Deterministic offline contract verification for the RunSteward execution lifecycle
Project description
RunSteward
RunSteward is for developers who hand Claude Code (or OpenAI's Codex CLI) work that takes longer than one sitting (big refactors, migrations, overnight builds) and can't sit there watching it. It bundles the tools that keep that work moving unattended: queue tasks with a spending cap, checkpoint progress, resume automatically when a usage limit resets, and read a reviewable summary of what happened in the morning. Without it, hitting a usage limit mid-task means coming back to a stopped session with half-applied edits and no record of what was done or what to do next.
Getting started
- Prerequisites: Node 18 or newer. Claude Carry, the bundled overnight runner, runs straight on Node with no extra dependencies. On Windows, clone to a short path and turn on long paths first, because a few fixture filenames are long (exact command in the Windows note below).
- Install: RunSteward is not on npm or PyPI, so you run it from a clone. Run
git clone https://gitlab.com/krahul02004/RunSteward.gitandcd RunSteward. The Node surfaces, including Claude Carry, run straight from the checkout with nonpm install. Fuller setup (and the optional Python contract verifier) is under Install. - Check it works: from the checkout, run
node packages/claude-carry/bin/carry.mjs doctor. It prints one line per check and finishes withAll 7 checks passed.
30-second demo
Queue a task for Claude Carry, the overnight runner bundled in this repo. From your project folder, in a checkout:
node packages/claude-carry/bin/carry.mjs add "refactor the auth module into smaller files" --goal "npm test passes" --budget 5
queued t1: refactor the auth module into smaller files
done when: npm test passes
model: sonnet (default) budget: $5
work: branch carry/t1 in your project (shows in Source Control)
in: X:\my-app
That task now waits in a plain-JSON queue. carry run --until-idle starts the night shift: each
task runs as headless Claude Code on its own carry/<id> branch, capped at its budget, with
guardrails that park risky actions for your approval instead of doing them. If your usage limit
hits, the runner reads the exact reset time from Claude Code's own event stream, wakes the PC at
that moment (on Windows), and resumes the same session. In the morning, carry handoff prints what
got done, what's parked for approval, and which branches to review. The full walkthrough is in
Claude Carry's README.
What's inside
Three working products, plus the shared core being built underneath them.
The products
| Product | What it does for you |
|---|---|
Claude Carry (packages/claude-carry/) |
Runs queued Claude Code tasks overnight: per-task budgets, an allow/deny guardrail set, automatic resume when your usage limit resets (including waking the PC), and a morning handoff. Can also adopt your live session so it continues by itself after a reset. |
Limit-Aware Wrapup (packages/limit-aware-wrapup/) |
Ends a Claude Code session gracefully instead of mid-edit: watches your 5-hour and weekly usage windows and, just before the budget runs out, has the session commit its work-in-progress, write a handoff note, and stop clean. Silent the rest of the time. |
Codex Nightwatch (packages/codex-nightwatch/) |
The same overnight discipline for OpenAI's Codex CLI: reads codex exec --json event streams, applies your token thresholds, checkpoints, stops on policy, produces a safe resume command and a morning report. |
Each product keeps its own README, tests, changelog, and backlog.
The shared core
The @runsteward/* packages are the provider-neutral engine being extracted from those products:
implemented and fully tested, but not yet switched on as the runtime that drives them
(see Status).
| Package | What it's for |
|---|---|
@runsteward/core (packages/runsteward-core/) |
Defines how a run is recorded, scheduled, checkpointed, resumed, and proven finished: the contracts and invariants everything else consumes |
@runsteward/cli (packages/runsteward-cli/) |
Lists and describes the sixteen planned run-management skills (queue, adopt, checkpoint, wrap, resume, report, …); it routes and describes but executes nothing yet |
@runsteward/sensor-claude-limits (packages/runsteward-sensor-claude-limits/) |
Turns Claude usage-window percentages into typed evidence the core can consume |
@runsteward/sensor-codex-usage (packages/runsteward-sensor-codex-usage/) |
Turns Codex token usage into typed evidence the core can consume |
@runsteward/adapter-claude-code (packages/runsteward-adapter-claude-code/) |
Thin binding from the core's checkpoint/wrap/resume contracts to Claude Code |
@runsteward/adapter-codex (packages/runsteward-adapter-codex/) |
Thin binding from the core's checkpoint/wrap/resume contracts to Codex |
A few core modules validate decision receipts from ChoiceGate, a companion selection tool that
lives outside this repository; that boundary is documented in
docs/architecture.md.
How it works
Three ideas carry most of the engineering:
- Runs are digest-linked event chains. Every lifecycle fact (queued, running, checkpointed, stopped, …) is an ordered JSON event carrying a deterministic digest (a hash of the exact canonical bytes) linked to the previous event's digest. A run's current state is only accepted if it is the replay of one complete, unbroken chain, so any machine can verify what happened.
- Resume requires a checkpoint and a lease. A checkpoint captures everything needed to pick a run back up (branch, worktree, session identity); a lease is an exclusive, epoch-numbered claim on that run's branch and worktree. Two runners can never grab the same task, and a crashed run can be resumed without guessing.
- Everything fails closed. When evidence is missing, stale, or ambiguous, the core refuses to act rather than act on a guess: an unattended runner that guesses can destroy work while you sleep. The same rule shows up product-side as Claude Carry's guardrails and Limit-Aware Wrapup's do-nothing-if-unsure sensor.
Deeper reading: docs/architecture.md (layer and boundary index),
contracts/README.md (contract map and digest rules),
docs/contracts.md (lifecycle semantics).
Install
The repository root builds as the Python distribution runsteward, which packages the offline
contract verifier. It is not yet on PyPI; install from a clone:
git clone https://gitlab.com/krahul02004/RunSteward.git
cd RunSteward
pip install .
runsteward-verify-contracts --root .
Windows note: some fixture filenames are over 100 characters, so a deep clone destination can push full paths past Windows' default 260-character limit, which breaks the clone ("Filename too long") and, later, the verifier. Clone to a short path (e.g.
C:\src\rs) and enable long paths:git clone -c core.longpaths=true https://gitlab.com/krahul02004/RunSteward.git.
runsteward-verify-contracts replays the full contract verification (every schema, frozen
fixture, and digest vector under contracts/) against the checkout, entirely offline. The
distribution also builds offline (python -m build --no-isolation, then python -m twine check dist/*).
The Node surfaces run straight from the checkout, with no npm install:
node packages/claude-carry/bin/carry.mjs doctor # Claude Carry health check
node packages/runsteward-cli/bin/runsteward.mjs list-skills
Claude Carry's one-time setup (installs the standalone Claude Code CLI if missing) is
packages/claude-carry/setup.ps1.
Run the tests
All validation is deterministic and offline:
node packages/runsteward-core/scripts/run-all-tests.mjs
node --test tests/runsteward-atomic-family.test.mjs
The first command runs fixture validation, the Python contract-compatibility verifier, and every package-level Node test suite. The second validates the sixteen-skill definition surface.
Status
The three bundled products are working, tested tools; the shared core underneath them is implemented and fully tested, but not yet switched on as the engine that drives them. The precise integration state and the gates before activation are in STATUS.md.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
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 runsteward-0.1.0.tar.gz.
File metadata
- Download URL: runsteward-0.1.0.tar.gz
- Upload date:
- Size: 15.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
641430d3034cf705256f4fa779fbaffee9efa24e5a13bbf42d889d564d197a7c
|
|
| MD5 |
cbefb572e25a3a946e74f2bc0211f7eb
|
|
| BLAKE2b-256 |
cf55610bf64939366c625e7d98b7aa61c8b5c65860639ce8084d33761755533e
|
File details
Details for the file runsteward-0.1.0-py3-none-any.whl.
File metadata
- Download URL: runsteward-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2941d90f003104b18eeb4865da3e755def29264a9b8c2d4f398ea0e125d1cc8d
|
|
| MD5 |
5e0ef02e45af5f0749c47104cf18f6d9
|
|
| BLAKE2b-256 |
89e3b1c2e64029e527342b116e0bf9bb1c91ac02e7adff6fe69207af03d9dfc2
|