sumofbytes/dex 发布 Rust 终端编码智能体,采用客户端与守护进程分离架构
sumofbytes/dex
sumofbytes/dex 是一个用 Rust 编写的终端编码智能体,通过 read、bash、write、edit、grep、find、ls 等工具以及 MCP 服务器操作本地文件,支持 OpenAI 兼容、Anthropic 和 Codex 三类提供方,并把每次会话保存为可恢复的 JSONL 记录。
A terminal coding agent written in Rust. It calls tools (read, bash,
write, edit, grep, find, ls, plus MCP servers) to work on your local
files, talks to OpenAI-compatible, Anthropic, and Codex providers, and saves
every conversation as a resumable JSONL session.
The TUI is a pure HTTP client — a daemon does the LLM calls, tools, and
sessions over HTTP+SSE — and that engine is a workspace of reusable crates
(dex-ai, dex-agent-core, dex-session, …), so the harness pieces can be
reused to build your own agent.
Features
- Multi-provider backends — OpenAI-compatible Chat Completions/Responses endpoints, Anthropic's Messages API, and ChatGPT-backed Codex OAuth, with streaming, retries, and automatic protocol fallback. See Configuration.
- Agentic tool use — the model reads, runs, writes, edits, and searches
your files. Bring your own tools via MCP servers (stdio or HTTP/SSE, with
OAuth);
DEX_TOOL_CACHE=1opts into result caching. - Client–daemon architecture — the TUI is a pure HTTP client; the daemon does the LLM calls, tools, and sessions. Attach from anywhere, reconnect with journal replay, and approve tool calls remotely.
- Interactive TUI — a
ratatuiREPL with a streaming markdown transcript, multi-line input, autoscroll, a status bar, and a follow-up queue while the agent works.!runs shell commands without the agent. - Session persistence — each conversation is a crash-safe JSONL journal.
Use
--sessionto continue one, or--reattach <id>to reattach to a daemon session (quitting the TUI prints the exact resume command). - Skills — teach the agent something by dropping a directory with a
SKILL.mdfrontmatter; inject into the system prompt or load on demand via/skill:<name>. See Sessions and skills. - History compaction — when the context window fills, older turns are
summarized deterministically (no LLM call).
DEX_COMPACTION=llmor=jevswitch strategies — see Environment variables. - Modular by design — providers, the agent engine, sessions, protocol, and server live in separate crates; see Architecture and Runtime composability.
- Project instructions — a repo-level
AGENTS.md/CLAUDE.mdis appended to the system prompt automatically. - Runtime logging —
DEX_LOG=off|error|warn|info|debug|tracewith a TUI-safe sink (stderr outside the TUI,dex.loginside). - Herdr-aware — running inside a Herdr pane
(
HERDR_ENV=1), dex reportsworking/blocked/idleto the Herdr sidebar; no-op everywhere else. - No telemetry — dex makes network calls only to the LLM providers you
configure (plus
models.devfor the model catalog). Nothing else.
Documentation
| Document | Contents |
|---|---|
| docs/getting-started.md | Install → configure → verify → first run, everyday usage, troubleshooting |
| docs/configuration.md | Config file, precedence, model: knob, provider examples, legacy keys, system prompt |
| docs/tui.md | Slash commands, ! shell escape, agent modes, keyboard controls, steering queue |
| docs/tools.md | Built-in tools, then_run, sub-agents (delegate), MCP servers |
| docs/sessions-and-skills.md | JSONL session storage, skill discovery and SKILL.md format |
| docs/extensions.md | Lua extensions: tools, hooks, harness slots, agent_loop |
| docs/environment.md | Every DEX_* and provider environment variable |
| docs/architecture.md | Workspace crates, project structure, how a turn works |
| docs/releasing.md | Release/tag process and CI |
| docs/runtime.md | Runtime composability: slots, profiles, replaceable agent loop |
Install
Every v* tag builds binaries for x86_64/aarch64 Linux (static musl — runs
on any distro, no libssl or glibc constraints), x86_64/aarch64 macOS, and
x86_64 Windows, and attaches them to the GitHub release.
curl -fsSL https://raw.githubusercontent.com/sumofbytes/dex/HEAD/scripts/install.sh | sh- Pin a version:
curl -fsSL .../install.sh | sh -s -- 0.2.0 - Custom directory:
DEX_INSTALL_DIR=/usr/local/bin curl -fsSL .../install.sh | sh - Windows: grab
dex-v*-*-x86_64-pc-windows-msvc.zipfrom the releases page.
First run needs one thing: a model — the
Getting started guide walks through it. Copy a
sample from examples/config.yaml, set model: <provider>/<model> in the
config (see Configuration), and run dex doctor to
verify (exit 1 means setup is still incomplete). The daemon fetches the
models.dev catalog in the background on first start (dex update --models for
a manual refresh).
Building
Requires a Rust toolchain (edition 2021):
cargo build --release
# binary: target/release/dexReleases are tagged with scripts/release.sh — see
docs/releasing.md.
Usage
Run dex with no arguments to launch the interactive TUI:
dex
Ask it to do something:
> read src/main.rs and summarize what it does
Doctor
dex doctor shows the fully resolved configuration — provider, endpoint, model,
wire protocol, key source, thinking effort, catalog state — each with the origin
(flag > env > file > default). It never touches the network and is the first
thing to run when setup misbehaves. Exit 0 means the config builds cleanly,
exit 1 means resolve ERROR (script-checkable).
dex doctor
One-shot mode
Pass a prompt as arguments to get a single answer (no TUI):
dex "explain the Cargo.toml dependencies"Raw tool mode
dex --tool reads JSON tool-invocation lines from stdin and prints JSON
results. Useful for piping tool calls from another process:
echo '{"name":"read","args":{"path":"Cargo.toml"}}' | dex --tool # => {"ok":"[package]\nname = \"dex\"\n..."}
An empty line quits raw tool mode.
One-shot tool mode
dex run <tool> <key>=<value>... executes a single tool and prints the raw
result (errors go to stderr with exit code 1). Values that look like JSON
numbers/booleans are coerced (limit=5, replaceAll=true); a single JSON
object string is also accepted. Inside agent shell commands the binary is
available as $DEX_BIN, so ONE bash call can stitch a whole read-only pipeline
— search locally, read excerpts, print only the distilled result — while
intermediate output never enters the conversation:
"$DEX_BIN" run grep pattern=TODO output_mode=files | while IFS= read -r f; do "$DEX_BIN" run read "path=$f" limit=3 done
Model catalog
dex update --models refreshes the cached model catalog (context windows and
/model autocomplete). A fresh daemon bootstraps it in the background, so this
is a manual refresh, not a required step.
dex update --models
Self-update
Bare dex update replaces the running binary with the latest release (--all
also refreshes the model catalog). It resolves the latest version via the
/releases/latest redirect, verifies the download against the release's
SHA256SUMS, and atomically renames the new binary over the running one, so a
crash mid-update can never leave a torn install. It refuses (with a pointer at
the right command) when the binary was built from source, installed via
cargo install, or is a Windows build. It honors the same DEX_REPO and
DEX_VERSION envs as scripts/install.sh:
dex update # latest release DEX_VERSION=v0.4.0 dex update # pin (or downgrade to) a release dex update --all # self-update + refresh the model catalog
Client–server mode
The TUI is a pure HTTP client; all agent work (LLM calls, tools, sessions)
happens in a daemon. dex with no arguments starts a daemon in the background
and attaches the TUI to it:
dex # daemon on a random localhost port + TUIRun the daemon headless (e.g. on a remote machine, in the directory you want as the agent workspace) and connect the TUI from anywhere:
dex serve # daemon on 127.0.0.1:8420 dex serve 0.0.0.0:8420 # reachable from other machines dex connect http://127.0.0.1:8420 dex connect http://10.0.0.5:8420 "explain the Cargo.toml dependencies" # one-shot
A non-loopback bind always requires a bearer token: the daemon generates one and
prints it, clients present DEX_DAEMON_TOKEN=<token> (or the token file at
$XDG_DATA_HOME/dex/daemon.token). Loopback-only daemons need no token unless
DEX_DAEMON_TOKEN is set (explicit env wins everywhere). One machine, one token
file: two daemons share it (second overwrites), so multi-daemon clients must
pass per-host DEX_DAEMON_TOKEN explicitly.
If the connection drops, the TUI replays the session journal and re-POSTs with
the same idempotency key: finished turns replay their result, still-running
turns answer 409 — use --reattach <id> to take over — and turns that died
with the daemon re-execute from their last journal event. Everything looks
local: text streams live, tool calls and results appear as they happen, tool
approvals take the composer's place (the daemon parks the turn until you decide),
and Ctrl+C cancels the in-flight turn. API keys and permissions resolve in the
daemon's environment; client flags like --model are forwarded as
per-request overrides. Tools execute on the daemon's machine, relative to its
working directory.
Command-line flags
| Flag | Description |
|---|---|
--base-url <url> |
Override the API base URL for this run (pins the endpoint; routing prefixes become naming only). |
-H, --header <"Name: Value"> |
Extra provider header (repeatable; Name=Value or JSON object also accepted). |
--model <name> |
Override the model for this run: <provider>/<model> (a bare provider name has no model and is rejected). |
--system-prompt <text> |
Replace the built-in base system prompt for this run (project/extensions/skills still append). |
--system-prompt-file <path> |
Read the replacement base system prompt from a file (client-side, so remote daemons work). |
-s, --session <path> |
Open/continue a specific session file. |
--no-session |
Disable session persistence for this run. |
-n, --new |
Start a new session (the default). |
--permission <mode> |
Tool permission ceiling: read-only, ask, or trusted (default trusted). |
--mode <plan|manual|auto> |
Agent mode for this run (plan = read-only + planning directive); clamped to the permission ceiling. |
--name <name> |
Name the session (default <workspace>-<7 chars>, e.g. dex-k3m9x2q). |
--reattach <id> |
Attach to an existing daemon session and replay its event journal (bare dex or dex connect <url>, no prompt). |
--skill <dir> |
Add an extra skill directory to discover skills from. |
--tool |
Run raw JSON tool mode (read JSON lines from stdin). |
Defaults, all overridable via DEX_* env vars — see
Environment variables:
- Permission ceiling:
trusted(no approvals); setDEX_PERMISSION=askor--permissionto approve writes and shell commands. A client can only go stricter than the daemon's ceiling; the ceiling seeds the TUI's agent mode (Agent modes). - Shell commands: 120 s timeout, 1 MiB per output stream (
DEX_TOOL_*). - HTTP: 10 s to connect, 300 s overall (
DEX_HTTP_*). - Sessions: journals live in
$XDG_DATA_HOME/dex/sessions/*.jsonl,fsyncon turn/effect events only (DEX_DURABLE=1for every line). - Audit: off;
DEX_AUDIT=1writesaudit.jsonlper tool call. - Paths: tools are not confined — relative paths resolve against the
workspace, but
read/write/edit/bashreach anything your user can. To restrict dex, run it in a sandbox or container.
In the interactive TUI, actions requiring approval replace the composer with an inline panel (the
transcript stays visible). Use the arrow keys and Enter to choose Allow once, Allow for this session, or
Deny; y, s, and n are direct shortcuts, and Esc denies.
Any other arguments are treated as a one-shot prompt. Subcommands (serve,
connect, run, usage, update, mcp, doctor) are covered under
Usage above and MCP servers;
--help/-h and --version/-V print help and version without
touching config or network.
Acknowledgments
dex interoperates with conventions from across the terminal-agent ecosystem:
CLAUDE.md project instructions and ANTHROPIC_CUSTOM_HEADERS (Claude Code),
response-first wire negotiation on OpenAI-compatible gateways, OAuth via codex --login (Codex), token-based compaction settings
(pi-mono), and fff-search file search (fff.nvim). Model metadata comes
from the models.dev catalog.
Support
- Bugs: open an
issue with
dex --version, redacted config, and steps to reproduce. - Ideas: open a feature request.
- Security: do not open a public issue — see SECURITY.md.
- There is no chat or discussion forum; GitHub issues are the contact channel.
Contributing
Contributions are welcome. There is no formal roadmap — open or pick up an issue
labeled
good first issue or help wanted.
Please read CONTRIBUTING.md first and follow the
Code of Conduct. By contributing you agree your work is
dual-licensed MIT/Apache-2.0 like the rest of the project. New to dex? The
Getting started guide is the fastest way to see it
work.
Status: pre-1.0 (0.x) — usable daily but expect breaking changes until a
1.0 release.
Note: the name dex collides with an unrelated dex crate on crates.io, so
dex is distributed via
GitHub releases and
scripts/install.sh, not cargo install.
License
dex is dual-licensed under the MIT and Apache-2.0
licenses, at your option (SPDX: MIT OR Apache-2.0). See
CONTRIBUTING.md and SECURITY.md for how to
contribute and report security issues.
来源:GitHub · github.com