Skip to content

Free and open sourceGet it running

How it works

The arithmetic, written out.

Nothing here is a secret, and a lock you cannot reason about is a lock you will resent. Every threshold below is the default the code actually ships with.

01 / The lock

Nothing local decides.

You arm a timer. The server records the deadline, and every client renders its countdown from the server's clock rather than the machine's — so moving your system time buys nothing.

The problem is chosen when the timer fires, not when you arm it. Otherwise you could read it during the focus block, which defeats the point.

When you pass, the API issues a short-lived token signed against one user and one session. The desktop shell verifies that signature in its main process with a key the page cannot read. A patched front end, an injected script, or the console calling the unlock channel by hand all fail the check, and the overlay stays.

02 / The speed gate

Correct, and fast.

The part people find surprising, and the reason a working answer can leave you locked.

budget = ceil(best × 1.35) + 40ms

best = fastest accepted runtime for this problem, in your language

Where your number comes from. Your code runs the whole suite twice. Within one run, the slowest test case is that run's time — a solution is only as fast as its worst input. Between runs, the faster one counts, so a scheduler hiccup does not cost you the session.

Timing happens inside the container. Measuring around docker run would include half a second of image start-up that varies more than the algorithmic difference the gate exists to detect — enough to make an O(n) and an O(n²) answer indistinguishable.

The 40ms floor is not padding. On a problem whose best answer takes 8ms, a 35% tolerance is a 3ms band — narrower than the judge's own jitter. The floor keeps fast problems winnable.

The bar moves. When someone posts a faster accepted answer it becomes the new best, and the budget tightens for everyone, including them.

Tolerance
1.35 — you may be 35% slower than the best known answer
Floor
40ms — added to every budget
Runs
2 — the faster one counts
Within a run
The slowest test case is your time
Watch it reject a working solution →

03 / Difficulty

Two rules, both visible.

Three fast solves in a row moves you up.
A solve counts as fast when you finish inside the problem's own average solve time. The streak is consecutive — one slow solve puts it back to zero, and the counter in the app shows exactly where you stand.
Two failed sessions in a row moves you down.
Giving up counts as a failure, and so does the desktop kill switch. Easy is the floor; you cannot fall off the bottom.
Changing tier resets both counters.
A streak belongs to the tier it was earned at. Arriving at Hard with two fast solves banked would promote you out of it on your first success there.

That is the entire ladder. It is a pure function of your history with no I/O and no model, which is why the interface can always tell you what would happen next rather than showing a score you cannot interrogate.

04 / Data

What leaves your machine.

A tool that interrupts your work has to be specific about this. CodeLock can only see its own window — it has no view of your other apps, and no keylogger.

Your submitted code
server
Sent to the API and run in a throwaway container with no network. Stored against your account so your history is readable later.
Session times and verdicts
server
Stored server-side. They are what the difficulty ladder is computed from.
Your access token
stays local
Held in browser local storage and sent only to the CodeLock API. On desktop the unlock key lives in the main process, where the page cannot read it.
Which apps you use, what you type elsewhere
stays local
Never collected. CodeLock cannot see outside its own window.
Accepted solutions
third party
Pushed to a GitHub repository you nominate — only if you connect it, and only on a pass.
Your LeetCode username
third party
Sent to LeetCode to read your public profile — only if you link it. Nothing about your CodeLock activity goes the other way.

No analytics, no third-party trackers, no cookies. Error reporting is off unless whoever runs your instance turns it on, and a self-hosted install sends nothing at all. The full statement is on the privacy page.

05 / Integrations

Both optional, both narrow.

GitHub

Accepted solutions are committed to a repository you nominate, so a month of locks leaves something behind. CodeLock asks for public_repo and never requests access to private repositories.

Your token is encrypted at rest with AES-256-GCM under a key held in the server's environment, never beside the ciphertext — a database dump on its own is not enough to use it.

A failed push never keeps you locked. The commit is attempted after the unlock token has already been issued, and a GitHub outage is logged and dropped rather than propagated.

LeetCode

Link a username and CodeLock reads your public profile to seed a starting difficulty, so you are not made to grind Easy problems you solved years ago.

It is read-only and one-directional: nothing about your CodeLock sessions is sent to LeetCode. The endpoint is unofficial and occasionally changes, so the last successful snapshot is cached and shown with its age when it breaks.

Now go and see it refuse a working answer.