Debugging unfamiliar code
Trace a symptom from a support ticket to its root cause in a codebase you have never opened.
Open-source engineering practice
Interviews and real jobs are not about inverting binary trees. They are about stepping into code you did not write, understanding what is broken and fixing it so it stays fixed. Patchground gives you that practice: a real repository, a real ticket, your own editor and your own AI, and checks that run in Docker.
src/payments/How it works
A session goes the way real work does. You pick up a ticket, dig into a codebase you have never seen, prove the fix holds and get a record of what you actually did.
pgnd startYou get a real repository with a bug report or feature request, in a fresh workspace. The tests that decide the outcome stay hidden.
Read code you did not write, reproduce the problem and change it. Use your own editor and your own AI agent, or work without one.
pgnd checkRun the checks in Docker whenever you like, as many times as you need. Red turns green only when the behaviour is actually right.
pgnd submitYour work is frozen into a report you can trust: what passed, whether your test proves the fix and where your diff landed.
What you practise
Puzzles train you to recall algorithms. Patchground trains the habits that matter on a team and in a practical interview, and gives you evidence to show for them.
Trace a symptom from a support ticket to its root cause in a codebase you have never opened.
Extend existing behaviour without breaking what already works, so the old tests stay green.
Write a regression test that fails before your change and passes after. Patchground runs it on both versions to check.
Direct Claude Code, Codex, a local model or no tool at all. Then use the outcomes to check what it really changed.
Fix the problem in the right place. The report shows exactly which files your diff touched.
Every challenge has a realistic timebox. See how long you really took and how many hints you used.
What you walk away with
When you submit, Patchground freezes your workspace and computes a report from test runs alone. When it cannot prove something, it says so instead of guessing.
src/payments/Visible and hidden checks run fresh in Docker on your final code.
Your new test is run on the original code and on yours. It only counts if it catches the bug.
It flags deleted test files or functions and fewer assertions, so a fix can't pass by weakening tests.
It lists every file you changed and whether each one is in the area the ticket expects.
Elapsed time against the timebox, plus how many practice checks and hints you used.
Who it's for
Live debugging rounds and take-home feature tasks, rehearsed on real repositories against the clock instead of on puzzles.
Build the habit of reading before changing, of finding the right place for a fix, and of leaving the tests stronger than you found them.
Practise directing your agent on a realistic task, then check its work with tests, regression evidence and diff scope.
Why it exists
Live debugging, feature work in an unfamiliar repo, PR review, directing an AI tool under scrutiny. There was no free, structured way to rehearse any of it.
No account, server or subscription. Image builds may use the network; checks run on an internal Docker network with resource limits.
Use Claude Code, Codex, a local model, or nothing—in your own editor. Patchground needs no API key and has no built-in AI; what your assistant sees is up to you.
Every published challenge must prove, in its container, that the broken state fails and a reference fix passes—deterministically.
Challenges
Each one is a complete repository with a ticket, visible tests you can extend, hidden checks, and a reference fix—validated in Docker before it is published. A handful of excellent challenges beat fifty generated ones.
The catalog API rejects the last page of results whenever the result count is not a multiple of the page size. Find the root cause and fix it.
patchground-examplesbuilt-in
A TTL cache keeps entries alive when they are read, expires them one tick late and accepts nonpositive TTLs. Find the causes and fix them without changing write behavior.
patchground-examplesbuilt-in
OrderService imports and constructs SQLite and SMTP adapters itself, so nothing can be swapped for SMS or for fast tests. Introduce ports, inject the adapters and keep behaviour identical.
patchground-examplesbuilt-in
A strict CSV stock importer aborts at the first bad row. Add a non-strict mode that returns the valid items and one precise error per rejected row, keeping strict behavior unchanged.
patchground-examplesbuilt-in
A successful charge followed by a timeout causes a retry to charge twice.
patchground-examplesbuilt-in
A synchronous exact-topic event bus cannot take a subscription back or listen once. Add unsubscribe and once with precise snapshot, re-entrancy and error-collection behavior.
patchground-examplesbuilt-in
A release-tool library chooses the wrong latest version and misorders prereleases.
patchground-examplesbuilt-in
No challenge matches. Clear the search or pick another filter.
Difficulty and realism are not yet human-rated. Challenges marked AI-generated were drafted with a coding agent and validated like any other. built-in means shipped with the CLI and validated in this repository's CI; verified means a community pack whose every challenge passed pgnd validate in Patchground's CI on the date shown. Installing packs by name from the CLI is planned; today the CLI runs challenges from a local path or a pack URL. How to run one · Registry status
Packs
A pack is a git repository with a pack.yaml and one folder per challenge. It stays in its author's repo; Patchground only indexes it after re-validating every challenge in its own CI. Stars and forks come from the host.
Curated examples shipped with the CLI; validated in this repository's CI on every push.
No community pack has been verified yet. Publish yours and it will appear here after the next registry run.
Install
Patchground is an early, working release. Install it straight from GitHub: the curated challenges ship with the CLI, so there is nothing else to download. A PyPI package will follow.
uv tool install git+https://github.com/franndeli/patchground
pgnd doctor
pgnd list --builtin
pgnd start pagination-last-pagePublish your pack
Your challenges live in your own repository. Patchground discovers it, re-runs its validator on every challenge, and lists what passes. The validator is the gate: nothing else is reviewed by hand, and nothing that fails is listed.
pgnd new my-bug scaffolds a runnable challenge; pgnd validate my-bug proves the broken state fails, the reference passes, and the result is stable. Fix every step until it reads valid.
Put each challenge folder at the root of a public repository next to a pack.yaml that names it. Declare a content_license and provenance in every challenge.yaml; keep services: [].
spec_version: "0.1"
name: my-pack # lowercase, hyphens; first publisher keeps the name
version: 0.1.0
description: Bugs from a payments team
challenges: [my-bug]Add the GitHub topic patchground-pack to the repository. On other hosts, add your https:// clone URL to registry/sources.yaml. That is the whole submission.
Every few hours the registry clones tagged repositories, runs the policy checks and pgnd validate on each challenge in Patchground's CI, and publishes the result. Passing packs show up in the catalog with a verified badge; anything else is explained on the status page with the failing step.
Planned: pgnd pack publish to validate and tag in one command, and pgnd pack add <name> to install by name from this index. Until then the steps above are the whole process. The registry never lists hidden checks, hints or reference solutions; only the public metadata you see in the catalog. Authoring guide
Built in the open
Patchground is Apache-2.0. Sharpen a ticket, extend the validator, add a language adapter, or report what confused you on your first session.