Skip to content

v2.17.0

Choose a tag to compare

@nokhodian nokhodian released this 28 Sep 01:50
· 860 commits to main since this release

[2.17.0] — 2026-09-28

Added

  • monomind agent exec --access full (#355), part of the Coder mode epic (#364). The claude runtime can now run a turn with unrestricted native tool access (canUseTool allows everything, permissionMode: "bypassPermissions") instead of the default scoped allow-list — guarded against root, unsupported runtimes, and a missing/invalid --cwd. New capability agent-exec-full-access and agent scan --json's full_access field.
  • monomind agent exec --settings none|<csv of user,project,local> (#356). A non-none value (claude runtime only) loads the normal Claude Code setup for the turn — CLAUDE.md, skills, hooks, and project/user MCP servers — and appends the caller's system prompt to Claude Code's own preset instead of replacing it; --settings none (default) stays byte-identical to before. New status NDJSON event reports SDK startup progress, and a --startup-timeout watchdog (default 30s) reports a clear error instead of hanging if the SDK never reports ready. Capability agent-exec-settings.
  • monomind agent exec emits tool_activity start/end events for the agent's own native tool calls (#357), capability agent-exec-tool-activity. Previously only --tools stdio bridged calls were visible on stdout; native calls (Bash, Edit, Write, Read, …) now get matched, size-capped events correlated by the SDK's own tool_use id, in every access mode. Edit/MultiEdit carry old_string/new_string, Write carries file_path/content; a denied call (scoped mode) closes with ok:false, denied:true; a --timeout or cancel closes any still-open call with ok:false, cancelled:true before done. parent_tool_use_id nests subagent calls. Non-Claude runtimes map their own best-effort liveness signal to a start-only event; agent scan --json reports each runtime's fidelity as tool_activity_fidelity.
  • monomind init --project <dir> --if-missing --json (#358) — headless, idempotent workspace init for coder sessions. --project <dir> targets a directory other than the cwd; --if-missing creates only files that don't exist yet and never touches an existing CLAUDE.md/AGENTS.md/.claude/settings.json/.mcp.json (idempotent — a second run creates nothing); --json prints {root, created, skipped, claude_project_registered, duration_ms} on stdout with human output suppressed; --no-graph skips the Monograph build for a faster init; --register-claude-project best-effort registers ~/.claude/projects/<slug>/ without a model call. New capability init-json — see doc/agent-exec-protocol.md §11.
  • Coder mode threat model + guardrails (#360). agent exec --access full now appends a one-line JSON audit record per turn (ts, cwd, runtime, session_id?, exit_code, tool_calls) to ~/.monomind/logs/agent-exec-full-access.log (MONOMIND_FULL_ACCESS_LOG overrides), regardless of how the turn ended — never for scoped access, and best-effort (a write failure never fails the turn). No MCP tool, org-runtime session, workflow/routine node, UI route, or hook can set or raise access: "full" — audited and pinned by regression tests. New threat-model doc: doc/concepts/coder-mode-security.md.
  • Coder mode for a specific org role — policy.access: "full" (#365, part of the Coder mode epic #364), capability org-role-full-access. A role can now run with the same unrestricted native tool access as agent exec --access full — no allow-list, no OS sandbox, no authority mask, no per-tool approval gate; budgets are still enforced. It is human-only, opt-in per role: monomind org role set-access <org> <role> full|scoped refuses outright when it detects an agent-context env var (CLAUDECODE, CLAUDE_CODE_ENTRYPOINT, MONOMIND_ORG_ROLE, MONOMIND_SDK_AGENT, or the new MONOMIND_AGENT_EXEC set on agent exec's runner child env) — not overridable by --yes-i-understand or a TTY — so a scoped chat/org can't reach a grant through an allowed monomind org … Bash prefix; outside that, full needs an interactive confirmation or --yes-i-understand. It is the only place that writes access_ack, which now carries both a hash over the role's security-relevant config (prompt, runtime, model, tool providers, reports_to, coder-mode settings, plus the org's unattended/taint knobs) and a sig — an HMAC-SHA256 of that hash under a machine-local key created on first grant and stored in the operator-credential directory, which every scoped/sandboxed role is denied Read/Edit on, so a config-writing path that can merely recompute the public hash still can't forge a grant the runtime will honor. The runtime verifies sig (timing-safe) before ever trusting hash, and recomputes both every session start: no signature, an invalid one, or a covered field changing since the grant drops the role to scoped (access_state: "suspended"); a scheduled/daemon run without run_config.allow_unattended_full_access also runs it scoped ("unattended-blocked"). org validate now errors on an unsupported runtime, a policy.git explicitly authored below push alongside access: "full", and taint — a full-access role that itself ingests untrusted input, or is reachable from one via reports_to, unless the path is named in run_config.accept_full_access_taint. Taint errors are also checked at every session start, so a role that becomes reachable from untrusted input after its grant runs scoped. org status --json gains roles_access for any role that declares it.
  • monomind agent exec --access full now kills the whole agent process tree on Stop/timeout/budget, and reports background survivors (#359, part of the Coder mode epic #364). The claude CLI is now spawned as the leader of its own process group; a cancel frame, --timeout, or --budget-usd breach SIGTERMs (then SIGKILLs after a 5s grace) the WHOLE tree, not just the CLI process. A single point-in-time check turned out to be insufficient against the real, installed Claude Code CLI (live-verified during development): it spawns each Bash-tool shell call as the leader of its OWN process group, and that shell — or a background job's whole launching chain — often exits within milliseconds of starting the job. orgrt/process-tree.ts's trackDescendants now finds the turn's processes by a per-turn MONOMIND_EXEC_TREE env marker every descendant inherits (so a nohup … & job reparented after its shell exited is still found, regardless of timing), plus continuous 50ms sampling that remembers every process-group id it saw, for jobs that clear their own environment. On a normal end_turn, background jobs are left running (the "start a dev server, use it next turn" flow still works) but now reported: done gains background_pids: number[]. Residual, documented v1 limitation: a job that clears its environment AND whose launching chain exited between samples can still go undiscovered. Implemented at the ClaudeAgentRunner layer, so a future full-access org role (#365) gets the same protection automatically. Scoped mode is unaffected. Windows falls back to taskkill /T for the kill and does not yet support background_pids discovery (omitted, not fabricated as empty). New capability agent-exec-background-pids.

Fixed

  • agent exec --tools stdio honors a cancel frame even when no tools are declared. stdin was only read when a tools file or tool names were given, so a caller's cancel was silently ignored and the turn ran on.
  • A second dashboard server no longer takes over the first one's pairing token when the first is too busy to answer. A secondary decided whether the primary recorded in .monomind/control.json was alive only by probing its /api/status (3 tries, 1.5 s each); a primary whose event loop was blocked longer than that looked dead, so the secondary overwrote dashboard-token — logging out the primary's clients — and never wrote its own dashboard-token-<port>. A live recorded pid now also keeps it a secondary.

npm: monomind@2.17.0, @monoes/monomindcli@2.17.0