A VS Code extension for competitive programming — scaffold problems from URLs, run tests against bundled cases, and commit with AI-generated messages, all without leaving the editor.
Note
This extension is primarily built for my personal use — a local environment to debug and implement competitive programming solutions from Kattis, Codeforces, and LeetCode. Kattis and Codeforces solutions still need to be manually submitted on each platform's official site; LeetCode can be submitted directly from the editor. A nice side benefit: committing solutions to a Git repo helps keep your GitHub contribution graph active.
Currently only Java is supported as the solution language. Support for other languages may come in the future.
If you find it useful, feel free to use it! Suggestions and new features are welcome via pull requests.
Check out cp-solutions-vault to see the extension in action with a real workspace.
- Scaffold a problem folder from a Kattis / Codeforces / LeetCode URL. Sample test cases are auto-fetched.
- Search LeetCode by title or keyword and pick a problem to scaffold.
- Test your
Solution.javawith one click on the editor toolbar (top-right of the editor). LeetCode problems are run on LeetCode's official judge. - Submit to LeetCode with one click on the editor toolbar — counts as an official submission, shows runtime / memory percentile.
- Commit with a Conventional-Commits message generated by Claude from your staged diff.
- LeetCode Daily Challenge widget in the sidebar — today's problem is one click away. Click to scaffold (or open if already done).
- Playground — a dedicated
playground/Playground.javafor ad-hoc Java experimentation. One click on the editor toolbar compiles and runs it.
Search for KestrelCP in the VS Code Extensions panel and click Install.
Or from the command line:
code --install-extension khoa-doan.kestrelcpAlternatively, .vsix builds are attached to GitHub Releases for manual installation.
- Python 3 with
requests,beautifulsoup4,anthropicpip3 install requests beautifulsoup4 anthropic
- JDK 17+ (
javacandjavaonPATH) - Anthropic API key for KestrelCP: AI Commit — store it via the command palette → KestrelCP: Set Anthropic API Key (saves to VS Code's encrypted SecretStorage, not plain settings.json). Or
export ANTHROPIC_API_KEY=sk-ant-…in your shell as a fallback. - LeetCode cookies (only if you want to run / submit LeetCode problems — scaffolding and search work without them). See LeetCode setup below.
-
Open VS Code on a folder — either an existing CP folder or a brand-new one.
-
First time only (required): run KestrelCP: Initialize Workspace from the command palette to create the
kattis/,codeforces/,leetcode/, andplayground/Playground.javascaffolding. All other commands require the workspace to be initialized first. -
Scaffold a new problem — three entry points, all via the command palette (Cmd+Shift+P):
- KestrelCP: New Problem — pick platform, paste the problem URL
- KestrelCP: Search LeetCode — type a title or keyword, pick from the results
- Click the LeetCode Daily Challenge entry in the KestrelCP sidebar to scaffold today's problem in one click
Solution.javaopens automatically once scaffolding finishes. For LeetCode, it's the exact starter code shown in LeetCode's web editor (correct method signature, helper class imports, etc.) — you fill in the method body. -
Solve it.
-
Run tests — click the ▶ button in the editor toolbar (top-right of the editor, visible whenever you're on a
Solution.java), or Cmd+Shift+P → KestrelCP: Run Tests for Current Problem.For Kattis / Codeforces, this runs
javac+javalocally against your*.in/*.outfiles. For LeetCode, this batches all*.infiles into one call to LeetCode's "Run Code" judge (the same one their web editor uses) and reports per-case PASS / FAIL. -
Submit (LeetCode only) — click the ☁️ button in the editor toolbar (only shown on a LeetCode
Solution.java), or Cmd+Shift+P → KestrelCP: Submit to LeetCode. Counts as an official submission and reports runtime / memory percentile. -
Commit — stage your files in the Source Control panel, then Cmd+Shift+P → KestrelCP: AI Commit. Claude proposes a Conventional Commit message; type
y/n/eto accept / abort / edit.
Need to try a snippet without scaffolding a whole problem? KestrelCP: Initialize Workspace also creates playground/Playground.java — a free-form Java scratchpad. Open it (e.g. Cmd+P → Playground.java) and hit the ▶ button in the editor toolbar to compile + run. Add helper classes alongside it (Helper.java, etc.) — javac *.java picks them up automatically; java Playground is the entry point.
The KestrelCP sidebar (cube icon in the activity bar) shows today's LeetCode Daily Challenge with its difficulty and acceptance rate. Click the row to scaffold it in one step; if you've already started it today, the click opens your existing Solution.java. The 🔄 button on the view title forces a re-fetch. No auth required for this — the daily-challenge endpoint is public.
Scaffolding LeetCode problems and searching the catalog work anonymously, but running tests and submitting require LeetCode's own session cookies — there is no public LeetCode API, so KestrelCP authenticates the same way your browser does.
One-time setup:
- Log in to leetcode.com in your browser.
- DevTools → Application → Cookies →
https://leetcode.com(Chrome / Edge), or Storage → Cookies (Firefox). - Copy the values of these two cookies:
LEETCODE_SESSION(long JWT, ~600 chars)csrftoken(~32 chars)
- Command palette → KestrelCP: Set LeetCode Cookies. Paste each value when prompted.
Cookies are stored in VS Code's SecretStorage (encrypted via the OS keychain), not in settings.json.
Expiry: LEETCODE_SESSION is a JWT that lasts about 2 weeks; csrftoken is effectively long-lived. KestrelCP decodes the JWT and refuses to make a doomed call when it's already expired — it tells you precisely which cookie to refresh:
- 🔑 "LEETCODE_SESSION expired on YYYY-MM-DD" → re-paste fresh cookies.
- 🛡️ "LeetCode rejected the csrftoken" → re-paste both (they're usually rotated together).
- ⏳ "LeetCode is rate-limiting" → wait a few seconds and try again.
To clear: run KestrelCP: Set LeetCode Cookies again and submit empty values for one or both prompts — empty input clears that secret.
| Command | What it does |
|---|---|
KestrelCP: Initialize Workspace |
Creates platform directories and playground/Playground.java. Required before using any other command. |
KestrelCP: New Problem |
Prompts for platform + URL, scaffolds the problem folder, fetches sample tests |
KestrelCP: Search LeetCode |
Searches LeetCode by title or keyword and scaffolds the picked problem |
KestrelCP: Run Tests for Current Problem |
For Kattis / Codeforces, compiles Solution.java and checks against every *.in / *.out. For LeetCode, runs the file on LeetCode's official judge via the "Run Code" endpoint (does not count as a submission). Only visible / runnable when a Solution.java is active. |
KestrelCP: Submit to LeetCode |
Submits the current LeetCode Solution.java for official judging. Reports verdict + runtime / memory percentile. Counts as a real submission. Only visible when a LeetCode Solution.java is active. |
KestrelCP: Set LeetCode Cookies |
Stores LEETCODE_SESSION and csrftoken in VS Code's SecretStorage (used by run / submit). Submit empty values to clear. See LeetCode setup. |
KestrelCP: Set Anthropic API Key |
Stores the Anthropic API key in SecretStorage (used by AI Commit). Submit empty to clear; otherwise the shell ANTHROPIC_API_KEY env var is used as a fallback. |
KestrelCP: Run Playground |
Compiles playground/*.java and runs Playground. Only visible when Playground.java is active. |
KestrelCP: AI Commit |
Generates a Conventional Commit message from staged changes via Claude (requires ANTHROPIC_API_KEY) |
| Setting | Default | Purpose |
|---|---|---|
kestrelcp.commitModel |
claude-haiku-4-5 |
Anthropic model used by AI Commit |
Sensitive values (Anthropic API key, LeetCode cookies) are not stored in settings — they live in VS Code's encrypted SecretStorage. Use the KestrelCP: Set ... commands to manage them.
KestrelCP invokes python3 directly — it expects Python 3 to be on PATH and will show an error on activation if python3 --version fails. Users with a virtualenv should activate it before launching VS Code.
- Scaffolding (Kattis / Codeforces) parses HTML with
requests+BeautifulSoupand writes one*.in/*.outpair per sample. - Scaffolding (LeetCode) uses LeetCode's public GraphQL endpoint to pull
exampleTestcases,codeSnippets(the editor's Java template), and the HTML problem statement. No auth needed for non-premium problems. - Testing (Kattis / Codeforces) runs
javac Solution.java, thenjava Solutiononce per*.inwith stdin redirected. Output is compared to the matching*.outignoring trailing whitespace and blank lines. 5-second timeout per case. - Testing (LeetCode) reads every
*.infor the problem, concatenates them into a singledata_input, and POSTs to LeetCode'sinterpret_solutionendpoint (the "Run Code" button). The judge runs every case in one container and returns parallelcode_answer/expected_code_answerarrays. End-to-end latency is typically ~1-2 seconds regardless of case count, since the cost is dominated by judge container spin-up.- For sample cases, KestrelCP honors LeetCode's overall verdict (
status_msg: "Accepted") even when string equality disagrees — so multi-valid-answer problems (e.g. two-sum returning[1,0]instead of[0,1]) don't get false FAILs. - For custom inputs (any
<N>.inyou add that LeetCode hasn't seen), there's no reference to compare against; the output is shown without a verdict so you can eyeball it. Local<N>.outfiles are deliberately not used for comparison.
- For sample cases, KestrelCP honors LeetCode's overall verdict (
- Submitting (LeetCode) POSTs to
/problems/<slug>/submit/and polls until the judge returns the verdict (Accepted / Wrong Answer / TLE / Compile Error / Runtime Error). On Accepted, reports the runtime and memory percentile. - AI Commit runs
git diff --staged, asks Claude for a one-line Conventional Commit message with an emoji prefix:
| Emoji | Type | When to use |
|---|---|---|
| ✨ | feat |
New solution or feature |
| 🐛 | fix |
Bug fix |
| 📝 | docs |
Notes / README update |
| ♻️ | refactor |
Rewrite without changing behavior |
| ✅ | test |
Adding or fixing test cases |
| 🔧 | chore |
Tooling, config, scripts |
| ⚡️ | perf |
Performance improvement |
| 💄 | style |
Formatting only |
Confirm with y (accept), n (abort), or e (edit before committing).
Working on the extension itself? Head to the GitHub repo for the dev loop, manual test plan, scraper canary, and release process.
MIT — see LICENSE.