Skip to content

Releases

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 17:43
3421a3c

Multi-model runtime

  • Native Kimi and GLM profiles share provider routing, model budgets and scoped
    credentials across the CLI and app-server clients. Unknown prices are shown
    as unavailable. See multi-model configuration.
  • Claude Agent SDK 0.3.310 is an explicit experimental engine, with controlled
    DeepCode tools, approvals, snapshots and isolated sessions. Native remains the
    default. To roll back, select engine: "native" and start a new session;
    existing SDK records are retained.
  • Truncated responses and exhausted turn budgets report incomplete execution.
    Summaries inherit the selected model and cancellation, credentials follow the
    documented precedence, and user prompts can be cancelled.
  • File mutations recheck permissions after approval; review restore respects
    file restrictions, and SDK rollback records point to the pre-edit snapshot.
    Hook processes and SDK resources are cleaned up when work stops. Cancellation
    during the final path check or file preparation no longer starts a later write.
    Additional writable directories work with the default sandbox mode; SDK
    session forks are rejected before copying incomplete history.
  • Real SDK executable tests run on Ubuntu and macOS against local fixtures;
    Linux bwrap/netns, desktop protocol journeys and release gates also pass.
    Real Kimi/GLM endpoints and long-task quality still need live acceptance.
  • The VSIX uses native by default and does not bundle the optional SDK
    executable. Signed macOS installers and npm publication require the release
    credentials described in Releasing DeepCode.

The following changes accumulated on main since v0.3.0 are also included.

⚠️ Breaking

  • deepcode mcp serve now applies your permission settings. It executed
    Read/Write/Edit/Bash for any connected MCP peer with no mode, no permission
    rules, no file contract and no PreToolUse hooks — the same shape as the
    runAgent bypass fixed in #181, in a different entry point. Every call now
    goes through the central gate, a call that would need approval is refused
    (nobody is attached to that pipe to approve it), and a permissive
    permissions.defaultMode is clamped to default exactly as a scheduled job's
    is. A peer can now do what permissions.allow says it can and nothing else,
    so anyone relying on the old behaviour must add rules — or start the server
    with an explicit --mode. --sandbox also applies now; it did not before.

