Automatically push your accepted LeetCode solutions to GitHub with complete formatting preservation!
- π Automatic Push - Solutions are pushed to GitHub automatically when accepted
- π¨ Perfect Formatting - Preserves Python indentation and all code formatting
- π Rich Metadata - Includes problem description, difficulty, tags, and acceptance rate
- π Complete Capture - Reads the whole Monaco buffer, not just the lines on screen
- π Fails Loudly - Refuses to push rather than committing a partial file
- π Python-Optimized - Special validation for Python indentation and structure
- Go to: GitHub Settings β Tokens
- Click "Generate new token" β "Generate new token (classic)"
- Give it a name:
LeetCode Extension - Select scope: β
repo(Full control of private repositories) - Click "Generate token"
- COPY THE TOKEN immediately (you won't see it again!)
- Open Chrome and navigate to:
chrome://extensions/ - Enable "Developer mode" (toggle in top-right corner)
- Click "Load unpacked"
- Select the
leetcode_extensionfolder - The extension should appear in your extensions list
- Click the extension icon in Chrome toolbar (puzzle piece icon)
- Enter your details:
- Repository:
your-username/repo-name(e.g.,john/leetcode-solutions) - Token: Paste your GitHub Personal Access Token
- AI provider + key (optional): pick Groq (free, via console.groq.com) or OpenAI (via platform.openai.com) and paste that provider's key to enable the AI features below. Leave both blank and everything else still works exactly the same.
- Repository:
- Click "Save"
β You're all set! The extension is now ready to use.
- Navigate to any LeetCode problem (e.g., https://leetcode.com/problems/two-sum/)
- Write your solution in the code editor
- Click Submit button
- Wait for "Accepted" result
- Done! Check your GitHub repo - the solution is automatically pushed
For debugging or to see what's happening:
- Open DevTools (press
F12) - Go to Console tab
- Look for messages starting with
[LeetCode Extension]
Expected console output:
[LeetCode Extension] π Submit button clicked!
[LeetCode Extension] Code Extraction Summary: {method: "monaco-model-bridge", lines: 15, editorReportedLines: 15, ...}
[LeetCode Extension] Attempting to push to GitHub...
[LeetCode Extension] β
Successfully pushed to GitHub!
For each accepted solution, the extension creates a folder in your repository:
Make_Sum_Divisible_by_P/
βββ Make_Sum_Divisible_by_P.py
βββ README.md
Your complete code with:
- β Perfect indentation (especially important for Python!)
- β All lines in correct order
- β Proper file extension based on language
Auto-generated with:
- Problem title and description
- Difficulty level (Easy/Medium/Hard)
- Tags (Array, Dynamic Programming, etc.)
- Acceptance rate
- Link to original LeetCode problem
- List of solution files
Example README:
# Make Sum Divisible by P
Given an array of positive integers nums, remove the smallest subarray...
---
## Metadata
- Language: Python
- Difficulty: Medium
- Acceptance: 25.4%
- Tags: Array, Hash Table, Prefix Sum
- URL: https://leetcode.com/problems/make-sum-divisible-by-p/
## Files
- Make_Sum_Divisible_by_P.pyA small floating π€ button appears on every LeetCode problem page. Click it to expand a panel with two on-demand tools, powered by whichever provider you picked in the popup - Groq (free tier) or OpenAI:
- Analyze Complexity β reads whatever code is currently in the editor (draft or accepted, via the same Monaco-bridge extraction used for pushes) and returns its time and space complexity in Big-O notation with a short justification.
- Hint β gives a progressive hint for the current problem. Each click escalates: level 1 is a conceptual nudge, level 2 describes the general approach, level 3 adds detail on data structures and edge cases. It's capped at level 3 and never returns code or pseudocode, so it can't spoil the full solution. The level resets automatically when you move to a different problem.
This is entirely optional. If no key is configured for the selected provider, clicking either button just shows "<Provider> API key not set" in the panel β GitHub pushing, code extraction, and everything else keep working normally regardless.
Check the Service Worker console:
- Go to
chrome://extensions/ - Find "LeetCode to GitHub" extension
- Click "service worker" (blue link)
- Look for error messages starting with
[LeetCode Extension BG]
Common issues:
- β "Repo or token not set" β Configure extension via popup
- β "GitHub API failed (401)" β Invalid/expired token, create a new one
- β "GitHub API failed (404)" β Repository doesn't exist or wrong name format
- β "No pending submission found" β Must click Submit BEFORE solution is accepted
This was a real bug, fixed in v1.1. Monaco only keeps DOM nodes for the lines currently scrolled into view, and the old extractor scraped those nodes β so a file longer than the editor viewport was pushed truncated. v1.1 reads the editor's text model instead, via a MAIN-world bridge, and never scrapes the DOM.
If you are on v1.1 and nothing pushes at all, look for:
[LeetCode Extension] β Could not read the editor buffer: <reason>
| Reason | Meaning |
|---|---|
bridge-not-installed |
monaco-bridge.js did not load β reload the extension and hard-refresh the page |
monaco-not-loaded |
The editor had not mounted yet; resubmit |
no-model / empty-model |
No editor buffer found, or it was blank |
The extension deliberately pushes nothing in these cases rather than committing a partial file, because a truncated push looks like a successful one.
If Python code has no indentation, check console for:
[LeetCode Extension] β οΈ WARNING: Python code lacks indentation - may be corrupted!
Solution: Reload the extension:
- Go to
chrome://extensions/ - Click the reload icon β» on "LeetCode to GitHub"
- Refresh your LeetCode page (
Ctrl+Shift+R)
If you see:
[LeetCode Extension] β οΈ Could not detect language, defaulting to py (Python)
The extension will use .py as default. This is fine if you're coding in Python!
Checklist:
- β
Extension is enabled in
chrome://extensions/ - β You clicked Submit button (not just "Run")
- β Solution got "Accepted" status
- β Repository and token are configured in extension popup
- β
GitHub repository exists and token has
repopermissions
There is one extraction path, and it reads Monaco's text model β the editor's own source of truth. It is complete and correctly ordered by construction, regardless of scroll position.
Getting at it takes a bridge. Chrome runs content scripts in an isolated world:
they share the page's DOM but get their own JavaScript globals, so content.js
cannot see the page's monaco object (nor expando properties that page scripts set
on DOM elements). So:
monaco-bridge.jsis declared with"world": "MAIN"and runs in the page's own context, wheremonacois reachable. It listens for a DOM event and writes a JSON snapshot of the model into an inert<script type="application/json">node.content.js(isolated world) dispatches that event and reads the node. DOM event dispatch is synchronous and crosses the world boundary, so the snapshot is already fresh whendispatchEvent()returns β extraction stays a plain synchronous call.
When several Monaco instances are mounted (solution editor, diff views, playground), the bridge prefers a model attached to a visible editor, then the largest.
There is no DOM-scraping fallback, by design. Scraping .view-line nodes only
ever yields the lines on screen; committing that is worse than committing nothing,
because a truncated file looks like a successful push.
- Line Count Cross-Check: Warns if the snapshot disagrees with the model
- Python Validation: Verifies indentation and structure
- Completeness Check: Warns if code seems too short
- Submit Click: Captures problem metadata
- Accepted Detection: Extracts code using best available method
- Validation: Checks order, indentation, completeness
- GitHub API: Creates/updates folder with solution and README
- Confirmation: Logs success in console
- Supported Languages: Python, Java, C++, JavaScript, TypeScript, and all LeetCode languages
- File Naming: Problem title with underscores (e.g.,
Two_Sum.py) - Updates: Re-submitting updates the existing file (no duplicates)
- Privacy: Token is stored locally in Chrome storage only
node test/bridge.test.jsNo dependencies. The tests load monaco-bridge.js and content.js into separate
JS contexts sharing one DOM, mirroring Chrome's isolated/MAIN world split, and assert
that a 200-line file rendered 20 lines at a time is captured in full.
Found a bug or have a suggestion? Feel free to:
- Report issues
- Submit pull requests
- Suggest improvements
This extension is provided as-is for personal use.
Happy Coding! π
Made with β€οΈ for LeetCode enthusiasts