cursorloop
Onion-architected, autonomous Cursor Agent session runner — Composer-first
(composer-2.5; Grok is a secondary model profile, not a product). Never
blocks on a human, distinguishes a waitable rate-limit window from
non-waitable exhausted credits, and resumes safely across usage windows.
What problem this solves
Cursor Agent sessions hit usage limits. A single agent turn ending doesn't
tell you whether the task finished or just that turn did. And when
Cursor rejects you, you can't tell from the outside whether waiting will
ever help — a rate-limit window resets on its own; an exhausted credits
balance never will, no matter how long you wait. Cursor does not publish a
stable credits discriminator on its RateLimitError, so cursorloop keeps a
configurable billing lexicon and, when a signal is ambiguous, biases toward
CreditsExhausted — the failure mode is a spurious "top up" notification,
never a hang past a fabricated reset.
cursorloop exists to get all three of those distinctions right,
automatically, so you can hand it a plan and walk away.
It is a deliberate transplant of the claudeloop
design — same state machine, same ports, same run-directory layout —
retargeted onto the Cursor Agent SDK (cursor-sdk). There is no Anthropic
dependency and no foreign vendor auth env fallback.
Install
Requires Python 3.12+, macOS or Linux, and a Cursor account with
CURSOR_API_KEY set for live runs. Windows is not a supported target.
pipx install cursorloop
cursorloop doctor # --offline skips the live me / models calls
See the installation guide for a from-source setup.
Quickstart
cursorloop doctor # fail-fast preflight before a multi-hour unattended run
cursorloop run --plan plan.md # seed a Cursor Agent from a plan and run to completion
cursorloop resume --agent-id <id> # continue an existing agent
cursorloop models # composer-fast → composer → grok-4.5 → grok → grok-xhigh, plus router-* aliases
cursorloop agents # local agents for a workspace (needs a live client)
cursorloop whoami # authenticated Cursor account
# Mid-run control (second terminal, same cwd):
cursorloop status
cursorloop logs
cursorloop prompt "Also cover the error path" # queued for the next turn
cursorloop watch # plain-text tail; --ui opens the Textual view
cursorloop hooks status # install | restore | diff the autonomy fragment
cursorloop stop # soft stop
cursorloop wind-down # finish the turn, write a handoff marker, exit 75
cursorloop savepoints
cursorloop unwind --to <sha-or-ref>
cursorloop reset # restore managed hooks after a crashed run
cursorloop cloud me|models|create|get|cancel is a partial Cloud Agents
REST surface (ADR-0006);
full generation waits on a digest-stable published OpenAPI document.
Why it's different from just retrying on 429
| Naive retry | cursorloop |
|
|---|---|---|
| Sees a rate-limit error | Sleeps a fixed duration, retries | Classifies why — a waitable window (bounded probe under --max-wait) or exhausted credits that only a human can fix; ambiguity resolves toward credits (ADR-0005) |
| Credits exhausted | Sleeps forever, no reset time exists | CreditsExhausted has no resets_at. Probes on a bounded backoff and tells you it needs you |
| Vendor changes an error string | Silent misclassification | Configurable billing lexicon; unmatched terminal errors land in the audit log; doctor --explain-error <payload> classifies them offline (ADR-0004) |
| Turn ends vs. task ends | A marker string, easily confused with a truncated limit message | Four-tier verdict: a cursorloop-verdict fenced block, done marker (CURSORLOOP_TASK_FULLY_COMPLETE), empty-turn soft-fail, plan-checkbox reconciliation. A capacity rejection outranks any completion claim |
| Agent asks a question | Hangs — Cursor has no can_use_tool callback |
Managed .cursor/hooks.json autonomy fragment + preamble + local.force + a stall watchdog. Hooks are hash-verified and restored afterward; a mid-run user edit wins (ADR-0008) |
See rate limits and credits and never blocking for the full reasoning.
Documentation
Full docs (built with MkDocs Material) live at
https://adammatthewsteinberger.github.io/cursorloop/. The same content
is in the docs/ directory on GitHub.
| Getting started | Install, quickstart, configuration |
| Guides | Autonomous runs, rate limits and credits, never blocking, completion detection, model profiles, logging, cloud agents |
| Architecture | The onion layers, the domain model, the run-loop state machine, and ten decision records |
| CLI reference | cursorloop --help and cursorloop --man |
| Contributing | Development setup, testing, docs, release |
| Plans | Design record, vendor research notes, and the shared transplant outline (GitHub tree; not in the site nav) |
| Changelog | Release notes, maintained by release-please |
Project status
Pre-1.0, but functional through the M5 milestone: Typer CLI (run /
resume / doctor / mid-run control), bootstrap that auto-launches
CursorClient.launch_bridge, a full offline-capable doctor checklist, a
deterministic pytest -m system harness (scripted agent, no Cursor account),
a partial-but-live Cloud Agents surface, a CLI-fallback gateway, and mirrored
agent skills. Later releases added the -v/-q verbosity ladder, --run-id,
wind-down, and capacity forecasting (measurement only, off by default).
Coverage floor is 100% on every layer — domain, application,
infrastructure, and CLI.
| Item | Value |
|---|---|
| Env prefix | CURSORLOOP_* |
| Auth | CURSOR_API_KEY (never an ANTHROPIC_* fallback) |
| State dir | .cursorloop/runs/<run_id>/ |
| Done marker | CURSORLOOP_TASK_FULLY_COMPLETE |
| Model ladder | composer-fast → composer → grok-4.5 → grok → grok-xhigh (or router-cost → router-balanced → router-intelligence); default composer-2.5 |
| Test-agent gate | CURSORLOOP_ALLOW_TEST_AGENT=1 and CURSORLOOP_TEST_AGENT_SCRIPT=<path> |
Contributing
Contributions are welcome — see CONTRIBUTING.md for the gitflow branch model, Conventional Commits requirement, and how to run every quality gate locally.
The GitHub default branch is develop. Open feature PRs into develop.
By contributing you agree that your work is licensed under the same MIT
License as the rest of this repository, and that you will follow the
Code of Conduct.
Agent guidance is mirrored across:
- CLAUDE.md +
.claude/skills/(Claude Code) - CURSOR.md +
.cursor/rules/(Cursor) - AGENTS.md +
.agents/skills/(Codex) - GEMINI.md +
.agent/rules/(Antigravity)
Getting help
| I want to... | Go here |
|---|---|
| Read the docs | https://adammatthewsteinberger.github.io/cursorloop/ |
| Ask a question | Discussions |
| Report a bug or request a feature | Issues (use the templates) |
| Report a vulnerability | SECURITY.md (private) |
See SUPPORT.md for the same map.
Security
This tool merges an autonomy fragment into .cursor/hooks.json for the
duration of a run (restored afterward, hash-verified), edits the working tree
without waiting on a human, and handles CURSOR_API_KEY. See
SECURITY.md
for the threat model and how to report a vulnerability.
Related projects
Same contract, different vendor. The four *loop runners share one domain
state machine, one set of application ports, and one .<name>loop/runs/<id>/
layout — pick the one that matches the agent you pay for:
| Runner | Drives | Install |
|---|---|---|
| claudeloop | Claude Code (Anthropic) | pipx install claudeloop |
| codexloop | OpenAI Codex / GPT | pipx install codexloop |
| cursorloop (this repo) | Cursor Agent (Composer-first; Grok as a model profile) | pipx install cursorloop |
| agyloop | Google Antigravity / Gemini | pipx install agyloop |
Around them:
- vibey — queue-based, six-phase conductor (spec interview → design → build → review → deploy) that drives the four runners as interchangeable engines. PostgreSQL-backed.
- vibey-bootstrap — Azure Functions cross-cutting layer: App Config + Key Vault + App Insights bootstrap, Service Bus plumbing, scaffold CLI.
- vibey-skills — versioned Agent Skills marketplace and deterministic context-packet engine.
- homebrew-tap —
brew tap adammatthewsteinberger/tap.
License
MIT — see LICENSE.
Built by Adam Matthew Steinberger · more open source
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cursorloop-0.7.0.tar.gz.
File metadata
- Download URL: cursorloop-0.7.0.tar.gz
- Upload date:
- Size: 405.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c0bbb49f72276f0d95aa4b0a589e961d6f16bc5208863de91c77f50d3a73b39
|
|
| MD5 |
7caf89762e8d8d4b59b8406ca4ac1cfe
|
|
| BLAKE2b-256 |
925f7103d0c354aa6ded3fc4283ff014f049992aebcb3fcfeb188b51443f3dbf
|
Provenance
The following attestation bundles were made for cursorloop-0.7.0.tar.gz:
Publisher:
release.yml on adammatthewsteinberger/cursorloop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cursorloop-0.7.0.tar.gz -
Subject digest:
2c0bbb49f72276f0d95aa4b0a589e961d6f16bc5208863de91c77f50d3a73b39 - Sigstore transparency entry: 2619466586
- Sigstore integration time:
-
Permalink:
adammatthewsteinberger/cursorloop@de88665656880be6941337ea63fc1815f8fdb2a8 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adammatthewsteinberger
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@de88665656880be6941337ea63fc1815f8fdb2a8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cursorloop-0.7.0-py3-none-any.whl.
File metadata
- Download URL: cursorloop-0.7.0-py3-none-any.whl
- Upload date:
- Size: 123.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
edcecb7493a24b98b698c9bed9906e7537390e097953db2637ea399a12e00e34
|
|
| MD5 |
275da8f92d73a0236ee32d66052254cc
|
|
| BLAKE2b-256 |
be62e2b2863a84a4e33a35d8741caa5d6b2439b42b7fdca494415cf6fbc84609
|
Provenance
The following attestation bundles were made for cursorloop-0.7.0-py3-none-any.whl:
Publisher:
release.yml on adammatthewsteinberger/cursorloop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cursorloop-0.7.0-py3-none-any.whl -
Subject digest:
edcecb7493a24b98b698c9bed9906e7537390e097953db2637ea399a12e00e34 - Sigstore transparency entry: 2619466617
- Sigstore integration time:
-
Permalink:
adammatthewsteinberger/cursorloop@de88665656880be6941337ea63fc1815f8fdb2a8 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adammatthewsteinberger
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@de88665656880be6941337ea63fc1815f8fdb2a8 -
Trigger Event:
push
-
Statement type: