crucible 0.0.1
The first release: a coding agent you can hold a session with, and the gates
that say what it is allowed to become.
Added
- A session that runs.
cruciblereads a prompt, streams the model's answer
inline, runs tools, and asks before anything that changes a file or starts a
process.--continuecarries on the most recent session started in the
current directory. An answer the provider cut short says so under the turn,
with the token ceiling, the content filter and a paused turn named apart
because the remedy differs for each. The bound on that: a stop reason this
build has not heard of reads as an ordinary finish, so a vendor adding one is
the case where a cut-short answer can still arrive looking complete. - A startup that fails leaves no session behind. Everything that can fail on the
way in runs before the session is started, so a wrong--modelor an unset
key writes nothing: an empty session would otherwise be the newest one for the
directory, and--continuewould offer it instead of the last real session. - Two providers, chosen by
--model [provider/]model:anthropic(the default
for an unqualified name, keyed byANTHROPIC_API_KEY) andopenai(keyed by
OPENAI_API_KEY). Authentication is a separate axis from the wire protocol —
a provider is handed a resolved credential and never learns which kind it was. - Six tools:
read,grep,glob,edit,write,bash. Every one of them
takes a permission token that only a verdict can mint, so code that has not
obtained one cannot call the operation; a read mints its own, and a file
change or a command asks first.alwaysremembers the tool for a file change
and the tool and program for a command, and is never written to disk. What a
tool returns is bounded, and a result that is short says so in the result
itself — more lines follow, a line was cut at a width, a listing stopped at
its limit, output was still arriving, the command was stopped for running too
long — because a silently trimmed result reads to the model as a complete one. - Session log: one JSON object per line, one file per session, under
$XDG_DATA_HOME/crucible/sessions. A log from a build with a different format
is refused rather than half-understood. The log is0600and its directory
0700, set on every start and every--continuerather than only at
creation, because a transcript holds what was typed, what files were read and
what commands printed — and a group-writable directory would let another
account drop a log in for--continueto replay. A log torn mid-line by a
crash costs that line, and the torn bytes are dropped from the file before the
continued session appends to it; one damaged in the middle is refused outright
rather than silently returning a session with a hole in it. docs/— getting started, providers and models, permission, and sessions.- Cargo workspace:
crucible-core,crucible-provider,crucible-tools,
crucible-runner,crucible-tui, and thecruciblebinary. Dependencies
point down only, enforced by cargo. scripts/check.sh— formatting, clippy with-D warnings, tests, a
400-line-per-file cap, pinning checks for dependencies, GitHub Actions and the
agent instruction files, a comment above every dependency saying why it is
needed, and a check that CI stops excusing a failing budget once the first
bench probe exists. CI runs the same script.scripts/bench.sh— one probe per performance budget, selectable by mode
(startup,mem,grep,stream, or all of them). Writes a JSON document
to stdout and a readable summary to stderr, so one run serves a pipeline and a
human. Every budget reportsUNMEASUREDuntil its probe exists, and the script
fails, so a release cannot claim a number nobody measured.- Lint configuration encoding the project rules: no panicking paths, no ad-hoc
terminal output,forbid(unsafe_code), function-length and complexity limits. CLAUDE.md— the rules a gate cannot check, withAGENTS.mdsymlinked to it
so every agent tool reads one file..claude/rules/— one file per crate carrying the obligations that bind only
inside it, scoped bypaths:frontmatter so each is read when a file it
claims is opened. They state what a change must do rather than restating what
the module documentation already explains, which is what keeps them from
becoming a second copy.scripts/check.shfails a rule with no frontmatter or
one aimed at a directory that no longer exists — either way nothing loads it,
and it fails by staying silent.- Agent skills for the procedures a rules file cannot carry: running and
extending the gate, adding a dependency, and staying clean-room. Written once
under.claude/skills/and symlinked from.agents/skills/, so Claude Code
and Codex read the same text. .codex/config.toml— how Codex should run here.network_accessis on
because cargo cannot resolve crates.io without it..github/: a CI workflow runningscripts/check.shandscripts/bench.sh
— the second uploading its JSON as a build artifact, so a budget trend exists
from the first pull request — plus a tag-triggered release workflow,
Dependabot for cargo and actions, and issue and pull request templates.deny.tomland a weeklyauditworkflow — the other half of pinning. Nothing
here moves on its own, so an advisory published against a version already
pinned would never surface; a scan on a clock finds it, and the same scan
refuses a licence that would make the MIT on the binary untrue or a dependency
from anywhere but crates.io. It runs apart fromscripts/check.shbecause its
answer changes when somebody else publishes rather than when you edit.- Contributor Covenant 3.0 code of conduct, contribution guide, and a documented
release procedure. crucible_tui::Title— sets the terminal tab title to▽ crucibleand
restores the terminal when dropped.
Known limits
- A window resized mid-turn is noticed at the next prompt, not as it happens.
Catching the signal a resize sends needsunsafe, which this workspace
forbids, so what a resize costs is the turn it lands in. - Ctrl-C ends the process rather than the turn, for the same reason.
The session log is written as the turn goes, so--continuepicks it up. - Path containment resolves a path and the tool then acts on it, which is two
steps rather than one. A path swapped for a symbolic link in between would be
followed, so the check bounds a model working in the tree and not an attacker
who can already write to it concurrently. - A provider that pauses a turn is reported and left there. Sending the
transcript back to carry on is a decision for the user, not something 0.0.x
does by itself. - A sessions directory or log left at anything other than
0700/0600is set
to it on start and on--continue, and a filesystem that refuses fails the
run rather than writing a transcript somewhere the whole machine can read. One
already at the right mode is not touched, so this costs nothing on the
ordinary path and leaves a sticky bit where it was. - Linux x86-64 only. The release builds one artifact.