✨ Added

  • Grep and Glob results in the desktop are now clickable locations. Both
    tools attach the places they found as structured data — resolved from their
    own parsed rows, where a path containing : is still unambiguous — and the
    desktop renders a search's card as a list of openable paths (with line and
    matched text in content mode) instead of a grey text blob. Clicking one opens
    it in the file panel. This is the locations render intent the DSH round
    specified and deferred: re-deriving entries by parsing the formatted result
    text was the rejected design, and attaching them at the source is what makes
    the entries exact. A session restored from its log has only the text the
    model saw, so replayed cards degrade to today's plain-text body.

  • /plan enters plan mode directly (/plan off leaves it) — the same
    switch /mode plan already threw, one word shorter and matching what Claude
    Code users type. A trailing prompt (/plan do X) is refused with a pointer
    rather than silently dropped, because half-obeying a command teaches the
    wrong lesson about what it did.

  • Persistent shells now last a whole CLI session, and /shells shows them.
    The registry landed in #273 owned by a single runAgent call, which meant a
    shell opened in one turn was gone by the next — a slower Bash with extra
    steps. The REPL now owns one registry for the session and threads it through
    every turn, so cd, export, and an activated virtualenv survive from one
    message to the next.

    /shells lists what is open and where each started; /shells close <id>
    closes one and whatever is still running in it. Worth having because the
    change is what makes these processes outlive a turn: without a view of them,
    the user has no way to see or stop something the agent left running.

    Everything closes when the session ends, including when it ends by throwing —
    these are real processes in their own process group, so they do not die with
    the CLI. Background tasks and sub-agents deliberately do not share the
    session's shells: two agents interleaving commands in one shell would each be
    wrong about its state.

  • A shell that survives between tool calls (#273) — ShellOpen / ShellRun /
    ShellClose / ShellList. Every Bash call is a fresh process, so cd,
    export, and source venv/bin/activate were forgotten the moment they
    returned; the workaround was re-pasting the whole prefix into every command,
    which still could not hold a running dev server.

    Not a PTY. That would mean node-pty, a native dependency needing a build for
    every platform the desktop ships to, bought for full-screen programs that are a
    small share of the value. This runs over pipes with a per-session random
    sentinel, and says plainly in its description that vim and top do not work.
    Commands run with stdin closed so cat cannot swallow the sentinel, and stderr
    is merged at the shell so the streams interleave in true order.

    Interrupting an overrunning command signals the shell's children, not its
    process group — signalling the group kills a non-interactive bash, which would
    lose the session every time. Lifetime is guaranteed rather than remembered: a
    run that opens its own registry closes every shell before returning, including
    when the loop throws. Idle shells close themselves and there is a cap on how
    many can be open.

  • The agent can search its own past sessions (#272) — SessionSearch finds
    text across previous sessions and SessionRead follows a hit into the
    surrounding conversation. Every session was already on disk as JSONL and
    nothing could read it back, so "how did we fix this last month" was
    unanswerable while the answer sat in a file the agent wrote.

    Scoped to the current workspace by default, matched on a resolved path boundary
    so /a/project cannot capture /a/project-two. Neither tool takes a scope
    argument
    : widening the search is a privacy decision, and a parameter would let
    the model consent to reading another project's history on the user's behalf.
    SessionRead enforces the same rule, so knowing an id is not authorisation. No
    index — a scan is fast at this volume, and an index is a second copy of the
    truth that can disagree with it.

  • Tools declare how they should be drawn (#271). Every tool call rendered as
    the same grey blob: an Edit showed its result sentence but never the change,
    a Bash showed output with no sign of which command produced it. A tool now
    declares a render intent beside its schema — Bash is terminal,
    Edit/Write/NotebookEdit are diff — and the desktop draws real coloured
    +/- lines and a shell transcript. The mapping lives in core so the CLI and
    the extension read one answer instead of each hardcoding tool names.

    Presentation is a pure function of the call's arguments, never the result or
    the filesystem, so a replayed session renders as it did live. That is why
    Write renders as wholly added: its arguments genuinely do not say what the
    file held before.

  • A backstop deadline on every tool call (#270). Only Bash bounded itself;
    a Grep against a stalled mount could hang the turn forever with nothing on
    screen but a blinking cursor. Deliberately generous (10 min default) so each
    tool's own limit fires first and produces the more specific error — this only
    covers the case where the inner limit never fires. A caller-requested timeout
    always wins when longer. On a side-effecting tool the message says the effect is
    unknown rather than implying nothing happened.

  • The loop notices when the model is repeating itself (#269). The most
    expensive agent failure is the loop that neither errors nor terminates: same
    tool, same arguments, same answer, quietly spending the budget. At 3, 5, and 8
    consecutive identical calls an escalating reminder is injected. It has no veto,
    which is what makes false positives affordable. Excluded tools are transparent
    to the chain rather than resets, so a bookkeeping call interleaved into a loop
    cannot launder it, and calls the gate refused still count.

  • thread/delete — the protocol could list, fork and archive threads but not
    delete one, so the desktop deleted session files through Tauri instead. The
    app-server is the single owner of thread storage; a client removing files
    behind it can pull the ground out from under an open writer. Served under the
    existing threadManagement capability, with the local writer kept as the
    fallback for a sidecar too old to know the method.

  • Change ledger records provenance. Each entry now carries derivedFrom —
    the files the turn read before making that change — answering the question
    after "what changed" and "how do I undo it": what was it derived from. That
    is what you ask when a generated file is wrong and you need to know which
    input to fix. Shown by deepcode ledger show. Built on the existing ledger
    rather than a second store.

    It is observed, not declared: only Read counts (Grep/Glob take a search
    root and return many paths — calling the root an input claims a derivation the
    turn did not make), a failed read is not an input, and the file being written
    is excluded so an Edit does not look self-derived. Absent rather tha...

Read more

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 08 Aug 14:17
5856ad9

[0.3.0] — 2026-08-08

A workspace-governance layer: what the agent may touch, what it changed, and how
to undo it. Derived from a first-hand study of Floatboat's open Selfware
protocol
— see docs/research/floatboat.md for
the research (with evidence grading) and
docs/FLOATBOAT_ADOPTION_PLAN.md for what was
adopted, what was rejected, and where the implementation diverged from the plan.

⚠️ Breaking

  • The CLI is published as @deepcode/cli, not deepcode-cli. Install with
    npm i -g @deepcode/cli. The unscoped name on npm belongs to an unrelated
    project, so it was never ours to publish to. The binary is still deepcode
    and nothing about the tool's behaviour changes. (#249)
  • Unattended runs no longer inherit a permissive permission mode. A
    permissions.defaultMode of bypassPermissions or acceptEdits — chosen for
    interactive convenience — is clamped to default for scheduled jobs, which
    run with nobody present to approve anything. Set a job's profile.mode
    explicitly to opt back in. The clamp names itself and the fix in the job log
    on the first run after upgrading. (#244)

🔒 Security

  • .env could be read, and there was no way to say otherwise. Permission
    rules match on the tool; their only path-aware match is a prefix compare
    against an argument that is usually an absolute path, so Read(.env*) matched
    nothing. The new file contract adds the missing axis —
    glob × read/write/execute × allow/ask/deny — composed with the existing rules
    by most-restrictive-wins. It can only tighten. (#238, #239)
  • A contract deny cannot be waived by bypassPermissions. It states
    something standing about a path rather than prompting about one call, so the
    mode that exists to skip prompts has no business clearing it. (#239)
  • Plugin subprocesses are gated by the same path rules; the capability bridge
    previously called the dispatcher without a contract. (#239)
  • /combo drafts exclude paths the contract denies reading and redact
    credential-shaped values. A rule that stops at the tool call but not at the
    export is not much of a rule. (#243)

✨ Added

  • File contract — deepcode contract <show|init|check>. Optional; with no
    contract file, behaviour is unchanged. (#238, #239)
  • Change ledger — deepcode ledger <list|show|export|rollback>. An
    append-only record pairing each mutation with the request that motivated it
    and the checkpoint that reverses it, on two timelines (changes,
    governance). Stored outside the repository so git status stays clean.
    (#240, #241)
  • No Silent Apply — explain, preview, accept/reject/defer, rollback point
    first. confirm is a required argument, so a caller that cannot ask a human
    cannot apply. (#241)
  • runtime/capabilities — a protocol method answering what the runtime may
    write and which actions always stop for a human, distinct from initialize's
    protocol-feature flags. The CLI and app-server build it through one function,
    with a test asserting they agree field-for-field. (#242)
  • /combo — distil a finished thread into a SKILL.md draft, with
    allowed-tools derived from the tools actually called. (#243)
  • Trigger profiles — per-job mode, permissions, and sandbox for
    scheduled work. Permissions and sandbox can only tighten. (#244)
  • onApprovalRequired: 'abort' for scheduled jobs, plus exit code 6. A job
    whose first write is refused otherwise grinds on and reports a confidently
    wrong result. (#237)
  • deepcode doctor prints the runtime capability declaration and the
    file-contract warnings. (#242)

🐛 Fixed

  • Aborting mid-batch left tool_use blocks unanswered, which a provider rejects
    on resume. Remaining calls now get an explicit "never ran" result. (#237)
  • docs/cli-flags.md's exit-code table contradicted the implementation (it
    listed 3 as "tool denied" and 5 as "API key invalid"). Corrected against
    apps/cli/src/headless.ts, which owns the contract. (#237)

📄 Documentation

🚫 Deliberately not adopted

.self self-executing distribution (a supply-chain surface for a coding agent),
Floatboat's passive habit observation across files and browser tabs (a privacy
line, and unnecessary — /combo gets the value from an explicit invocation),
cross-organisation agent networks, and a second loopback HTTP runtime alongside
the app-server. Reasoning in the adoption plan §3.


No macOS build in this release. Apple signing credentials were not configured when it was cut; see docs/RELEASING.md.

Not published to npm. NPM_TOKEN was not configured when this release was cut; install the VSIX below or build from source.

Full commit list: v0.3.0 compare view