All notable changes to this project will be documented in this file.
No changes yet.
0.13.0 - 2026-07-11
- First-class OpenRouter provider profiles — named profiles in
config.jsonmodelProvidersroute Docker agents (Claude Code, Codex, Goose) through openrouter.ai with a bound model map and per-profile key, with no LiteLLM sidecar (the implicitnativeprofile remains the fallback). GLM prompt caching is preserved via a MITM softz-aiprovider pin plus stable session affinity, and billing uses the authoritativeusage.costreported by OpenRouter rather than the CLI self-report. A profile is selectable across three surfaces — the globalmodelProviders.default,ironcurtain start --provider-profile <name>, and the mux/newpicker — and is configurable viaironcurtain config→ Model Providers and the web UI Settings view (#361). - Live web terminal for Docker Agent sessions — the Sessions view now runs real PTY-backed agent sessions through an xterm.js terminal, including terminal state serialization, reconnect/replay, trusted-input forwarding, and escalation events. The former chatbox session mode has been removed so the web UI and mux share the same interactive terminal model (#366, #368).
- Apple container UDS isolation — Apple
container1.1.0 and newer now use the same Unix-domain-socket topology as Linux Docker, with--network none, per-socket host/guest relays, and no host service listeners exposed on0.0.0.0(#371). - Docker resource garbage collection —
ironcurtain gccan inspect orphaned IronCurtain containers and networks in dry-run mode or explicitly reclaim them, using the same crash-recovery reconciler invoked during session startup (#380).
- Node.js 26 support — bumped the V8 sandbox dependency
isolated-vmto 7.0.0 (via an npmoverride, since it is transitive through@utcp/code-mode) so Code Mode initializes on Node 26;isolated-vm6.x has no Node 26 prebuild and fails to compile against Node 26's V8. Supported lines are now the even-numbered major lines 22, 24, and 26: Node 24 and 26 install prebuilt native binaries, while Node 22 compilesisolated-vmfrom source at install (no prebuilt binary ships for it, so a C/C++ toolchain is required). Odd non-LTS lines (23, 25) run withinengines(>=22.0.0 <27) but are untested —ironcurtain doctorreports them as a warning, not anok. CI runs Node 24 and 26 on every PR and adds a Node 22 source-compile job on pushes to master (#356, #358). - Claude Code workflow execution — subagents run synchronously and Claude Code's own streaming idle watchdog is disabled. IronCurtain's workflow budgets remain the timeout authority, avoiding false “Response stalled mid-stream” failures during long tool-use turns behind the MITM proxy (#372, #376).
- Runtime-capability-based workflow snapshots — workflow snapshot creation and cleanup now depend on the selected runtime's declared snapshot capability. Docker opts in; Apple
containerskips unsupported image commits cleanly (#369).
- Crash-safe Docker network lifecycle on macOS — Docker containers and per-bundle networks now carry owner leases and labels, and later sessions reconcile resources left by
SIGKILLor host crashes. macOS Docker uses collision-checked/29allocations outside192.168/16, retries a different subnet when end-to-end MCP/MITM routing checks fail, and handlesSIGTERM/SIGHUPwith bounded shutdown escalation (#380). - Docker writable-storage exhaustion diagnostics — session startup now probes the container's writable layer before reporting “Session ready,” gives targeted
docker system dfguidance forENOSPC, and treats a zero-exit/no-output Claude Code turn as a hard failure without poisoning the next conversation resume (#381). - Debian package validation and auditing — plain-HTTP apt traffic now passes through the same denylist validation and
package-audit.jsonlpath as HTTPS registry traffic, closing a path where denied.debpackages could install without an audit record (#355). - MITM proxy certificate generation on Node 22 / OpenSSL 3.0 — serial numbers are now always encoded as positive DER integers, eliminating intermittent
asn1 encoding routines::illegal paddingfailures when generating CA or leaf certificates (#360). - Workflow daemon-gate startup under tsx — detached daemon launches preserve
process.execArgv, so--ensure-daemonworks from the documentedtsx src/cli.tsdevelopment entry point instead of timing out (#354). - MCP stdio shutdown reliability — benign
EPIPEandECONNRESETerrors on closing stdio transports no longer become unhandled worker failures (#353).
- Bumped the AI SDK providers, Anthropic sandbox runtime, MCP/UTCP packages, XState, YAML, Zod, jsdom, and related production dependencies.
- Added
@xterm/addon-serializefor terminal reconnection and refreshed the web UI dependency set. - Refreshed TypeScript, ESLint, Prettier, tsx, lint-staged, and other development tooling.
- Added a deterministic MITM stream-delay harness and documented the streaming-watchdog investigation (#379).
- Hardened macOS CI against benign teardown races and native dependency download failures (#374, #375).
- Added packaged README documentation for the Evolve and Vulnerability Discovery workflows and expanded agent-memory architecture notes (#373).
0.12.0 - 2026-06-26
- Codex CLI agent and token-trajectory capture - added a Docker adapter for Codex CLI alongside faithful OpenAI/Codex token trajectory capture for SFT/RL training data.
--capture-tracesis wired through mux PTY sessions and daemon-launched workflows, with trajectory reassembly/tap support and documentation for downstream training pipelines (#273, #276, #280, #288). - Evolve workflow - new native workflow for iterative candidate evolution: deterministic container execution with packaged scripts, a structured deterministic result contract for verdict routing, single-round and multi-round execution, human-surface gates, final summaries, abort handling, a generic experiment harness, correctness stop conditions, resume idempotency, search-quality cognition promotion, multi-parent/selectable samplers, and synchronous N-way fan-out lanes (#292, #299, #300, #302, #303, #309, #313, #315, #323).
- Workflow runtime and gate improvements - workflow agents can now use daemon-driven gates, shared containers can be snapshotted and resumed across resumable stops, workflow workspace artifacts auto-refresh on lifecycle events in the web UI, and workflow dependencies are installed at runtime instead of requiring per-workflow baked images (#304, #308, #316, #318).
- Web UI workflow and persona management - added workflow statistics to the dashboard, hid test workflows from normal lists, added a workflow README modal, added copy-to-clipboard for workflow instructions, polished workflow pages, and introduced WebSocket-driven persona policy management (#283, #312, #340, #347).
- Apple container runtime backend and Rust fuzzing toolchain - added an Apple
containerruntime backend plus Rust fuzzing support for agent/container workflows (#290). - Cargo package proxying - the MITM package proxy now supports Cargo/crates.io, extending the package-install mediation model beyond npm, PyPI, and apt (#348).
- Memory MCP server 0.2.0 integration - upgraded the bundled memory server path with atomic-fact ingest, parent-context retrieval, new memory documentation, Docker build-context handling, and the separately tagged
memory-mcp-server/v0.2.0release (#335, #337, #339). - Vulnerability-discovery hardening - discovery now better resists masked findings, lost runs, background-wait ambiguity, and hanging harness validation (#268, #281).
- Workflow dependencies install at runtime - workflows no longer bake a per-workflow Docker image just to include dependency files; the runtime installs them in the active workflow environment (#308).
- Leaf subcommands parse arguments strictly - invalid trailing or misplaced arguments are rejected earlier for CLI leaf commands (#279).
- Builtin mode honors configured model provider - preflight/model-provider handling now respects the configured provider when running outside Docker (#287).
- Discussions linked from issue templates - the GitHub issue chooser now points users toward Discussions for support and exploratory topics.
- Codex provider-host WSS fallback - provider-host WebSocket upgrade attempts are fast-rejected so Codex falls back to HTTP instead of hanging through the MITM proxy (#341).
- Workflow teardown and gate CLI reliability - Docker teardown is drained before CLI exit to avoid network leaks, and bad-flag errors preserve the gate CLI's JSON/exit-code contract (#311, #314).
- Workflow harness boundedness - vulnerability-discovery harness validation and workflow harness execution now use hard-kill bounds to avoid indefinite hangs (#268).
- Trajectory capture robustness - missing-terminal token streams are classified as mid-stream aborts, improving retry/recovery decisions (#289).
- Docker UID/GID remap - benign Linux GID collisions are handled during agent UID/GID remapping (#333).
- Sandbox tool-error suggestions - UTCP manual prefixes no longer leak into tool-error suggestions (#301).
- Memory DB schema safety - incompatible memory databases are backed up before schema rebuild, and tests run serially to avoid model-download races (#337, #339).
- Bump
@provos/memory-mcp-serverto^0.2.0. - Bump
undicito^8.5.0. - Bump web UI dependencies including
vite,dompurify,hono,ws,qs,js-yaml,tar,form-data, and related transitive security updates. - Bump
actions/checkoutfrom 6 to 7.
- Broke a workflow runtime import cycle and added a
madgepre-push cycle gate (#277). - Added detailed daemon WebSocket JSON-RPC and workflow human-gate documentation.
- Marked evolve design slices as shipped and reconciled design documents with the implementation.
- Promoted mux over raw PTY in user-facing docs.
0.11.0 - 2026-05-18
- Vulnerability discovery workflow — the marquee 0.11.0 feature: an orchestrator-driven, hub-and-spoke FSM that hunts memory-safety and logic bugs in native code under a user-supplied threat model. Run it from the web UI (
ironcurtain daemon --web-ui→ Workflows → New run): the visual state-machine graph, per-state agent-message timeline, gate review panel, artifact browser, and live escalation modal are the intended way to follow a multi-hour discovery run — agent sessions span hours and produce many artifacts, which the CLI is not equipped to surface comfortably. The orchestrator routes between a structuralanalyzestate, a tiered harness pipeline (harness_design→ reviewer loop →harness_build→harness_validate), differential validation,discover/triagefor hypothesis confirmation, an LLMreviewpass, and a final humanreport_reviewgate; each agent state ships per-hypothesis directives written into a persistent investigationjournal.md. Harness build/validate uses a Tier 1 (isolated function) / Tier 2 (multi-component) / Tier 3 (full build) ladder picked mechanically from hypothesis scope, with libFuzzer/AFL++ coverage-feedback gating to catch the common failure mode where instrumentation never reaches the target. Domain content is factored into reusable skills —memory-safety-c-cpp(bug-class taxonomy with Class A/B/C delegate-library realism),harness-design-fuzzing,vulnerability-triage— loaded per-state, while ordering stays in the FSM. Conclude writes areport.mdindex plus onereport.h<N>.mdper hypothesis. Quota exhaustion (HTTP 429) and upstream stalls preserve the checkpoint so the run resumes where it stopped. CLI access viaironcurtain workflow start vuln-discovery "<task>"remains for scripting and debugging (#169, #175, #199, #198, #241, #229). - Workflow web UI — the intended way to run workflows. Opt-in Svelte 5 dashboard launched by
ironcurtain daemon --web-ui(defaulthttp://localhost:7400, bearer-token auth). The Workflows panel hosts the full lifecycle: start a new run (workflow picker, model selection, workspace path, task description), watch active runs through a live state-machine graph (dagre + SVG) with per-state agent-message timeline and markdown rendering, review gates with a workspace + artifact browser, and respond to escalations through an overlay modal with inline indicators. A Past section lists completed/failed/aborted runs by scanning~/.ironcurtain/workflow-runs/(checkpoints are now retained on success, and historical checkpoint-less runs are reconstructed from the message log via the shareddiscoverWorkflowRunsutility). The same daemon also serves the Sessions, Escalations, and Jobs views. Vuln-discovery and every other multi-agent workflow is meant to be driven from here — CLI workflow commands exist primarily for scripting and debugging (#154, #157, #163, #200). - Multi-agent workflow engine — the orchestration layer that powers the web UI: an XState v5 state machine with typed events, guards, agent/gate/deterministic states, declarative
when:verdict conditions on transitions, per-statemaxVisitscaps with bounded-loop escalation, transitionactions:(includingresetVisitCounts),freshSessioncontrol, artifact versioning that snapshots.v<N-1>backups on re-entry, and crash-resume via on-disk checkpoints. Workflow definitions are now packaged as directories (<name>/workflow.yaml) with YAML preferred over JSON, requireddescriptionfields surfaced in web UI tooltips and CLI inspect output, and arbitrary verdict strings for direct routing. The same engine runs identically behind the web UI (the intended interface),mux, and theironcurtain workflow start|resume|inspect|listCLI (provided for scripting and debugging) (#159, #163, #165, #169, #188, #190). - Workflow shared-container mode — opt in via
settings.sharedContainer: truein a workflow YAML. One Docker container and oneToolCallCoordinatorserve every agent state in the run; the orchestrator hot-swaps the activePolicyEnginebetween states viaPOST /__ironcurtain/policy/loadover a per-run Unix domain control socket, and the coordinator swaps undercallMutex → policyMutex. Audit entries are tagged withpersonaand written to a singleaudit.jsonlper run. Run artifacts consolidate under~/.ironcurtain/workflow-runs/<id>/withbundle/,states/<stateId>.<visitCount>/,audit.jsonl, andmessages.jsonl; nothing lands under~/.ironcurtain/sessions/for a workflow run. The newcontainerScopeprimitive lets workflows split states across multiple bundles when isolation is needed. Implements Steps 4–5 ofdocs/designs/workflow-container-lifecycle.md(#184, #186, #187, #191). - Agent skills (SKILL.md) — drop SKILL.md packages under
~/.ironcurtain/skills/<name>/to make purpose-specific guidance available to every Docker session; the merged set is staged so each agent's native skill discovery picks it up. Claude Code is pointed at the staging dir via--add-dir <parent>; Goose scans~/.config/goose/skills/<name>/SKILL.md. Each agent adapter declares its ownskillsContainerPathand the Docker infrastructure issues a dedicated read-only bind mount at that path. Workflows ship per-state skills via<workflow-pkg>/skills/<name>/SKILL.mdand an optionalskills: [...]field on agent states (omit = all workflow skills,nonesentinel = clean slate). Persona skills (~/.ironcurtain/personas/<name>/skills/) apply to standalone sessions. See WORKFLOWS.md (#227). ironcurtain doctorcommand — on-demand setup diagnostics that runs every health check independently and surfaces a single punch list (Node version, V8 sandbox viability, Docker availability with categorized errors, config parse, compiled policy / constitution / annotation drift, Anthropic OAuth/API-key presence and expiry, per-MCP-server env vars, and livetools/listagainst each configured server). Opt-in--check-apiadds a 1-token round-trip and OAuth refresh validation (#206).- Pre-flight checks for sandbox / Docker / OAuth —
start,daemon,bot, andworkflownow spawn a child Node process that imports@utcp/code-modeto validate the V8 sandbox before doing anything; SIGSEGV/SIGILL maps to "use Node 22–24",NODE_MODULE_VERSIONto "npm rebuild", and missing packages to "npm install". Success is cached at~/.ironcurtain/.preflight-ok. Docker availability returns a tagged union with targeted messages for ENOENT, permission denied, and "Cannot connect to the Docker daemon." OAuth-only-without-Docker now fails fast with a remediation hint instead of silently dropping into builtin and later 401-ing. Mux runs the same preflight in the parent before entering fullscreen so failures surface cleanly (#203, #213, #244). - Configurable Docker container resources with auto-clamp and probe — new
dockerResources: { memoryMb, cpus }field in~/.ironcurtain/config.json(each independently nullable;null= no limit), editable viaironcurtain config→ Docker Agent → Container resources. Values are auto-clamped againstos.cpus()/os.totalmem()before reaching Docker.ironcurtain doctorand the first-start wizard run a realdocker run --rm --cpus N --memory Mm <image> /usr/bin/trueprobe, parse Docker's stderr for rejection patterns, and suggest concrete lowered values. Necessary on small hosts (2-vCPU VMs) and on macOS Docker Desktop whereos.cpus()over-reports vs. the VM (#247). - Idle-timeout watchdog for Docker pull / build — replaces hard wall-clock timeouts on
docker pullanddocker buildwith a progress-aware idle watchdog (spawnWithIdleTimeout); legitimate multi-hour pulls of large base images (e.g.devcontainers/universal) now succeed, only true silence kills the child. A TTY-aware progress sink collapses the per-layer / per-step chunk flood into a single in-place updating status line (docker pull 4/12 layers 2 downloading); non-TTY stderr passes the raw transcript through (#250, #251, #260). - Linux UID/GID remap for agent containers — on Linux hosts where the user's UID/GID isn't 1000, the agent container now starts as root (
--user 0:0) with host UID/GID passed via env; the entrypoint runsusermod/groupmod/chownto renumber the bakedcodespaceuser to match the host, then drops privileges viaexec runuser -u codespace. Fixes the "Not logged in / Please run /login" symptom on Kali, NixOS, and other non-default-UID environments where bind-mounted credential files were unwritable. macOS is unchanged. Centralized inbuildAgentUidRemap()and shared by batch- and PTY-mode container creation (#245). - Per-persona / per-job memory opt-in —
PersonaDefinition.memory?: { enabled: boolean }andJobDefinition.memory?: { enabled: boolean }let users disable the memory MCP server for individual personas / cron jobs (default on). The globaluserConfig.memory.enabledkill switch still wins.MEMORY_SERVER_NAMEwas removed from the persona resolver's always-included set; the workflow orchestrator now spawns the memory relay only when at least one persona in scope opts in, closing a shared-container gap where the prompt advertised memory but the relay was absent. CLI surfaces the toggle viapersona create/edit,daemon add-job/edit-job, andironcurtain config -> Memory(#215). - Real-time LLM token stream observation — the MITM proxy taps Anthropic/OpenAI SSE and JSON responses inside Docker agent sessions and publishes structured
TokenStreamEvents on a shared pub/sub bus. Newironcurtain observecommand renders a Matrix-style data rain panel alongside formatted tool calls, results, thinking text, and assistant output by subscribing through the daemon's WebSocket. Workflow summarytotalTokensis now accumulated frommessage_endevents across all the workflow's agent sessions and displayed in the UI (#178, #211). - Matrix rain login page — web UI auth screen renders a Canvas 2D Matrix rain that assembles into the "IronCurtain" wordmark (#180).
IRONCURTAIN_MITM_ALLOW_ALL_HOSTSescape hatch — opt-in env var makes the MITM proxy treat every unknown host as a passthrough TCP tunnel, bypassing the CONNECT allowlist for HTTPS, plain HTTP, and WebSocket upgrades. Provider/registry traffic is unchanged (TLS termination and credential swap still apply); only unknown hosts get the wildcard. Logs aWARNon proxy startup so the posture downgrade is visible in the audit trail (#249).- Sudo and apt-get inside agent containers — Linux capabilities (SETUID, SETGID, CHOWN, FOWNER, DAC_OVERRIDE, AUDIT_WRITE) added so
sudoworks despite--cap-drop=ALL;python3-pipbaked into both base images;/etc/apt/apt.conf.d/90-ironcurtain-proxywritten into containers soapt-getroutes through the MITM proxy; MITM plain-HTTP forwarding fixed for Debian registry hosts (#164). - Annotation drift warnings — three drift-detection warnings between configured MCP servers and
tool-annotations.json(policy-load time, MCP-connect time, and stale-on-disk). Previously such mismatches surfaced as silent per-call default-denies via the policy engine'sstructural-unknown-toolfallback (#193). - Ollama-style model IDs in workflow YAML —
settings.modeland per-statemodelfields now accept opaquename:tagforms (e.g.glm-5.1:cloud) via a newlooseModelIdschema, while~/.ironcurtain/config.jsonslots stay on strictqualifiedModelId(#194).
- Silent fallback to the builtin agent is gone.
UserConfignow carriespreferredMode: 'docker' | 'builtin'(default'docker'); ifpreferredMode: 'docker'and Docker is unavailable, the session refuses to start with a remediation hint instead of silently dropping into builtin.--agentCLI flag continues to win over config.ironcurtain doctortreats declared-but-unmet preferences as failures (exit 1). Borderline-breaking for users who relied on the implicit downgrade — setpreferredMode: 'builtin'explicitly, or pass--agent builtin, to keep the old behavior. Closes feedback where testers ran in builtin mode for hours without noticing (#225). - MCP relays only spawn for servers the policy actually references.
extractRequiredServers(policy)walksrule.if.serverin the active compiled policy; unreferenced servers are dropped frommcpServersbefore relay subprocesses start. Default-deny would have rejected every call to them anyway. The workflow factory passes the per-scope union across all personas with the samecontainerScope(#208). - Spawn only MCP servers that successfully connect. When every backend of an MCP proxy subprocess fails to connect (missing env var, missing OAuth, etc.), the proxy now exits non-zero instead of staying alive with an empty tool list and causing every annotated tool to be flagged by the drift check (#259).
- Workflow definitions are directories. Bundled workflows ship as
<name>/workflow.yaml(with optional siblingskills/) rather than a single JSON file; YAML is preferred for new authoring. Custom.jsonuser workflows continue to work (#169, #227).
ironcurtain doctorexit code + preflight cwd resolution —doctornow exits non-zero when a declaredpreferredModecannot be honored; the sandbox-viability preflight resolves@utcp/code-modefrom the parent viacreateRequire().resolve()so runningironcurtainfrom outside the install tree (e.g. afternpm install -g, from~or/) no longer falsely reports a missing dependency (#266).- Workflow agents wedged by
ScheduleWakeup— the schedule built-in skill's tools are stripped from/v1/messagesrequest bodies for workflow agents, and conversation-history references to those tools (Claude Code'sToolSearchdeferred-tool fetcher surfaces them astool_referenceentries and<function>{...}</function>schema blocks) are scrubbed so Anthropic doesn't 400 the next request. Closes a workflow-abort failure mode reproduced in multi-hour runs (#258, #263). - Per-leg state directories — workflow forensic dirs (
states/{stateId}.{N}/) are now keyed on a disk scan vianextStateSlug()rather than the FSMvisitCounts, so resume legs of a single visit land in fresh dirs instead of overwriting the original leg'ssession.logandsession-metadata.json(#264). - Per-hypothesis discovery/triage files —
discoverandtriagestates write per-hypothesis files instead of overwriting a single shared artifact, preserving evidence across hypotheses (#264). - Status-block reprompt anchored on final response —
buildStatusBlockRepromptnow tells the agent to emitagent_statuson the last response only, fixing aharness_buildfailure where multi-checkpoint runs emitted intermediate blocks and a prose-only final turn that Claude Code's-pJSON output dropped (#254). - Rotate agent conversation id on upstream stall — Claude Code mid-stream kill (exit 143 + empty output) now retries the original prompt up to 2 times with a freshly-minted agent conversation id, instead of sending a "missing status block" reprompt against a consumed session id (#195).
- 429 quota-exhaustion resilience — workflow runs detect upstream 429s, short-circuit retries, preserve the checkpoint, and exit as aborted (not completed) so
workflow resumeaccepts the run once the quota window reopens. Sustained upstream stalls (exit=0+usage.output_tokens === 0+stop_reason === null) are now classified as resumable transient failures viaAgentResponse.transientFailure(#198, #210). - MITM token routing in shared-container workflows — the proxy's routing
sessionIdis now mutable and flipped by the orchestrator around eachexecuteAgentState; per-responsesidAtAttach/sidForToolResultssnapshots prevent a mid-stream flip from splitting a single SSE response across two ids (#211). - Deterministic-state failures forward to the next agent — orchestrator now propagates deterministic-state errors as agent_status notes so downstream agents see the failure (#242).
- MCP
isErrorsurfaces to Code Mode — sandbox now throws on MCPisErrorso Code Mode LLMs see tool failures instead of silently consuming an error envelope (#185). - Docker batch mode multi-turn context — switched from
claude -p --continue(silently no-ops in non-interactive print mode) to--session-id <uuid>on first turn +--resume <uuid>thereafter, fixing context loss in web UI, cron, and workflow Docker sessions (#177). - Mux PTY session MITM bridge — mount the bundle sockets dir so the MITM bridge is reachable (#209).
- Web UI bad-auth-token recovery — UI no longer wedges on a malformed bearer token; surfaces a re-auth flow (#182).
- Web UI stuck at
waiting_humanafter gate rejection — phase tracking refreshes after a gate verdict (#173). - Web UI Matrix rain review fixes — accessibility and performance polish to the login Canvas (#183).
- Web UI markdown rendering — use
prose-markdownclass for consistent typography (#170). - Web UI e2e tests — repair after mobile drawer + gate auto-fetch changes (#212).
- Goose PTY readiness probe — stop spawning a doomed agent process during the readiness check (#226).
- Shared
validatePolicyDirhelper —src/config/validate-policy-dir.tsrealpath-resolves candidate policy directories and enforces containment under the IronCurtain home or the package config dir; CLI flags, theloadPolicyRPC, and session creation all funnel through it (#207). - Shared
applyAllowedDirectoryToMcpArgshelper — single source of truth insrc/config/index.tsfor keepingmcpServers.filesystem.argsin sync with the activeallowedDirectory; fixes stale paths in shared-container workflow runs. - Audit stream errors latch —
AuditLognow remembers stream errors and surfaces them synchronously on the nextlog()instead of silently dropping entries. - Workflow run directory hardened at 0o700 —
chmodSyncenforces the mode so the control socket and audit log are protected by filesystem permissions. - Zero-constraint whitelist no longer blanket-approves
add_proxy_domain(#151). - Conversation state directory mounted in Docker batch mode (#152).
- Base-URL env vars validated —
ANTHROPIC_BASE_URL,OPENAI_BASE_URL,GOOGLE_API_BASE_URLare nowz.url()-validated at config load (#257). npm test -- <file>forwards the filter to vitest.- Claude Code v2 telemetry and MCP marketplace endpoints allowed through the MITM proxy.
- Sanitize agent output by escaping NUL bytes and truncating to 32KB.
- Hash workflow artifact metadata, not contents — avoids re-hashing huge artifacts on each transition.
- Bump
uuidfrom 13.0.0 to 14.0.0 (#233) - Bump
axiosfrom 1.15.0 to 1.16.0 (#236) - Bump
honofrom 4.12.14 to 4.12.18 (#237) - Bump
fast-urifrom 3.1.0 to 3.1.2 (#238) - Bump
postcss(dev) from 8.5.6 to 8.5.14 (#235) - Bump
actions/github-scriptfrom 8 to 9 (#166) - Recurring vulnerable-package upgrades.
- PolicyEngine + AuditLog centralized into
ToolCallCoordinator— the security pipeline (tool-call-pipeline.ts) now owns all policy/audit/circuit-breaker/whitelist state; MCP proxy server subprocesses became pure relays (#179). DockerInfrastructurebundle with explicit lifecycle — reframes the implicit "bag of stuff the session owns" into a typed handle with pairedcreateDockerInfrastructure/destroyDockerInfrastructureand anownsInfraflag onDockerAgentSession. Pure refactor, prerequisite for shared-container mode (#184).- Module layering rules — guidance added to per-directory
CLAUDE.mdfiles;src/pipeline/is offline tooling that live-session runtime must not value-import. URL normalizers, list matcher, session error hierarchy, server listing, llm-logger, and misplaced constants moved to their correct layers; event bus generified;WorkflowManagermoved out ofsrc/web-ui/(#216, #217, #218, #219, #220, #221, #222, #223, #224). - TokenStreamBus migrated to module singleton (#189).
0.10.0 - 2026-04-01
- Custom API gateway support — route LLM traffic through API gateways (LiteLLM, Ollama, etc.) via
ANTHROPIC_BASE_URL,OPENAI_BASE_URL, andGOOGLE_API_BASE_URLenvironment variables or config file fields; the MITM proxy intercepts container traffic as usual but forwards upstream to the custom gateway; Code Mode passesbaseURLdirectly to AI SDK providers (#148) --modelCLI flag — override the agent model onstartandmuxcommands (e.g.,--model jaahas/qwen3.5-uncensored:35bfor Ollama);parseModelId()now handles non-provider colon-separated tags; Claude Code adapter passes the model to the container via--modelandIRONCURTAIN_MODEL(#148)- Haiku-based server pre-filter — cheap Haiku pre-filter step during policy compilation skips servers irrelevant to the constitution, saving expensive Opus/Sonnet LLM calls; configurable via
prefilterModelIdin user config (#146) - Parallel server compilation — compile all servers concurrently via
Promise.allSettledwithp-limitthrottling (10 servers, 8 LLM calls); multi-line TTY progress display shows all servers simultaneously; addsHTTPS_PROXY/HTTP_PROXYsupport for AI SDK providers (#144) annotate-toolsrequires explicit target —--server <name>or--allflag required instead of always annotating everything; single-server mode merges with existing annotations; includes--helpand server name validation (#142)- WebSocket and plain HTTP CONNECT tunnels — WebSocket upgrade handling for
ws://viaHTTP_PROXY; passthrough CONNECT tunnels use raw TCP tunneling instead of TLS MITM, fixing plain HTTP and WebSocket connections (#139) - SSH agent socket in sandbox — forward
SSH_AUTH_SOCKinto Docker containers for git operations requiring SSH keys - Workspace display in resume picker — mux
/resumepicker shows the workspace directory (with~/shortening) when a session was started with--workspace(#149) - Enhanced Docker base images — additional packages (
build-essential,cmake, graphics/Qt libraries, common Python native deps) and passwordless sudo in arm64 image
- x86_64 Dockerfile missing node-gyp — install
node-gypglobally inDockerfile.baseto match the arm64 variant; fixes Docker build failures on Windows/WSL2 (#147) - Stale Docker containers on resume — clean up containers from previous sessions before starting a new one (#134)
- Mux exited tab cleanup — auto-remove exited tabs to restore the splash screen when all sessions end
- Plain HTTP passthrough in MITM proxy — fix plain HTTP connections through CONNECT tunnels for passthrough domains (#133)
- Integration test reliability — use local
mcp-server-filesystembinary instead of global install
- Bump
node-forgefrom 1.3.3 to 1.4.0 - Bump
path-to-regexpfrom 8.3.0 to 8.4.0 - Bump
picomatch(security fix)
0.9.1 - 2026-03-25
- macOS mux text selection — replace X11 mouse tracking with alternate scroll mode on macOS so native text selection (Shift+drag) works in Terminal.app; scroll wheel works in command mode via arrow key mapping (#130)
- macOS OAuth Keychain refresh — refresh expired OAuth tokens from the macOS Keychain instead of silently falling back to API key auth; write refreshed tokens back to the Keychain via
security add-generic-password -U; enableOAuthTokenManagerself-refresh for Keychain-sourced credentials during long sessions (#131)
0.9.0 - 2026-03-24
- Third-party OAuth onboarding — full OAuth 2.0 flow for MCP servers with PKCE, callback server, token store with auto-refresh, interactive scope picker for Google services,
ironcurtain authCLI with setup guides, import, revocation, and incremental consent (#108) - Google Workspace MCP server integration — credential-file rendezvous pattern (access-token-only, no refresh token in MCP server),
TokenFileRefresherwith proactive refresh, strict filesystem sandbox withdenyRead: ["~"], dynamic Node path discovery for nvm/volta/fnm/asdf, and newshare-permission,email-address,email-bodyargument roles (#113) - Per-server policy compilation — compile each MCP server independently with its own compile-verify-repair cycle, Zod-enforced server scoping to prevent cross-server rule leakage, per-server artifact caching for incremental recompilation,
--serverCLI flag for single-server debugging, annotation batching for 100+ tool servers, and point-fix repair mechanism that preserves passing rules (#118) - Policy-mediated MCP access for dynamic lists — all MCP tool calls during list resolution are gated through a read-only PolicyEngine via the MCP proxy server; includes
--no-mcpflag, compiled read-only policy covering all servers, and error surfacing for failed MCP calls (#122) - Escalation picker UI — tab-per-escalation floating box overlay with single-key actions (a/d/w for approve/deny/whitelist), batch resolve-all via Shift+A/D, auto-open on new escalations with smart suppression, and narrow-terminal guards (#112, #116)
- Ephemeral approval whitelisting — whitelist domains, directories, or identifiers during escalation approval for session-scoped auto-approve; role-driven pattern extraction,
/approve+syntax across CLI/mux/listener, full audit trail (#109) - Proxy MCP server for dynamic domains — virtual tools (
add/remove/list_proxy_domain) give Docker agents runtime control over MITM proxy domain allowlists via an HTTP control API on a host-only socket (#126) - Multiple parallel mux sessions — per-session ownership via
muxIdreplaces the global escalation-listener lock; per-session Docker networks prevent cross-session teardown; orphan detection via PID liveness checks (#110) - Auto-save session memory — forced final turn after task completion prompts the agent to store session context via
memory.store; works across all transports, configurable viamemory.autoSave(#124) - Tool argument validation against input schemas — proxy validates argument names against MCP tool
inputSchemabefore forwarding, returning actionable errors with valid parameter names so the agent can self-correct (#125) - Scenario argument schema validation —
inputSchemastored on tool annotations and validated at the Zod level during scenario generation and verification, catching wrong argument names before they reach the LLM (#122)
- Google Workspace token expiry — immediate refresh check on
TokenFileRefresher.start()andforceRefresh()that bypasses the 5-minute early-return threshold, preventing tokens from expiring mid-session (#123) - Sandbox arg resolver mangling npm packages — skip scoped (
@org/pkg) and versioned (pkg@1.2.3) specifiers when resolving relative args to absolute paths (#119) - Mux PTY key forwarding — forward raw terminal-kit bytes instead of mapping key names, fixing broken Shift+Tab, F-keys, and Alt+arrow sequences (#127)
- Claude Code WebFetch in Docker — add
skipWebFetchPreflightandHTTPS_PROXYto Docker settings so WebFetch works through the MITM proxy (#129) - Docker exec timeout logging — detect and log timeout duration for docker exec calls; guard against empty Signal responses (#128)
- Fetch server JSON responses — return structured
{ error, status, headers, body }JSON fromhttp_fetchinstead of concatenated plain text (#114, #115) - SSH agent forwarding — forward
SSH_AUTH_SOCKto the MCP server proxy process, fixing 60-second hangs ongit push - Mux shutdown spinner — exit fullscreen before showing the shutdown spinner so it is always visible on
/quit - workspace:* protocol — replace pnpm-specific
workspace:*with semver range for npm compatibility (#111)
- Remove sideEffects from tool annotations — the boolean was nearly useless (81/85 tools marked true); argument roles already capture security-relevant characteristics (#118)
- Remove monolithic compilation path — all compilation routes through
runPerServer(), deleting ~577 lines of dead code (#122) - Increase Docker container resources — bump defaults to 8 GB memory and 4 CPUs for resource-intensive workloads (#107)
- storedAnnotations mandatory throughout pipeline — single required code path after monolithic removal, eliminating optional guards and fallbacks (#122)
0.8.0 - 2026-03-15
- Secure package installation proxy — npm and PyPI registries are proxied through the MITM layer with metadata filtering (age-gate quarantine, allow/denylists), tarball backstop validation, and per-package audit logging; containers can now
npm installandpip installpackages at runtime without direct network access (#101) - Debian apt registry proxy —
apt-get installworks inside Docker containers by proxyingdeb.debian.organdsecurity.debian.orgthrough the MITM proxy; GPG-signed metadata passes through unmodified,.debdownloads go through backstop validation (#105) - Memory MCP server integration — persistent memory with semantic search, LLM summarization, and automatic compaction; integrates with personas and sessions for context-aware recall (#95, #98)
- Persona picker in mux mode — interactive persona selection overlay in the
/newflow with workspace browsing pre-filled from persona defaults (#104) - Session resume for Docker PTY sessions — resume previous sessions with
--resume, conversation state persistence, snapshot validation, and session scanner UI (#94) - Server-namespace tool naming — tools use
serverName__toolNameformat with prefix stripping for cleaner display (#102) - Pre-installed Python 3.12 in Docker base images — containers no longer need to download Python at runtime, preventing failures in network-isolated environments
- PyPI sidecar file handling — strip PEP 658/714 sidecar suffixes (
.metadata,.provenance) before filename parsing in the registry proxy, fixing fail-closed denials for pip/uv metadata fetches (#105) - Memory context missing memories — fix
memory_contexttool not returning memories and LLM config passthrough (#103) - Roots expansion race condition — retry tool calls after roots expansion with 200ms delay when the filesystem server hasn't finished processing updated roots (#93)
- Harden arm64 Docker base image — expand system packages with build tools, graphics/Qt libraries, X11/XCB deps, and fonts needed for Python packages with native extensions (#105)
- Upgrade vulnerable package versions
- Re-enable OS-level sandbox for git MCP server — upgrade
@anthropic-ai/sandbox-runtimeto 0.0.42 which supports selective network access on Linux; git server now runs sandboxed with filesystem restrictions (~/.gnupg,~/.awsdenied) and network limited to GitHub/GitLab domains - Use
UV_NATIVE_TLSin Docker base images for MITM CA trust with uv - Shared Python install directory (
/opt/uv-python) across users - Use Debian Trixie base for arm64 image (GLVND transition)
0.7.2 - 2026-03-11
- Mux command-mode input retention — preserve the input buffer when toggling between command mode and PTY mode with Ctrl-A; previously any typed text was lost on mode switch
- Stay in command mode after /new — spawning a new session via
/new(quick-spawn or directory picker) now returns to command mode instead of switching to PTY mode
0.7.1 - 2026-03-10
- macOS PTY session networking — reverse PTY socat direction in the sidecar so the host can reach the container's PTY socket (MCP/MITM remain container→host); skip the readiness probe for TCP since the container's socat only accepts one connection; add retry logic in
attachPtythat polls until the connection receives data; allocate dynamic host ports viafindFreePort()to avoid collisions between concurrent PTY sessions (#89) - Filesystem server path in PTY sessions — export and reuse
patchMcpServerAllowedDirectory()so the filesystem MCP server's directory arg points to the actual session workspace instead of the stale default fromloadConfig()(#87) - macOS node-pty spawn-helper — auto-fix missing execute permission on the node-pty
spawn-helperbinary at startup; show actionable error if chmod fails (e.g., read-only npx cache) - MITM leaf certificate renewal — track per-cert expiry and regenerate 1 hour before the 24-hour validity window closes, preventing "SSL certificate has expired" errors in long-running sessions (#84)
- OAuth token endpoint — update refresh endpoint from
console.anthropic.comtoplatform.claude.com/v1/oauth/token - Sentinel triage — widen the
sincewindow from 24 hours to 30 days so expired challenges are not silently filtered; useincludes()for marker matching - Upgrade vulnerable package versions
- Persona system — named profiles bundling a constitution, compiled policy, server filter, persistent workspace, and memory file under
~/.ironcurtain/personas/<name>/; CLI commands (persona create/list/compile/edit/delete/show),--personaflag forstart, Signal/new [persona], cronpersonafield, and session metadata persistence for--resume(#82) - Auto-generate constitutions for cron jobs — Code Mode session with read-only policy explores the workspace and MCP servers to produce a tailored constitution (#77)
- Design documents for Memory MCP Server and Session Resume
- Extract
isUserContextTrustedhelper fromhandleCallToolfor independent testability (#86) - Extract
formatAnnotationsSummaryto eliminate duplicate annotation-formatting logic (#81) - Remove
extractPathsHeuristicfrom policy engine; rely solely on tool annotations for path extraction (#78) - Flatten
resolveDefaultGitRemotewith named git helpers (#75)
- Coverage for
docker/audit-log-tailer,pipeline/pipeline-shared,pipeline/generate-with-repair,pipeline/list-resolver,cron/format-utils, and signal formatting modules (#72, #73, #74, #80, #83, #85)
0.7.0 - 2026-03-06
- Cron mode — unified daemon with per-job policy, scheduled sessions via
ironcurtain cron add/list/remove/run, job-specific constitutions and compiled policies (#63) - Daemon & cron polish — Signal transport fixes, CLI help improvements, job management enhancements (#70)
- Goose agent adapter — run Goose as an external agent in Docker Agent Mode with auto-generated YAML config and provider-specific env vars (#55)
- Conditional argument role assignment — role specs can include conditions evaluated against tool call arguments for multi-mode tools (#60)
- Mux bracketed paste and multiline input — paste detection with bracketed paste sequences, multiline editing support (#57)
- Sentinel triage workflow — auto-close expired agent challenges via GitHub Actions
- Ensure PTY session cleanup on mux shutdown
- Don't auto-scroll to bottom on new mux output (#61)
- Stay in command mode after sending trusted input
- Bypass MCP SDK client-side
outputSchemavalidation on error responses (#54) - Allow workspace to contain in-package protected paths
- Remove duplicate image-building methods from
DockerAgentSession(#68) - Extract
DEFAULT_DENY_RESULTandruleToResult()in policy engine (#62) - Extract
pushColorSgrhelper inbuildSgrSequence(#65) - Merge identical ESCAPE and Ctrl-C branches in
handleCommandKey(#66)
0.6.0 - 2026-03-03
- Terminal multiplexer —
ironcurtain muxprovides a terminal multiplexer for managing multiple PTY sessions with tab management (/new,/tab N,/close), trusted input forwarding, workspace picker (fresh sandbox or existing directory via interactive file browser), mouse wheel scrollback, and escalation overlay for informed approve/deny decisions; uses headless xterm.js with SGR attribute rendering and resize propagation - Matrix-style splash screen — mux startup shows a Matrix rain animation that forms "IronCurtain" in ASCII art with usage info; small-terminal fallback for narrow viewports (#53)
--workspaceflag —ironcurtain start -w ./pathpoints the agent at an existing directory instead of a fresh sandbox; validates against root, home,~/.ironcurtain/, and bidirectional protected-path overlap (#51)- OAuth token auto-refresh in MITM proxy — proactive refresh before token expiry and reactive 401 retry as fallback for long-running Docker PTY sessions; read-only mode on macOS to avoid rotating Keychain-sourced refresh tokens; security hardening for transfer-encoding stripping, credential injection scoping, and 0600 file permissions (#50)
- Graceful process shutdown — unref intervals and stdin in escalation watcher, listener, agent session, and escalation handler to prevent blocking process exit
0.5.1 - 2026-03-01
- Reverse path rewriting for Docker agent sessions — MCP server results containing host sandbox paths are now rewritten back to
/workspacebefore reaching the agent, completing the symmetric path translation;CONTAINER_WORKSPACE_DIRextracted as a shared constant (#49) - Improved Docker agent system prompt — remove bind-mount details and host path exposure, replace with clear guidance on when to use
execute_codevs built-in tools; add attribution guidance for IronCurtain (#49)
- Skip MCP servers with missing environment variables instead of crashing — graceful degradation when Docker
-e VAR_NAMEforwarding references unset host env vars - Resolve PTY size mismatch in Docker agent sessions — set initial PTY size via env vars before exec'ing Claude, add verify+retry loop with
check-pty-size.sh, usepgrep -x claudefor reliable process detection - Stabilize TCP transport test on macOS — use message-flow synchronization instead of probe-based polling
0.5.0 - 2026-03-01
- PTY mode for Docker agent sessions —
ironcurtain start --ptyprovides interactive terminal access to Claude Code running inside Docker, with host-side Node.js PTY proxy bridging the user's terminal to the container via UDS (Linux) or TCP (macOS), SIGWINCH forwarding, and Ctrl-\ emergency exit (#43) - Escalation listener TUI —
ironcurtain escalation-listenercommand with a terminal dashboard that aggregates escalations across multiple concurrent PTY sessions; approve/deny via/approve Nand/deny Ncommands with incremental rendering to preserve input state (#43) - OAuth support for Docker agent sessions — auto-detects credentials from
~/.claude/.credentials.json(viaclaude login) or macOS Keychain and prefers them over API keys; real tokens never enter the container — a fake sentinel is swapped for the real bearer token by the MITM proxy (#47) IRONCURTAIN_DOCKER_AUTH=apikeyenvironment variable to force API key mode when both OAuth and API key credentials are available- GitHub MCP server integration — add the official GitHub MCP server as the 4th built-in server with 41 annotated tools,
github-ownerargument role with case-insensitive canonicalization, owner-scoped policy rules, and GitHub identity discovery for policy customization; graceful degradation when Docker is unavailable (#38) - Audit log PII/credential redaction — masks credit cards (Luhn-validated, keeps first/last 4), US SSNs (area/group/serial validated, keeps last 4), and API keys (OpenAI, GitHub PAT, Slack, AWS) at any nesting depth; enabled by default (#16)
- Improved MCP error messages — extract meaningful error messages from McpError exceptions instead of opaque schema validation errors; track git server working directory and display it in escalation requests so reviewers know which repo is affected (#46)
- Signal bot multi-session support — managed session map with auto-incrementing labels,
#Nprefix for one-shot message routing without switching sessions, configurable max concurrent sessions, and escalation reply auto-routing with disambiguation - Interaction log — JSONL logging of each conversational turn (user prompt + assistant response) to
{sessionDir}/interactions.jsonlvia new BaseTransport abstract class - First-start wizard safe to re-run — loads existing config, pre-fills defaults from current settings, skips prompts for values already configured, accumulates changes atomically so cancelling mid-wizard never writes partial state (#34)
- lint-staged integration for pre-commit formatting and linting checks
- Mount only sockets subdirectory into Docker containers — previously the entire session directory was bind-mounted read-write, giving a compromised agent access to escalation files and audit logs; now only the
sockets/subdirectory is mounted (#42) - Eliminate ReDoS risk in credit card regex — replace nested quantifiers with flat pattern to avoid exponential backtracking
- Update minimatch to 10.2.4 (CVE-2026-27903)
- Display escalation context in listener dashboard — the TUI was not rendering the context field even though all other display paths did
- Defer session map removal until after successful close so the session remains trackable and retryable if close fails
- Spawn tsx directly instead of via npx to prevent orphaned child processes — npx's intermediate
sh -cprocess doesn't forward SIGTERM, causing "close timed out" warnings in vitest
- Reduce test execution time from 102s to 33s by replacing fixed setTimeout delays with fake timers and event-driven polling helpers
- Upgrade production and development dependencies
- Restructure README with PTY/escalation-listener and web search sections
- Move architecture diagrams from README into SANDBOXING.md
- Clarify audit redaction is enabled by default
0.4.1 - 2026-02-27
- Progressive tool disclosure for Docker agent mode — replace the full inline tool catalog (~3,150 tokens) with compact server-names-only listing (~770 tokens, 75% reduction) and on-demand
help.help()discovery (#31) - Protect entire
~/.ironcurtain/directory with scoped sandbox exclusion, preventing new files (e.g. CA certs) from being unprotected (#30)
- Fix Docker agent web search — the MITM proxy strips server-side tools but the prompt incorrectly told the agent they would work, causing hallucinated results; now directs the agent to use the MCP
web_searchtool with concrete examples - Fix macOS Docker Desktop connectivity via socat sidecar — containers on
--internalnetworks cannot reach the host, so a sidecar bridges the internal network to host-side proxies (#32) - Loop boilerplate tag removal in fetch server to prevent nested-tag bypass (CWE-116)
- Bound
resolveRealPathancestor walk with explicit depth limit
- Refactor MCP proxy server main function into smaller, purpose-oriented utilities
- Nix development shell via flake.nix (#29)
- Run CI on macOS in addition to Linux
- Update SECURITY_CONCERNS to document socat sidecar isolation as equivalent to Linux
--network=none - Enhance CONTRIBUTING and TESTING documentation with pre-commit hook setup
0.4.0 - 2026-02-25
- Signal messaging transport -- run IronCurtain sessions via Signal messages (#27)
- macOS Docker Desktop support for Docker Agent Mode via TCP proxy transport, ARM64 base image, and
--internalnetwork egress restriction (#24, #25, #28) - Content-Encoding filtering in MITM proxy to reject unsupported encodings
- Protect
.envand user config from agent access (#23) - Cross-platform reliability fixes for audit log tailing and sandbox path resolution
- Pin Node 22 LTS and cap engines below Node 26 (#20)
- Design doc for TCP mode network egress restriction with macOS test plan
- Signal messaging transport design and brainstorm docs
0.3.1 - 2026-02-25
- Web search tool with multi-provider support (Brave, Tavily, SerpAPI)
- Web search configuration in interactive editor and first-start wizard
- CONFIG.md documenting all configuration options
- Strip server-side injected tools from Anthropic API requests
- Fix constitution loading to fall back to bundled user constitution base
- Thread sandbox directory path to policy verifier for accurate scenario generation
- Add
not-allowscenario decision type for flexible handwritten scenario verification - Fix
deepMergeConfigto support section removal via empty object sentinel - Improve MITM proxy request filtering for Docker Agent Mode
- Consolidate design docs into single directory
0.3.0 - 2026-02-24
- TLS-terminating MITM proxy for Docker Agent Mode (#17)
- Docker agent broker with auto-mode selection (#14)
- First-start wizard for new installations (#15)
- Policy customization pipeline and default-deny model
- Prompt caching (#12)
- Add show-system-prompt script for MCP server tool listing
- Enable strictTypeChecked ESLint and eliminate non-null assertions (#13)
- Update README with customize-policy workflow and current constitution
- Correct minimum Node.js requirement to 20 (not 18)
- Add Semgrep CI and .semgrepignore for build artifacts
- Rename design docs
0.2.0 - 2026-02-22
- Add Readability-based article extraction to fetch server (#11)
- Allow user-local constitution override (#9)
- Improve escalation timeout handling in proxy and sandbox
- Implement escalation timeout for UTCP SDK client requests
- Add interactive configuration command and enhance user config management
- Add demo GIF and update README for enhanced visualization
- Add comprehensive review instructions for copilot
- Update Node.js engine requirement to >=20.19.0
- Move constitution freshness check into main
- Use tilde paths in shipped policy artifacts (#10)
- Add timeout to root expansion and use annotation-driven path filtering (#8)
- Pin marked to v15 for marked-terminal compatibility
- Trigger CI on master branch, not main
- Test on Node 22 and 24 (isolated-vm requires newer V8)
- Slim RoleDefinition interface and relocate URL utilities (#7)
- Update PolicyEngine terminology and clarify evaluation phases
- Centralize version string via
src/version.ts - Add GitHub Actions release workflow
- Dependency updates via Dependabot
0.1.0 - 2026-02-20
Initial public release.
- Secure agent runtime with trusted process mediation
- Policy engine with two-phase evaluation (structural + compiled rules)
- LLM-powered policy compilation pipeline (annotate, compile, verify)
- OS-level sandboxing for MCP servers via bubblewrap/socat
- Multi-turn interactive sessions with escalation handling
- Auto-approver for LLM-based escalation decisions
- Auto-approver with argument handling and sanitization
- Dynamic lists for policy rules (domains, emails, identifiers)
- Fetch server for HTTP GET requests
- LLM-assisted constitution customization CLI
- Resource budget management (tokens, steps, wall-clock, cost)
- Auto-compaction for message history management
- Circuit breaker for repeated tool call detection
- MCP Roots protocol integration for dynamic directory management
- ArgumentRole registry for annotation-driven argument normalization
- Multi-provider model support (Anthropic, OpenAI, Google)
- Interactive configuration command (
ironcurtain config) - Session logging with credential redaction
- CI pipeline with Node 22/24 matrix testing
- Code of Conduct, Contributing guidelines, Security policy