Your repo. Your providers. Your evidence.
A local-first command runtime for bounded work, inspectable receipts, safe Browser checks,
provider readiness, and script-stable output.
Important
The signed public preview supports Apple Silicon macOS and glibc Linux on x64 and arm64. Its installer authenticates the exact source-bound runtime before activation. You can also build the same bounded runtime from source.
Bitter runs the exact argv after -- without a shell, stops when the work fails,
and leaves a bounded receipt in the repository.
$ bitter loop start -- bun test
Loop completed: loop_<timestamp>_<id>
command: bun
iterations: 1/1
receipt: .bitter/public-loop/receipts/loop_<timestamp>_<id>.json
output: .bitter/public-loop/runs/loop_<timestamp>_<id>/attempt-1.stdout.log
$ bitter loop status
Loop status for my-project
runs: 1 (1 succeeded, 0 failed)
last: completed - .bitter/public-loop/receipts/loop_<timestamp>_<id>.jsonThe same local truth is available to scripts without scraping terminal prose:
$ bitter --unwrap loop
{
"schema_version": "bitter.public_loop_home.v0",
"account_required": false,
"network_required": false,
"shell_interpretation": false,
"state_directory": ".bitter/public-loop",
"state_git_ignored": true,
"operations": ["loop.home", "loop.start", "loop.status", "loop.history"]
}That is the core idea: useful local work, explicit authority, and evidence you can inspect after the terminal scrolls away.
| What you get | What Bitter refuses to pretend | |
|---|---|---|
| Local by default | Loop, status, discovery, Browser checks, and provider probes without a Bitter account | The command you invoke may still use the network; Loop is not an OS sandbox |
| Evidence over vibes | Exit status, timing, timeout/signal state, byte counts, full-stream SHA-256 digests, and bounded stdout/stderr artifacts | Receipts are durable local records, not signed or tamper-proof attestations |
| Bring your own agent | Narrow readiness probes for Codex CLI, Claude Code, and Gemini CLI | Bitter does not authenticate, launch, or inspect the private state of those tools |
| One truth, three views | Human-readable terminal output plus deterministic --json and --unwrap results |
TTY formatting never becomes a second source of runtime truth |
| Inspectable delivery | Allowlisted source projection, pinned dependencies, reproducible runtime build, signed update verification, and anti-rollback state | This preview does not silently self-update |
You need Bun 1.3.13, Git, GNU tar 1.35 or a compatible GNU tar, and gzip.
git clone https://github.com/sheetgenius/bitter-cli.git
cd bitter-cli
bun install --frozen-lockfile
bun run verify:source
bun run check
bun run test
bun run build
./build/public-beta/bin/bitter --helpThe build writes a bundled-Bun runtime to build/public-beta/. Prove two
byte-identical builds from the same source, validate the archive, and run the
extracted CLI smoke test with:
bun run verify:reproducibleFor the complete first-run path, see the five-minute local tour.
| Surface | Useful today | Boundary |
|---|---|---|
| Loop | Run literal argv with bounded iterations and timeouts; inspect status, history, receipts, and captured streams | One Git repository at a time; no shell interpretation; final 1 MiB of each stream retained while the full stream is counted and hashed |
| Browser | Inspect public capability posture and capture screenshots from explicit public or loopback URLs | No browser profile input, storage inspection, page interaction, or arbitrary evaluation |
| Codex, Claude, Gemini | Check whether a supported provider CLI is present and report its version | Runs only <tool> --version; does not read provider homes, credentials, history, or subscription state |
| Methods and plugins | Discover and inspect 20 digest-bound public methods across the kernel and five bundled plugins | No private Factory/Grid operations and no ambient plugin marketplace |
| JSON and non-TTY | Use deterministic output envelopes, --json, and --unwrap in scripts and agents |
Errors remain structured and go through the same public contracts |
| Bitter account | Optionally use browser-bound PKCE login and inspect local auth posture | Separate from provider authentication; local work remains accountless |
| Updates | Verify signed stable-channel metadata and anti-rollback state with update --check |
Check-only in this preview; installer-owned activation remains separate |
Explore the shipped surface directly:
bitter capabilities
bitter methods list
bitter loop --help
bitter browser capabilities
bitter codex_cli probe
bitter claude_code probe
bitter gemini_cli probe
bitter --json statusbitter loop start --directive "Keep the repository healthy" -- bun test-- is the authority boundary. Bitter passes the following arguments directly
to the child process and never evaluates a shell string.
bitter loop status
bitter --json loop history --limit 5State lives under .bitter/public-loop/ and is added to the repository's local
Git exclude file. A receipt survives the process that created it.
bitter browser capabilities
bitter --json codex_cli probeBrowser reports the exact operations it permits. Provider probes reveal only executable readiness and version output.
bitter login
bitter --json authLogin is optional and browser-bound. It connects to the intentionally public Bitter account contract; it does not sign you into an AI provider.
Bitter keeps the local and connected planes visibly separate:
- Explicit input: Loop receives argv, not a shell command string.
- Narrow capabilities: every bundled method belongs to a declared profile and a digest-bound plugin manifest.
- Local custody: receipts and stream artifacts stay in the working repository by default.
- Safe projection: human, JSON, and unwrapped output share one versioned envelope.
- Public contracts only: login and update checks are the optional connected edges; no private control plane is embedded in this source tree.
- Reproducible delivery: the public tree is a deterministic allowlisted projection, and the runtime is bound back to its exact source digest.
Read the public boundary, output envelope, and runtime bundle contract for the exact rules.
| No account required | Optional connection |
|---|---|
status, doctor, capabilities |
login, logout, auth |
| method discovery and inspection | signed update --check metadata retrieval |
| Loop execution, receipts, and history | intentionally public Bitter account contract |
| Browser capabilities and screenshots | |
| Codex, Claude, and Gemini version probes |
The Browser screenshot operation may fetch the explicit URL you provide. Likewise, a child command can use whatever OS and network authority your user already has. Bitter narrows its own behavior; it does not claim to sandbox the machine.
| Target | Source-build gate | Signed public preview |
|---|---|---|
| macOS arm64 | Supported | Supported |
| Linux x64, glibc | Supported | Supported |
| Linux arm64, glibc | Supported | Supported |
| macOS x64 | Not supported | Not published |
| Windows | Not supported | Not published |
The three stable bundles are narrowed builds of this public projection. Their signed manifests bind the exact source commit, runtime digest, Bun toolchain, and published source packet. Install with:
curl --proto '=https' --proto-redir '=https' --max-redirs 0 \
--fail --location --silent --show-error https://install.bitter.sh | shSee the release history and update contract for the precise channel posture.
- Documentation map
- Contributing
- Security policy
- Support policy
- Changelog
- Apache-2.0 license
- Third-party notices
Bitter CLI is preview-quality software with a deliberately bounded public surface. It is an Apache-2.0 project developed by SheetGenius, Inc.; identified third-party material keeps its own terms.