Small task β giant diff.
Scope contracts for coding agents. ChangeBudget records what a task is allowed to change, inspects the real Git state, and reports whether the result is inside the approved boundary.
No cloud policy engine. No telemetry. No LLM required at runtime.
π Quick Start β’ π Update β’ π» Show Me Code β’ π€ Agent Discovery β’ π§ How It Works β’ πΊοΈ Roadmap
A small request can become a large, difficult-to-review diff:
Task:
"Add an empty state to the player"
Expected:
3 files
~100 lines
Agent result:
17 files
new dependency
navigation refactor
configuration changes
full-project cleanup
The agent may produce valid code and still exceed the change the developer intended.
ChangeBudget turns the intended scope into a Change Contract, then compares the repository's actual Git changes with that contract.
Task
β
Change Contract
β
Agent implements
β
Git inspection
β
Deterministic rules
β
PASS / REPAIR / HUMAN_REVIEW
The agent proposes code. The developer owns the boundaries.
ChangeBudget is deterministic, local-first, Git-backed, explainable, and usable without an LLM. Git and explicit ChangeBudget rules decide compliance; the LLM uses the framework but does not control its policy.
The recommended first run is three separate steps.
npm install -g changebudgetChangeBudget is installed from the npm registry. To install a specific published release, use its exact version:
npm install -g changebudget@VERSION --registry=https://registry.npmjs.org/From the target Git repository:
changebudget integrate opencodeThis creates or updates exactly one project-local OpenCode V2 resource:
.opencode/plugins/changebudget.js
The marked wrapper is loaded automatically by OpenCode V2. The plugin adds the ChangeBudget workflow to the session context and evaluates permissions through the native context and evaluate hooks. The command never creates or edits opencode.json, instruction files, or AGENTS.md; the core CLI remains independent of OpenCode.
Open OpenCode and describe the task normally:
Implement T031
or:
Add pagination to the users endpoint. Keep the change minimal.
That's it. OpenCode V2 loads the project-local plugin automatically, so the coding agent receives the ChangeBudget workflow through the session context. This automatic discovery currently refers specifically to OpenCode; it is not a claim that every model or coding tool supports it.
To inspect command syntax without executing a command, run changebudget <command> --help or changebudget help <command>.
changebudget update discovers published versions from the npm registry and installs only a newer compatible release in the installed major line. It installs the selected release by exact version and reports real installation start and result status without estimating progress. If the current release is already up to date, it safely refreshes only an existing managed OpenCode integration in the current project. If a newer major version is reported and automatic installation is refused, it still safely refreshes an existing managed OpenCode integration.
changebudget updateAfter a successful compatible update, ChangeBudget automatically refreshes a managed stale OpenCode V2 wrapper in the current project. Projects with no wrapper or a user-owned conflict are not changed automatically.
For a first-time setup, or to explicitly action an integration, run:
changebudget integrate opencodeUse changebudget integrate opencode --dry-run to preview the explicit integration action. The command manages only its marked wrapper and leaves unrelated project files untouched.
To only check for a new update without installing it:
changebudget update --checkThis queries the npm registry and reports the installed version, the latest compatible version, and whether an update is available. It makes zero writes and does not inspect or modify the target project.
The developer gives the implementation request. The integrated coding agent handles the ChangeBudget ceremony according to the workflow delivered through the OpenCode V2 session context, while the developer keeps authority if more scope is required.
The following is an illustrative workflow, not a promise of fixed prose output:
You:
"Implement T031"
Agent:
- runs `changebudget status`
- if the repository is uninitialized, runs `changebudget init` and checks status again
- if no contract is active, runs `changebudget diagnose T031`
- starts the appropriate contract, such as `changebudget start T031 --tiny`
- implements the task and runs targeted validation
- runs `changebudget check`
- repairs an in-scope violation without widening the contract
- runs `changebudget close` only after validation and PASS
For a project without Spec-Kit:
You:
"Add pagination to the users endpoint. Keep the change minimal."
Agent:
- checks ChangeBudget state
- establishes the appropriate contract
- implements only within the approved scope
- validates the implementation
- runs `changebudget check`
- closes the contract only after PASS
changebudget integrate opencode creates the project-local OpenCode V2 plugin wrapper, which makes the workflow explicit to the coding agent:
Developer integrates once
β
changebudget integrate opencode
β
Native V2 plugin wrapper + Runtime Guard
β
OpenCode loads the plugin
β
Session context receives the ChangeBudget lifecycle
β
status β diagnose/start β implement β check β close
The plugin's session context tells the agent to:
Before implementation
- run
changebudget status; - if the repository is uninitialized, run
changebudget initand check status again; - start a contract if none is active;
- for a Spec-Kit
Txxxtask without an explicit budget, runchangebudget diagnose Txxx; - never widen a contract automatically; wait for explicit developer approval before adding each exact literal path with
changebudget amend --allow-path <path> --reason <reason>, then runchangebudget checkand ask again for any further scope. The CLI cannot cryptographically distinguish a human from an agent; its technical guarantees are an explicit amendment request, exact literal path, non-empty reason, and path safety invariants.
During implementation
- stay inside allowed paths;
- never manually modify
.changebudget/**; - respect protected and denied paths.
After implementation
- run targeted validation;
- run
changebudget check; - repair violations without widening the contract;
- run
changebudget closeonly after validation succeeds.
There is no special ChangeBudget model, no required prompt to paste every session, and no persistent model memory involved. The integration is project-local and idempotent. ChangeBudget can also be used manually or by another coding agent capable of invoking commands. Automatic workflow discovery documented here targets OpenCode only; support for Cursor, Claude Code, Copilot, Aider, or other agents is not implied.
flowchart LR
A[Developer task] --> B[Change Contract]
B --> C[Coding Agent]
C --> D[Repository changes]
D --> E[Git inspection]
E --> F[ChangeBudget rules]
F --> G{Decision}
G -->|PASS| H[Continue]
G -->|REPAIR| I[Bring changes back in scope]
G -->|HUMAN_REVIEW| J[Developer decides]
The enforcement core is intentionally simple:
Git + explicit rules + deterministic evaluation
The diff is the source of truth, not the agent's description of what it changed. ChangeBudget can evaluate staged, unstaged, untracked, deleted, renamed, and binary Git changes. Its own .changebudget/** metadata is excluded from the user budget.
Repository state satisfies the active contract.
A deterministic violation exists. Bring the implementation back inside the already-approved contract.
Developer authority is required because ChangeBudget cannot safely continue under the current contract or environment. HUMAN_REVIEW is not authorization to amend or widen a contract.
ChangeBudget never automatically widens a contract, raises a budget, rewrites permissions, reverts work, or deletes user files. REPAIR and HUMAN_REVIEW report a decision; neither grants authority to amend or widen a contract.
| Decision | Exit code |
|---|---|
PASS |
0 |
REPAIR |
1 |
HUMAN_REVIEW |
2 |
| Guard | What it controls |
|---|---|
| Allowed paths | allow_paths controls WHERE a task may touch existing repository paths; an allowed path does not grant file-creation permission |
| Denied paths | Protected paths that remain unavailable |
| Maximum files | The number of changed files |
| Maximum lines | Added plus deleted lines |
| New files | allow_new_files controls WHETHER file creation is allowed; it defaults to false, including for paths allowed by allow_paths, unless --allow-new-files is set |
| Dependencies | Dependency-sensitive changes |
| Migrations | Migration paths and changes |
| Configuration | Configuration-sensitive files |
| Public API | Explicitly classified API-sensitive files |
| Stack policies | Android, Flutter, Spring Boot, and Node/TypeScript rule packs |
| Spec-Kit tasks | Deterministic association with Txxx tasks |
| Runtime Guard | Optional project-local OpenCode allow / ask / deny behavior |
| Diagnose advisor | Read-only budget recommendation before implementation |
allow_paths controls WHERE changes may occur. allow_new_files controls WHETHER a new file may be created. An allowed path does not imply permission to create a new file. New file creation defaults to false unless --allow-new-files is set.
| Command | Purpose |
|---|---|
changebudget init |
Initialize ChangeBudget state in the current Git repository |
changebudget diagnose |
Recommend a deterministic budget before implementation |
changebudget start |
Open a Change Contract |
changebudget status |
Inspect lifecycle state and the active contract |
changebudget check |
Compare real Git changes with the active contract |
changebudget close |
Close a validated contract |
changebudget amend |
Amend numeric budgets or developer-authorized literal paths |
changebudget integrate opencode |
Install or update project-local OpenCode integration |
changebudget update --check |
Check for a compatible ChangeBudget update |
changebudget update |
Install a newer validated compatible ChangeBudget release |
Useful options include --json for check, status --budget, and diagnose; contract presets --tiny, --normal, and --free; --allow-path, --deny-path, --max-files, --max-changed-lines, and --stack-profile; and integrate opencode --dry-run or --remove.
ChangeBudget policy and the OpenCode Runtime Guard are separate layers:
| ChangeBudget policy | Runtime Guard action |
|---|---|
| Deterministic contract evaluation | Runtime allow, ask, or deny behavior |
PASS |
Allow known in-scope work |
| Risky or unresolved context | Ask when explicit review is appropriate |
REPAIR, unsafe mutation, or protected state |
Deny or block |
The project-local Runtime Guard can allow known in-scope writes, ask again for risky operations, deny protected paths, protect .changebudget/**, and fail safely when a mutation target cannot be resolved. It remains local and is not an operating-system sandbox.
The normal installation path is changebudget integrate opencode; users do not need to hand-write a plugin wrapper. The compiled plugin must exist, so a source checkout should run npm run compile first.
ChangeBudget can associate a contract with an existing Spec-Kit task without replacing or modifying Spec-Kit:
changebudget diagnose T031
changebudget start T031 --tinyTxxx resolution is deterministic. Task metadata is captured when the contract starts. ChangeBudget never modifies tasks.md, marks tasks complete, invokes /speckit.*, or treats PASS as proof that a Spec-Kit task is complete.
Task lines may define a default:
- [ ] T031 [budget:tiny] Implement task bridgePrecedence is deterministic: explicit CLI budget, then task [budget:...] default, then normal contract behavior. Projects without Spec-Kit work normally.
diagnose is a deterministic, read-only advisor based on observable repository and task evidence. It is not an LLM, does not enforce the result, and cannot widen an active contract.
Possible recommendations are tiny, normal, free, or manual review:
changebudget diagnose --allow-path "src/player/**"
changebudget diagnose T031 --jsonIt does not create contracts, modify .changebudget/**, modify project files, modify Spec-Kit tasks, or invoke OpenCode.
Stack policies are deterministic rule packs, not semantic AI analysis. Current profiles are:
- Android: Gradle, manifests, signing, release, and protected configuration surfaces.
- Flutter:
pubspec, analysis configuration, platform, and release surfaces. - Spring Boot: Maven/Gradle dependencies, application configuration, and migration paths.
- Node / TypeScript:
package.json, lockfiles, TypeScript configuration, and selected public API surfaces.
Select a profile when starting a contract:
changebudget start --task "Update application config" --base-revision HEAD --stack-profile spring-boot --max-files 5 --max-changed-lines 150Repository overrides live in .changebudget/stack-policy-overrides.json; individual rules can be disabled with --disable-stack-rule <rule-id>.
- Local Change Contract lifecycle and deterministic Git budget engine.
PASS,REPAIR, andHUMAN_REVIEWresults with reports and exit codes.- OpenCode Runtime Guard and project-local
integrate opencodeworkflow. - Android, Flutter, Spring Boot, and Node/TypeScript stack policies.
- Spec-Kit task bridge and deterministic diagnose advisor.
- Personal v1.0 reliability hardening.
- Immutable tagged installation, Windows/Linux CI, and tagged-smoke validation.
- SPEC-012 complete: immutable
v1.1.5tagged smoke passed on Ubuntu and Windows. - Working Tree Baseline: unchanged pre-existing work is excluded from a new contract while later semantic edits remain enforced.
The roadmap's explicitly deferred items remain deferred: cloud services, dashboards, accounts, billing, marketplaces, remote execution, full OS sandboxing, silent auto-repair, and LLM-based compliance.
Current development version: 2.0.0-beta.7.
- Normal CI runs on Windows and Ubuntu.
- Windows test execution uses native Node sharding.
- npm package installation is validated from the public registry.
- A maintainer-controlled GitHub Release triggers
npm-publish.yml, which uses GitHub Actions OIDC trusted publishing after publication validation passes on Ubuntu and Windows. - SPEC-012 is complete.
- GitHub Release publication remains a manual maintainer action.
The npm package is public. The stable OIDC release flow uses the public registry and does not require a PAT, custom secret, SSH key, gh, or a personal credential helper.
The published Git tag must be exactly v followed by the package version. Stable releases use a normal GitHub Release and npm dist-tag latest; prereleases use a GitHub prerelease and their matching npm channel:
| Version | Git tag | GitHub Release | npm dist-tag |
|---|---|---|---|
X.Y.Z |
vX.Y.Z |
Normal release (prerelease=false) |
latest |
X.Y.Z-alpha.N |
vX.Y.Z-alpha.N |
Prerelease (prerelease=true) |
alpha |
X.Y.Z-beta.N |
vX.Y.Z-beta.N |
Prerelease (prerelease=true) |
beta |
X.Y.Z-rc.N |
vX.Y.Z-rc.N |
Prerelease (prerelease=true) |
rc |
Only those stable and prerelease forms are supported. The release workflow validates the package, lockfile, Git tag, and GitHub Release classification, then always publishes with an explicit npm dist-tag. Before a prerelease it records the existing stable latest; afterward it verifies that the prerelease channel points to the new version and latest is unchanged. A mismatch fails without attempting to repair registry tags. Prereleases never modify latest.
changebudget update remains stable-only: it does not discover or automatically install prereleases. Install or update a prerelease explicitly through npm, for example npm install changebudget@beta.
- Local-first: no backend or account is required for normal operation.
- Deterministic: Git and explicit rules decide compliance.
- Human authority: agents cannot authorize their own scope expansion.
- Explainable: violations expose rules, paths, and reason codes.
- No silent destruction: validation does not revert or delete user work.
- Fast-path friendly: small tasks should have a small workflow.
- No LLM required at runtime: AI may write code; it does not decide policy.
- Zero telemetry by default: code, diffs, and project paths stay local.
This is for working on ChangeBudget itself, not the normal end-user installation path.
Requirements: Node.js 20+, Git, and npm.
npm install
npm run compile
npm run typecheck
npm testChangeBudget/
βββ src/ # CLI, Git inspection, rules, state, and policies
βββ opencode-plugin/ # OpenCode Runtime Guard package
βββ tests/ # Unit, integration, acceptance, and contract tests
βββ specs/ # Spec-Kit feature artifacts
βββ .specify/ # Spec-Kit project configuration
βββ ChangeBudget_Roadmap.md
ChangeBudget does not provide a cloud backend, accounts, teams, telemetry, a web dashboard, remote code execution, a general shell parser, a full operating-system sandbox, universal AST analysis, LLM-based compliance decisions, automatic rollback, silent contract widening, or a public policy marketplace.
ChangeBudget is available under the MIT License. See third-party notices, contributing guidance, the security policy, and the Code of Conduct.