Releases: Tarekkharsa/agentstack
Release list
v0.10.1
v0.9.0
The first release where the flagship enforcement ships in the box: every binary below is built with the sandbox feature, and --lockdown is zero-config.
Highlights
-
Confined runs out of the box —
agentstack run --sandboxand--lockdownwork from these binaries directly (Docker required for the runs themselves). Lockdown pulls its egress-proxy sidecar automatically from GHCR, pinned to this exact version — no env vars, no image builds. -
Honest posture labels — every run is labeled in the banner,
--plan, andagentstack report:HOST / ADVISORY,SANDBOX / PROXIED · DIRECT ROUTE OPEN,LOCKDOWN / ENFORCED · NO DIRECT ROUTE. ENFORCED is reserved for lockdown, on purpose. -
The enforcement matrix — docs/ENFORCEMENT.md states, per mode and per policy dimension, what is enforced / coarse / unsupported. "Trusted" is not "confined"; the docs now make that impossible to misread.
-
Machine-policy presets — ready-made
compatible/developer/locked-down/cipolicies in examples/policies/, anddoctorreports your machine-policy posture. -
Flight recorder fill-out — sandbox run logs now record tool calls (outcome + rule + args digest, never values) and secret refs touched (names only);
agentstack reportrenders it all. -
Supply chain — release binaries and the sidecar image carry GitHub build-provenance attestations; workflows are SHA-pinned. Verify any asset:
gh attestation verify agentstack-<target>.tar.gz --repo Tarekkharsa/agentstack
Breaking
- Trust store moved to
~/.agentstack/trust.json(the trust crate no longer parses TOML). There is no migration: existing projects read as untrusted — fail-closed by design. Re-runagentstack trust .per project. - Egress policy patterns accept an optional
:port(api.example.com:443); the compiled ruleset version bumped, and older enforcers refuse newer rulesets rather than misread them.
Install
curl -fsSL https://raw.githubusercontent.com/Tarekkharsa/agentstack/main/install.sh | shStart here: the ten-minute journey — untrusted repo → review → trust → confined run → readable report.
Egress proxy image: ghcr.io/tarekkharsa/agentstack-egress-proxy@sha256:e8e0580ab161a8daae78d72701cc6ce58919e66c756bc134b1a957cc552559f4
v0.8.1 — first-run fixes from a fresh-user walkthrough
First-run fixes from a documented-paths-only walkthrough: a fresh agent followed the README and docs on a clean machine with no source access, and everything it stumbled on is fixed.
Onboarding
agentstack initworks on a clean machine. With no supported CLIs to import, it now scaffolds a commented starter manifest (worked server example + next steps) instead of writing nothing — previously every other command said "runagentstack init" whileinititself declined, a circular dead end for first-time users.applyexplains skills. Skills activate through profiles (agentstack use <profile> --write), never throughapply— that's by design, andapplynow says so instead of silently ignoring manifest skills.use --writesummary is honest when skills were written but no CLI binaries were detected (no more "activated on 0 target(s)" under a ✓ skills line).
Docs
- README opening reconciled with the tool's own
agentstack setuphint; skills-need-profiles stated up front; pointer to the zero-files trust-gate path from the top. agentstack connect --all --writeshown correctly (bareconnecterrors).- Running
agentstack lockre-gates trust (new pins = new consent) — now documented where you'll hit it. - Manifest relative paths anchor at
.agentstack/(a skill'spath = "./skills/x"lives at.agentstack/skills/x); a server'scwdis the documented exception (project root).
Embedded skill
The bundled using-agentstack skill (served to agents over the control plane) now covers the runtime half: the trust gate (agents must never run agentstack trust themselves — it's the human consent gate), reading two-layer policy denials, compact vs transparent modes, audit --calls, and analyze.
For what the walkthrough confirmed working exactly as documented — trust gate, both policy layers, transparent mode, call log, library + lock — see v0.8.0.
v0.8.0 — machine policy, transparent proxy, hardened call log
The runtime control plane grows teeth: a machine-level policy layer no repo can loosen, a transparent proxy mode for standard MCP clients, and a hardened call log.
Machine-level policy with deny precedence
Your own [policy.tools] in ~/.agentstack/agentstack.toml is now checked before the project's on every brokered call — a cloned repo's policy cannot loosen it, and machine refusals name their layer in the error and the call log.
# ~/.agentstack/agentstack.toml — applies to every project on this machine
[policy.tools]
"*" = ["!delete_*"] # rename-proof: no server may delete_*, whatever a repo names it
github = ["get_*", "list_*"] # servers named github are read-onlyBe precise about what a rule binds to: named rules match the manifest-chosen server name (which a repo controls); the new "*" wildcard key constrains every server regardless of name. explain <server> shows both layers; doctor flags an unreadable machine manifest (which fails open to project-only policy).
Transparent mode: a drop-in MCP proxy
agentstack mcp --transparent (register with connect --transparent) advertises the policy-filtered upstream tools as <server>__<tool> in tools/list — any standard MCP client can use the proxied surface with zero agentstack knowledge. Compact mode (bounded tool context via tools_search) stays the default. Auto-project mode announces the lazily built, trust-gated gateway via notifications/tools/list_changed.
Call log hardening
- No upstream-authored text: failed calls log a fixed error class (
unresolved-secret/timeout/spawn-failed/http-error/upstream-error) — a malicious server can no longer write into the log. - Keyed argument digests: a per-machine random secret (
audit/key, 0600) keys the digests, so an exfiltrated log alone can't confirm guessed argument values. - Private files: log, key, and audit dir are created (and re-tightened) 0600/0700.
- Honest docs: it's a best-effort local diagnostic call log — not durable, not tamper-evident.
Also
- Gateway per-upstream concurrency shipped in the previous tag now drains in-flight calls at session end instead of dropping responses.
- The gateway's module contract and reference docs updated throughout.
Upgrading from ≤ v0.6.x: the v0.7.0 trust-digest change applies — previously trusted projects re-gate once; re-run agentstack trust <dir> after reviewing.
v0.7.0 — trust closes the loop, gateway goes concurrent
Runtime hardening release: the trust gate now covers everything the gateway runs, and the gateway no longer serializes calls behind one lock.
⚠️ One-time re-trust required
The trust digest formula changed: it now covers the manifest layers and agentstack.lock. Every previously trusted project will show as "changed" once after upgrading — review and re-run agentstack trust <dir>.
Trust gate: the consent loop is closed
- The trust digest covers
agentstack.toml+agentstack.local.toml+agentstack.lock— re-pinning the lock re-gates the project, exactly like a manifest edit. - The gateway verifies central-library server definitions against the lock's pinned digests before serving them: a drifted definition is refused with a
re-run \agentstack lock`` message; an unpinned ref serves with a warning. agentstack trust .now previews the effective runtime surface — library name refs included, each labeledpinned/unpinned/DRIFTED— not just inline[servers.*]tables. What you review is a strict superset of anything any session can run.
Gateway: per-upstream concurrency
- Calls to different MCP servers now run in parallel — a slow 60-second call to one server no longer blocks every other server. Same-server calls still queue (one stdio pipe).
- Both serve loops dispatch upstream calls to worker threads (agentstack's own control-plane tools stay serialized), and the code-mode endpoint handles requests concurrently.
Fixes
- Gateway spawns stdio servers in the project root (or the server's
cwd) — previously the.agentstack/layout anchored relative paths at the manifest dir. - Library servers referenced only by name now reach the gateway exactly like inline ones (previously silently absent in zero-files mode).
- Manifest, lockfile, and library index refuse schema versions newer than the build supports instead of misreading them silently.
- An unreadable central library is reported on stderr instead of silently resolving to empty.
install.shverifies release tarballs against the publishedchecksums.txt(since v0.6.0); releases publish checksums from a single aggregated job.
v0.6.0
v0.5.0
This release brings the read-only analysis tooling out of the terminal and into
the local dashboard, and gives the docs pages a proper visual pass.
Dashboard: read-only analysis panels
The proxy wire report and the analyze / optimize / stats reports were
CLI-only. They now render in the embedded, token-gated dashboard — no new
mutating routes, so --read-only mode stays fully enforced (and pinned by the
route-matrix test).
- Proxy tab — the wire lens, the same ranked report as
agentstack proxy report: per-turn tools and token weight, plus a per-capability table (tools,
average tokens/turn, calls, and adrop / lazy·keep·watchhint). An
explicit empty state points atagentstack proxy startwhen there's no
telemetry yet. - Insights tab — three stacked read-only reports: Optimize (each
recommendation with its evidence, exact command/TOML, and why it's safe or
needs a human), Analyze (runtime call activity from the gateway audit log
plus library dead weight), and Stats (per-capability activations, measured
context cost, live slots, and dead-weight flags). - The snapshot collectors are best-effort: a failing report degrades to an empty
panel instead of sinking the whole dashboard. Theoptimizeandstats
report logic was extracted into shared pure helpers so the CLI and the
dashboard can never drift.
Observe-only wire proxy
agentstack proxystands up a loopback proxy in front of the Anthropic API
and relays every request verbatim — nothing injected, the tools/system block
is never touched, so the prompt-prefix cache stays warm. As requests flow it
accounts what thetoolsblock costs per turn and stashes best-effort
per-capability numbers.proxy reportranks it into the ground-truth
companion to the staticstatsestimate.
Doctor
doctornow warns on bare, PATH-dependent stdio launchers — a server that
will break the moment it's spawned from a different environment.
Docs
The landing and central-library pages got a self-contained visual refresh —
sticky blurred nav, a bolder hero, terminal showpieces, a proof row of all 13
supported CLIs, and a feature-card grid — with light and dark both tuned and no
external assets. The dashboard guide documents the new Proxy and Insights panels.
v0.4.0 — plugin parity, owned servers, per-target scoping
Everything in this release came out of one dogfooding cycle: running agentstack
against a real machine with 8 CLI harnesses, and fixing what actually broke.
Plugins: adopt once, install anywhere
plugins adoptlifts an installed native plugin (Claude Code or Codex)
into the manifest. Bundled skills are copied into the central library
with plugin provenance (source,rev) recorded — the recipe survives
native plugin updates and uninstalls instead of path-pointing into a
versioned plugin cache. Codex auth wiring (bearer_token_env_var,
env_http_headers) is carried through as portable${REF}headers.- Satisfied natively: the harness a recipe was adopted from is satisfied
by its still-installed native plugin.plugins statusanddoctorreport
it as up to date at the adopted version + rev and surface drift when the
native plugin moves ahead — they never suggest double-installing. - Generated Claude Code packages no longer reference the auto-loaded
hooks/hooks.jsonpath fromplugin.json(Claude Code treats that as a
duplicate-hooks error that breaks the whole plugin); hook-less recipes ship
no hooks file at all.
Servers: scoping, native keys, and app-owned config
- Per-server targets —
[servers.X] targets = ["claude-code"]scopes the
fan-out like instructions and hooks already could;targets = []opts a
server out entirely (how adopted plugin servers are stored, so the same
server is never configured twice on a harness its plugin already serves). - Per-target extras —
[servers.X.extra.codex] startup_timeout_sec = 20
passes native keys the manifest schema doesn't model through to one
adapter, verbatim.initandadoptlift unknown config keys back into
extras, so hand-tuned settings surviveapply --writeround trips. - Owned servers —
[servers.X] owner = "codex"makes the owning app's
config the source of truth. When the app rewrites its own entry (a
self-update), every plan refreshes the manifest from disk and fans the
fresh values to the other CLIs — instead of proposing a downgrade.
${REF}values stay manifest-canonical so secrets never leak back into
the manifest, and valid trust is re-pinned across the machine-derived
rewrite.
Secrets & reporting
- Secret refs are strict
${IDENTIFIER}s: shell fallback syntax
(${VAR:-fallback}) and prompt-style placeholders (${input:key}) pass
through verbatim and are no longer misread as manifest secrets. - One keychain read per ref per run; a transient read failure is retried and
a persistent one reports as keychain read failed — distinct from not
found, so a flaky keychain daemon can no longer block writes by claiming
a stored secret is missing. apply --writesummaries count targets actually written ("X of Y written —
Z blocked"), not planned changes.
Docs: README gains the plugin-parity walkthrough and owned-servers story; the
feature reference covers the new manifest fields and secret semantics; the
shipped using-agentstack skill teaches agents the new rules.
v0.3.0 — the runtime trust plane, versioned packs, and a friction-free lifecycle
agentstack 0.3.0 — the runtime trust plane, versioned packs, and a friction-free lifecycle.
Highlights
The gateway now proxies stdio MCP servers. Zero-files mode is no longer HTTP-only: stdio children spawn lazily in their own process group, get ${REF}s resolved into their env per session, and are tree-killed when the session ends (stdin-EOF → SIGTERM → SIGKILL). Code-mode bindings cover stdio tools too.
MCP firewall — [policy.tools]. Per-server tool rules enforced at the runtime gateway:
[policy.tools]
github = ["get_*", "list_*", "!list_secrets"]Plain globs allow, ! denies; with allow patterns the list is an allowlist. A denied tool is invisible — filtered from tools_search and code-mode bindings — and refused with the rule named if called anyway. doctor validates the rules; explain <server> shows the effective policy.
Call audit log. Every call the gateway brokers is appended to ~/.agentstack/audit/calls.jsonl — timestamp, run id, server, tool, argument digest (never values), outcome, latency. Read it with agentstack audit --calls [--since <days>] [--json], or in the dashboard: each run's trust footprint on the Runs panel (agentstack run now exports AGENTSTACK_RUN_ID so calls attribute to runs). Logging is best-effort and size-rotated — it can never fail a call.
Versioned packs from any git host. Any repo with a pack.toml is an installable pack, pinned to a version tag:
agentstack add from git:github.com/acme/agent-pack@v1.2.0 --write
agentstack upgrade acme --write # finds the newest tag, previews the diff, re-pins[policy] allowed_sources is enforced before anything is fetched; the clone's content passes the same hidden-Unicode scan gate as install; the ledger records source/version/commit and extracted skills stay digest-pinned so install --locked reproduces. agentstack pack init scaffolds a publishable pack. (Semver ranges and transitive dependencies are deliberately out of v1.)
Context-cost lens. agentstack stats --live measures each server's tools/list token footprint through the gateway and caches it; stats, explain, and the dashboard's sortable context column show what every server taxes each session — and stats flags dead weight (high-cost, never-activated servers) with the exact remove command.
The dashboard closes the loop. Doctor runs from the Health tab (the same checks as the CLI, rendered); servers gain Remove from stack…; --read-only is enforced centrally for every mutating endpoint and pinned by a route-matrix test; Discover installs packs from a git URL. The full UI-only lifecycle is documented in docs/dashboard.md.
agentstack lock — pin without materializing. Clean-at-rest repos reference library capabilities by name and keep no generated files on disk; locking those refs used to require an activate-then-deactivate dance. agentstack lock [--profile <name>] resolves every profile's skill + server refs and pins them in agentstack.lock — no configs rendered, no skills materialized. install is profile-aware to match, so library-profile pins survive its reconcile pass.
Trust is visible from inside the session. An untrusted (or edited-since-trusted) project used to degrade the gateway to control-plane-only with only a stderr whisper. Now tools_search says so and names the exact agentstack trust <dir> command, the agentstack_doctor MCP tool reports a Trust (auto mode): line, and CLI doctor warns when a harness has the bridge registered but the project is untrusted.
Small operations feel instant. Read-only MCP skill loads (agentstack_list_loadable / agentstack_load) no longer hash the library at all — on a 373 MB library that's seconds → milliseconds. A persistent stat-fingerprint digest cache (~/.agentstack/digest-cache.json, per-file size+mtime folded into the fingerprint, any mismatch re-hashes) collapses repeat digests for use/lock/doctor; session start resolves the profile once instead of twice; the gateway is built once per process; doctor's full content scan moved behind --deep (--ci always includes it). And lib add warns when a skill exceeds ~10 MiB — vendored node_modules don't belong in a skill.
A first-class home for personal instructions. agentstack init --global seeds ~/.agentstack/agentstack.toml plus an instructions/ dir — the machine-level layer for cross-project operational knowledge. Its [instructions.*] fragments merge in beneath every project (global scope only: personal rules never land in a repo's committed CLAUDE.md, and servers/skills deliberately don't inherit). instructions is un-hidden and wired into apply/setup/doctor; a bundled agentstack house-rules fragment teaches every agent the manifest-first workflow; and the using-agentstack manual is always loadable through the gateway — even in untrusted, control-plane-only sessions.
agentstack self link. The supported from-source install: symlinks the running binary into your PATH (/usr/local/bin or ~/.local/bin, AGENTSTACK_PREFIX honored); self which catches stale shims. Retire your hand-rolled shell functions — they break in non-interactive agent shells.
Drift is a guided decision now. doctor names the exact servers a write would remove and offers both paths — keep them: agentstack adopt · prune them: agentstack apply --write. Cross-manifest prunes are guarded: servers recorded by a different manifest are kept on write, tracked as kept_foreign (still reported by doctor/diff), and pruned only by an explicit apply --prune-foreign.
Also
- Lifecycle hygiene: the managed
.gitignoreblock is directory-level and survives deactivation (no more churn or stripped committed blocks); an emptied managed skills dir is removed with rmdir semantics (user content always survives);session endrestores the filesystem exactly. lib addsays "copied", notes the library copy is canonical, and warns when the source is a temp dir (dangling provenance).- Missing instruction fragment sources now block
apply --writeandinstructions --writeinstead of silently deleting previously compiled content. audit --callscolumn alignment fix (pad before coloring).- Runnable, fully sandboxed closed-loop demo:
agentstack-test/demo-closed-loop.sh. - Docs site refreshed with the new capabilities. 423 tests.
Install
curl -fsSL https://raw.githubusercontent.com/Tarekkharsa/agentstack/main/install.sh | sh
# or: cargo install agentstack
# or, from a checkout: cargo build --release && target/release/agentstack self link