README
Type
External
Status
Published
Created
Aug 3, 2026
Updated
Aug 4, 2026
Updated by
Dosu Bot
Source

Decant#

CI
OpenSSF Scorecard
License: Apache 2.0

Your coding agent sessions contain a lot of useful information. What tokens got
spent on, how full the context window got, which files an agent worked with, and
what a run cost. Decant gives you insight into what's on disk, right now.

Built by Dosu for developers who want their agents to learn
from real work.

It reads the JSONL logs Claude Code and Codex already write
(~/.claude/projects/*.jsonl, ~/.codex/sessions/rollout-*.jsonl), normalizes
both formats into one WAL + FTS5 SQLite archive, and gives you full-text search,
token economics, context-window occupancy, and phase breakdowns from a CLI or a
local web UI. Your transcripts never leave your machine.

The current Decant Analytics UI showing the command palette, report and share
controls, session and token totals, activity economics, and daily charts.
Rendered from the repository's synthetic fixtures.

Features#

  • One archive for Claude Code and Codex sessions.
  • Full-text search across messages and tool calls.
  • Usage, estimated cost, tool, MCP, file-hotspot, and
    activity analytics.
  • Deterministic distill artifacts from real command history: scripts, replays,
    and skill/AGENTS snippets.
  • Persisted recommendations with implemented-state tracking.
  • Local React UI served by the same Bun process: decant serve.
  • Watch mode with native filesystem events plus a periodic sweep.
  • Scriptable JSON output, shell completions, and stable exit codes.

Quick Start#

Run Decant with npx—no Bun install or global package required:

npx @dosu/decant@latest

That starts the local web UI at http://127.0.0.1:3000, prints the link, and
opens your browser (skipped when it can't — the printed link always works). The
first run syncs the Claude Code and Codex logs already on your machine, then
keeps watching them for changes. decant serve is the same thing with flags:
--port, --host, --no-open, and friends. npx downloads the launcher and
matching native binary for this run without installing a persistent decant
command.

Use the same package for one-off CLI commands:

npx @dosu/decant@latest sync
npx @dosu/decant@latest ls
npx @dosu/decant@latest search "auth bug"

For a persistent installation:

npm install --global @dosu/decant@latest
decant

Install it with Homebrew:

brew install dosu-ai/dosu/decant
decant

Install it without Node, straight from the release assets:

curl -fsSL https://raw.githubusercontent.com/dosu-ai/decant/main/install.sh | sh
decant

Run the GHCR image:

docker run --rm \
  -p 127.0.0.1:3000:3000 \
  -v decant-data:/var/lib/decant \
  -v "$HOME/.claude/projects:/sources/claude:ro" \
  -v "$HOME/.codex:/sources/codex:ro" \
  ghcr.io/dosu-ai/decant:latest

To run from source instead, install Bun 1.3+ and use bun run dev. It performs
a frozen dependency install, starts decant serve, runs the startup sync, and
keeps watching your source logs. See Install Matrix for the
full set of options.

Keep the 127.0.0.1: host prefix on the Docker port publish. Publishing as
-p 3000:3000 exposes the archive port on every host interface. The container
binds 0.0.0.0 only inside its own network namespace so Docker's host loopback
publish can reach it.

The API is unauthenticated, so the peer's source address is the boundary. The
image ships no peer allowlist. It sets DECANT_TRUST_DEFAULT_GATEWAY=1, which
trusts exactly one address: the container's own bridge gateway, which is where
Docker's port publisher forwards -p traffic from. It does that only when
Decant can prove the default route is a container veth to an on-link gateway
inside 172.16.0.0/12. A sibling container on the same bridge keeps its own
source address and gets 403 forbidden remote.

Shapes that cannot be proven trust nobody beyond loopback and need one env var:
--network host, macvlan/ipvlan, multi-homed hosts, and bridges outside
172.16.0.0/12 (Podman's 10.88.0.0/16, a custom --subnet, Kubernetes). If
the UI answers 403 forbidden remote, set DECANT_TRUSTED_PEERS to the exact
address requests arrive from, for example
-e DECANT_TRUSTED_PEERS=192.168.65.1. That replaces the gateway default
entirely; DECANT_TRUST_DEFAULT_GATEWAY=0 turns it off without naming a peer.

CLI#

decant sync
decant ls
decant show 1
decant search "auth bug"
decant stats --by model
decant files --group ext
decant tool stats
decant mcp stats
decant distill script
decant distill replay 1
decant distill skill --kind agents
decant recommendations ls
decant export 1 > session.md
decant export 1 --as trajectory > session.trajectory.json
decant completion zsh

All read commands support --json. Use --db /path/to/decant.db or
DECANT_DB for an alternate archive. Use decant sync --path /path/to/log-or-dir
to ingest only specific source files or a temporary source tree, including raw
Claude stream-json logs; pass --path more than once to ingest multiple paths.

Configuration#

  • DECANT_DB: archive path, default ~/.decant/decant.db.
  • DECANT_CLAUDE_DIR: Claude projects directory, default
    ~/.claude/projects.
  • DECANT_CODEX_DIR: Codex home directory, default ~/.codex.
  • DECANT_CONFIG_DIR: settings directory, default ~/.config/decant.
  • DECANT_LOG_LEVEL: minimum structured operational log level written as JSON
    Lines to stderr. Defaults to info; accepts trace, debug, info, warn
    (or warning), error, fatal, and off (or silent).
  • DECANT_NO_SYNC: set to any value to skip the sync-on-read that read commands
    perform, and to run decant serve without its source watcher so it serves the
    archive as-is and ingests nothing. The --no-sync flag does the same. The
    "Sync now" button and POST /api/sync still work; this only suppresses the
    syncing Decant starts on its own.
  • DECANT_NO_OPEN: set to any value to never auto-open a browser from
    decant serve; the --no-open flag does the same per run.
  • BROWSER: opener command used instead of the platform default (open on
    macOS, xdg-open on Linux). A bare command name or path, no arguments;
    BROWSER=none disables opening. The URL is always printed either way, and
    auto-open is skipped in CI or when stdout is not a terminal.
  • DECANT_TRUSTED_PEERS: comma-separated peer IPs or IPv4 CIDRs allowed through
    the local API guard when serve is bound to a non-loopback host. Unset by
    default. Keep it as narrow as the deployment allows: every listed address, and
    every address inside a listed CIDR, reads and writes the whole archive without
    a credential.
  • DECANT_TRUST_DEFAULT_GATEWAY: set to 1 to trust this container's own
    bridge gateway, resolved once at startup from /proc/net/route and
    /sys/class/net. Off by default and off for any other value, including 0.
    The derived peer is a single address, and only when the default route is a
    container veth pointing at an on-link gateway inside 172.16.0.0/12; every
    other shape resolves to no peers. The container image turns this on so the
    documented docker run recipe works without a peer CIDR.

Precedence is replace, not merge: --trusted-peer wins over
DECANT_TRUSTED_PEERS, which wins over DECANT_TRUST_DEFAULT_GATEWAY. Setting
either peer source, including DECANT_TRUSTED_PEERS= with an empty value,
means no gateway is derived.

decant serve binds 127.0.0.1:3000 by default. Override with
--host/--port. There is no authentication, so bind loopback unless you
deliberately want other hosts in: the Host header check is not an access
control for non-browser clients, which can send Host: localhost freely.

Archives older than schema v8 are rebuild-only. v8 through v21 archives migrate
forward to v22 on open. Schema v22 tracks the ingest-pipeline revision for every
source: when parser or enrichment behavior advances, the next decant sync
transactionally re-ingests each unchanged stale source once, and later syncs
skip it again. Existing archives therefore backfill new derived data without a
manual rebuild. Older archives should be deleted and rebuilt with decant sync.
Source logs remain the source of truth, so nothing is lost by rebuilding.

Integrating with Decant#

decant serve exposes a documented local API at
http://127.0.0.1:3000/api. It has no authentication on the default loopback
listener, so any local process can read or mutate the archive. Keep the listener
on loopback unless you have deliberately configured the trusted-peer boundary
described under Configuration.

The source OpenAPI 3.1 contract is
docs/api/openapi.yaml. A running server exposes the
same contract as JSON at http://127.0.0.1:3000/api/openapi.json.

For example, read the archive summary:

curl --fail --silent --show-error \
  http://127.0.0.1:3000/api/stats/summary

See docs/api/routes.md for local access-control semantics,
write-request requirements, and Server-Sent Event names.

How It Works#

~/.claude + ~/.codex
        |
        v
 Bun + TypeScript Decant process
 parse -> enrich -> ingest + economics vectors -> SQLite WAL + FTS5
        |
        +--> CLI reads / JSON
        +--> local React UI + JSON routes + SSE

There is no background daemon or separate service process. The old
Rust/Phoenix/Swift implementation is preserved in the signed pre-typescript
tag.

The local API contract lives in
docs/api/openapi.yaml, with operational semantics in
docs/api/routes.md.
The architecture guide maps the modules and data flow;
analytics methodology defines the reported
units; API recipes show reproducible local queries; and
archive lifecycle explains sync, visibility, deletion,
and rebuild behavior.
Operational log fields and privacy rules live in docs/logging.md.
Distribution notes live in docs/distribution.md, and the
tag-driven release pipeline is documented in
docs/releasing.md.

Install Matrix#

Ordered from the most streamlined to the most manual. Everything except "build
from source" is available from v0.1.0, once the Release workflow has
published a version. See docs/distribution.md for build
details and per-artifact verification.

  1. npx / npm — zero persistent install, or a global one:

    npx @dosu/decant@latest
    npm install --global @dosu/decant@latest # persistent, then use `decant`
    
  2. Homebrew — via the dosu-ai/dosu tap:

    brew install dosu-ai/dosu/decant
    

    Or with the tap and short names:

    brew tap dosu-ai/dosu
    brew trust dosu-ai/dosu # Homebrew 6.0+ only — skip on older versions
    brew install decant
    
  3. Install script — for machines without Node:

    curl -fsSL https://raw.githubusercontent.com/dosu-ai/decant/main/install.sh | sh
    

    Detects your platform, downloads the matching release tarball, verifies it
    against SHA256SUMS, and installs to ${DECANT_INSTALL_DIR:-~/.local/bin}.
    Pin a version with DECANT_VERSION, skip the PATH edit with
    DECANT_NO_MODIFY_PATH=1, or point DECANT_BASE_URL at a mirror — see
    docs/distribution.md for the full knob list.

  4. Docker — the ghcr.io/dosu-ai/decant image, per the docker run recipe
    in Quick Start. Keep the 127.0.0.1: host prefix on the port
    publish.

  5. Build from source — the contributor path, and the only one that works
    before v0.1.0:

    bun run dev
    

macOS, tarball downloads only. v0.1.0 binaries are ad-hoc signed but not
notarized, so a tarball downloaded through a browser carries
com.apple.quarantine and Gatekeeper blocks the first run. Clear it with
xattr -d com.apple.quarantine ./decant. brew install, npx @dosu/decant, and the
install script are unaffected, because none of them set the quarantine
attribute. Integrity comes from SLSA build provenance (published with each
release as an offline-verifiable decant-<version>.sigstore.json bundle),
SHA256SUMS, and the gh attestation verify check install.sh runs.

Upgrading. npx @dosu/decant@latest always resolves the newest published
version. For a persistent install, run npm i -g @dosu/decant@latest,
brew upgrade decant, re-run the install script, or
docker pull ghcr.io/dosu-ai/decant:latest. A source checkout reports
git describe --tags --always --dirty from decant --version (for example,
v0.1.0-8-ge9a0c00-dirty); a non-Git unstamped build falls back to dev.
Released artifacts carry their injected release version.

Development#

Run the local UI and watcher:

bun run dev

Run quality gates:

bun test
bunx tsc --noEmit
bunx biome check .
just check

Build distribution artifacts:

bun run scripts/build-binaries.ts --target native
bun run scripts/build-npm.ts --target native --no-build
docker build --platform linux/amd64 -t decant:local .

See AGENTS.md for the full command list, conventions, and project
invariants.

Security and Privacy#

Decant is local-first and offline at runtime. It reads files already on disk and
makes no outbound runtime network calls. Do not commit real session data,
personal archives, tokens, keys, or .env files. To report a vulnerability, see
SECURITY.md.

About Dosu#

Decant is built and maintained by Dosu, Knowledge
Infrastructure for Agents. Dosu makes agents faster, cheaper, and more effective
across every run.

Decant is the measurement end of that. It shows you what your agents actually
spent, read, and touched, from logs already on your disk. It is Apache 2.0 and
runs entirely on your own machine. See
Security and Privacy.

License#

Licensed under the Apache License 2.0.