Prompts, policy, providers, state, and the TUI live in this repository.
Dext — Technical Documentation
Dext is a single-binary Rust coding agent that runs from your terminal. It keeps project-scoped session state and gives the model a curated set of native tools for filesystem operations, search, shell execution, data processing, HTTP requests, Git operations, and task tracking.
Dext is source-first: prompts, runtime state, tool policies, provider wiring, and the TUI all live in the repository with no external service required beyond your chosen model provider.
docs/ after each reviewed change to main. Focused Markdown guides remain supplemental. Open non-documentation risks are tracked in the risk register.cargo fmt --all -- --check, Clippy with warnings denied, cargo audit --deny warnings, cargo deny check licenses, the vendored ratatui-core tests, release build/tests, and the PTY smoke suite. Reinstall with cargo install --path . --force --locked so the binary on PATH matches the source. Renderer-specific requirements are documented in docs/TUI.md.workspace-write sandbox intentionally denies shared /tmp, arbitrary pseudo-terminals, and Cargo install metadata such as ~/.cargo/.crates.toml. Running Dext's own full suite through a confined Dext shell can therefore cause cascading temp-directory failures, deny all TUI smoke tests, and block installation. Run the gate directly in a trusted terminal or CI. If Dext must orchestrate it, start a separate controlled process with dext --sandbox-profile danger-full-access --approval always; setting an environment variable inside an already-confined shell cannot relax the parent kernel sandbox. Do not weaken the default sandbox for test convenience.Architecturally, Dext uses Agent in main.rs as a facade around focused modules: provider request shaping and auth (provider.rs), bounded stream assembly (streaming.rs), tool-round execution and side-effect fencing (tool_round.rs, tool_journal.rs), tool schemas and policy (tools.rs, tool_policy.rs), project/session state (session.rs), interactive rendering (tui.rs), safety/recovery primitives (git_checkpoints.rs, mutation_preview.rs, sandbox.rs), and extension metadata/runtime (packs.rs, shelves.rs, orchestrator.rs).
Quick Start
Install
git clone https://github.com/SiliconState/Dext.git
cd Dext
cargo install --path . --force --locked
Authenticate
dext auth providers # list available providers
dext auth login chatgpt # ChatGPT/Codex OAuth
dext auth login glm <key> # ZAI GLM API key
dext auth login openai <key> # OpenAI Platform key
dext auth login kimi <key> # Kimi Code plan key
Run
dext # interactive session
dext "summarize this repo" # one-shot
dext --frugal --effort off # low-token mode
Project Layout
| File | Purpose |
|---|---|
src/main.rs | Agent loop, provider HTTP, permissions, slash commands, CLI entry, eval |
src/main_tests.rs | Unit and integration tests for main.rs |
src/tui.rs | Ratatui inline TUI, permission prompts, transcript rendering |
src/provider.rs | Provider catalog, auth, request shaping, model normalization |
src/sse.rs | Input-buffer-bounded SSE frame decoder shared by runtime and benchmarks |
src/streaming.rs | Provider event validation and stream/tool-call assembly |
src/tool_round.rs | Tool planning, approval, checkpoint/journal boundaries, dispatch, result normalization |
src/tool_journal.rs | Owner-private side-effect start/terminal records and resume reconciliation |
src/session.rs | Session/log persistence, project state locks, atomic I/O |
src/sandbox.rs | OS confinement, profile write roots, private scratch, offline diagnostics isolation |
src/tools.rs | Tool definitions, permission metadata, parallel-safe classification |
src/orchestrator.rs | Work phases, similarity guards, objective tracking, adaptive caps |
src/git_checkpoints.rs | Git-native recovery refs, /undo, sidecar files, pruning |
src/mutation_preview.rs | In-memory line-level previews before applying file mutations |
src/packs.rs | Pack discovery, invocation, conversational pack inference |
src/shelves.rs | Typed shelf registry with ability metadata, signals, and effects |
src/tool_policy.rs | Command risk classification, input validation, bash guardrails |
deny.toml | Dependency-license allowlist enforced by security and release workflows |
benches/dext_bench.rs | Criterion performance harness |
tests/tui_smoke.rs | PTY-backed launch, multiline input, streaming, and resize regression tests |
vendor/ratatui-core/ | Exact upstream source plus Dext's narrow inline-terminal compatibility patch |
Architecture
Dext follows a single-binary architecture with no runtime plugin service. The Agent facade composes prompts and state while focused modules assemble provider streams, execute tool rounds, enforce policy, render the terminal, and persist recovery metadata.
High-Level Data Flow
User Input → Agent Loop → Provider HTTP (streaming SSE)
↓
Response Blocks (text/thinking/tool_use)
↓
Tool Dispatch → Execute → Result
↓
Append to History → Next Turn
↓
Compaction (if context pressure)
System Diagrams
This section documents executable runtime behavior with HTML-native SVG diagrams. The shapes map to Rust modules and runtime checkpoints instead of being merely illustrative.
Turn Loop Sequence — user input to next turn
Tool Execution Sequence — validation, policy, checkpoint, result
read_file, rg, git_diff, etc.) parallelize.Checkpoint Lifecycle — Git recovery before mutation
Turn Loop Flowchart — branch points
Checkpoint Restore Flow — preview vs apply
Key Enums and Structs
| Type | Defined In | Purpose |
|---|---|---|
ThinkingEffort | main.rs | Reasoning depth: Off, Low, Medium, High, XHigh, Max |
OutputMode | main.rs | Text, Json, StreamJson — output format for non-interactive mode |
ApprovalProfile | main.rs | Ask, AutoRead, AutoWrite, Never, Always — permission gating |
SandboxProfile | main.rs | ReadOnly, WorkspaceWrite, DangerFullAccess |
ContextMode | main.rs | Standard, Frugal, Tiny — context window management |
MutationPreviewMode | main.rs | Off, Simple, Git — diff preview before mutations |
Usage | main.rs | Token tracking: input, output, cache_create, cache_read |
BudgetCap | main.rs | Session budget limits in USD or tokens |
WorkLedger | main.rs | Objective, phase, decisions, pending/done/blocked items |
SessionHeader | main.rs | Persisted session metadata with full provenance |
Message / Block | main.rs | Conversation history: Text, Thinking, ToolUse, ToolResult |
AgentEvent | main.rs | Event stream: TurnStart, TextDelta, ToolCallResult, etc. |
Main.rs — Agent Core .rs
main.rs owns the Agent facade, CLI and slash-command dispatch, prompt/context assembly, compaction, built-in tool adapters, and eval harness. Provider stream parsing lives in streaming.rs; tool planning and dispatch live in tool_round.rs; durable side-effect records live in tool_journal.rs.
Agent Loop
The central Agent struct drives a turn-based loop:
- Prompt composition — Builds the system prompt from
DEXT.md, project context, tool catalog, session header, work ledger, shelf abilities, and recall cache. - History management — Maintains a
Vec<Message>with automatic compaction when context pressure exceeds configurable thresholds (default: 90% at end-turn, 80% after safe tool-result checkpoints). - Provider dispatch — Sends streaming requests to the active provider. Applies connect, first-byte, and between-chunk idle deadlines, then parses bounded SSE frames into
Blockvariants. - Tool execution — Dispatches
tool_useblocks to native Rust implementations. Supports parallel execution for read-only tools. - Permission gating — Routes tool calls through
EventSink::request_permission()based on the activeApprovalProfileand tool risk classification. - Steering — Active-turn user input is routed to a steering channel, injected at safe boundaries.
Stream Parsing
| Provider | API | Request Builder |
|---|---|---|
| Anthropic / GLM / Kimi Code | Messages API (/v1/messages) | Request struct with AnthropicThinking |
| OpenAI / DeepSeek / Local | Chat Completions (/v1/chat/completions) | OaiRequest with reasoning_effort |
| ChatGPT / Codex | Responses API (/codex/responses) | build_chatgpt_request() |
Transport Deadlines and Body Bounds
The shared provider client uses a 15-second connect timeout. Cloud requests allow 180 seconds to first response headers and 90 seconds between stream chunks; local llama.cpp requests default to 600 seconds and 300 seconds respectively. DEXT_PROVIDER_CONNECT_TIMEOUT_SECS, DEXT_PROVIDER_FIRST_BYTE_TIMEOUT_SECS, and DEXT_PROVIDER_STREAM_IDLE_TIMEOUT_SECS accept positive overrides. Initial requests and compaction retries use the same first-byte policy. Non-stream compaction responses use the stream-idle deadline while reading and reject JSON bodies above 4 MiB; provider error diagnostics stop at 4,000 bytes.
src/sse.rs limits its in-progress input buffer to one configured event plus at most four delimiter bytes before rejection. One large network read may still contain many valid small events; the decoder drains complete frames incrementally rather than rejecting by chunk size.
ChatGPT Responses terminal events with status=incomplete are recoverable rather than fatal protocol errors. Dext executes only function calls that reached a streamed completion event and discards truncated calls, ignoring complete-looking terminal snapshots for those unfinished calls. Discarded live text/thinking preview state is reset; interactive warnings identify the recovery. If no executable call remains, Dext issues a bounded continuation request with a concise runtime hint; provider-reported content filtering halts immediately instead of retrying. Recovery lowers ChatGPT reasoning effort for that request only (for example, xhigh to medium) without changing the user-selected effort or consuming the normal tool-iteration budget. After three unsuccessful continuation requests, Dext halts the turn with guidance while keeping the session usable.
Session Persistence
Sessions are stored as JSONL files under ~/.dext/projects/<project-key>/sessions/. The first line is a SessionHeader with full provenance (model/provider, tool policy surface, approval/sandbox profiles, context mode, usage ledger, work ledger, provider health, and runtime diagnostics). This header is the replay anchor for deterministic restore behavior.
Eval Harness
Outcome-oriented assertions on files and command output. The eval path validates objective completion semantically (not just command exit) and records verification artifacts for later audit. Run via dext --eval.
Crash Recovery
A panic hook writes an owner-private JSON snapshot under ~/.dext/crashes/ with a generated crash id, hashed source-location metadata, terminal dimensions, process id, current generated session id, recent event breadcrumbs, and whether backtraces were enabled. Free-form panic payloads, raw source paths, environment text, and backtrace content are omitted.
Session.rs — Session & State .rs
Manages all persistent state for Dext sessions, logs, and project-scoped data.
State Directories
~/.dext/ # DEXT_HOME (overridable)
├── providers.json # Provider catalog
├── auth.json # Stored credentials (0600 on Unix)
├── .env # Optional user-owned Dext dotenv settings
├── settings.json # user compaction threshold settings
├── crashes/ # owner-private crash snapshots
├── shelves/ # User-scoped shelves and packs
└── projects/
└── <project-key>/
└── sessions/
├── <name>.jsonl # Named session export
└── <session-id>/
├── _latest.jsonl
├── latest.log
├── session.lock.json
├── DEXT.todo.json
├── tool-journal.json
├── artifacts/
├── git-auth/
└── sudo/
Project Key
Each project gets a stable key derived from its canonical path: <slug>-<FNV-1a-hash>. This ensures isolated state per project even with identical directory names.
Atomic Writes
Sensitive state writes use a temp-file-and-replace helper. On Windows the replacement uses MoveFileExW; on Unix it uses fs::rename. Session logs normally use private append writes while they remain below the cap.
Session State Lock
Each active session directory has a session.lock.json record containing PID, token, project, sandbox, and session identity. Matching locks are released through a cleanup registry; a lock is removed as stale only when its recorded process is no longer running.
Log Rotation
Each session's latest.log is capped at 64,000 bytes. DEXT_LOG_ARCHIVES may retain up to 16 rotated archives; the default is zero.
Provider.rs — Provider Catalog .rs
Manages the catalog of model providers, authentication, request shaping, and model normalization.
ApiProvider Enum
Three wire-format families:
Anthropic— Anthropic Messages API (also used by GLM viaapi.z.ai/api/anthropic)OpenAi— OpenAI Chat Completions API (also used by DeepSeek, local llama.cpp)ChatGpt— ChatGPT Responses API (OAuth-backed)
Built-in Providers
| ID | Display | API | Default Model | Auth |
|---|---|---|---|---|
glm | ZAI GLM | Anthropic | glm-5.2[1m] | API Key (ZAI_API_KEY) |
chatgpt | ChatGPT | ChatGPT Responses | gpt-5.4 | OAuth (OpenAI auth) |
openai | OpenAI API | OpenAI | gpt-5 | API Key (OPENAI_API_KEY) |
anthropic | Anthropic | Anthropic | Provider catalog default | API Key (ANTHROPIC_API_KEY) |
kimi | Kimi Code | Anthropic | k3 | API Key (KIMI_API_KEY) |
deepseek | DeepSeek | OpenAI | deepseek-chat | API Key (DEEPSEEK_API_KEY) |
local | Local llama.cpp | OpenAI | qwen3.6-35b-a3b-mtp-ud-q5_k_m | None; accepts the server model alias, probes live context, and defaults to frugal context |
Provider Resolution Chain
DEXT_PROVIDERenv varDEXT_PROFILEenv varDEXT_API_PROVIDERenv varactive_providerfield inproviders.json- Default:
glm
Model Resolution Chain
DEXT_MODEL_{PROVIDER}(provider-specific)DEXT_MODEL(withDEXT_MODEL_FORCEoverride)- Profile's
default_model
ChatGPT Model Normalization
Compact aliases are canonicalized (for example gpt5codex → gpt-5-codex and ChatGPT gpt-5.6 → gpt-5.6-sol). GLM models get an automatic glm- prefix when omitted, and model-name context hints such as [1m] are honored.
Authentication
Credentials stored in ~/.dext/auth.json. Two types: ApiKey (plain key, supports env var refs and !command secret references) and OAuth (access token + refresh token + expiry, used by ChatGPT). Provider/profile resolution merges built-ins with user catalog overrides while pruning retired bundled providers.
Tools.rs — Tool Catalog .rs
Defines all provider-visible tools, their schemas, permission requirements, and parallel-safety classification.
Tool Profiles
| Profile | Description | Schemas |
|---|---|---|
Full | Complete tool descriptions and full JSON schemas | Full |
Lean (default) | Compact one-liner descriptions, schemas without field descriptions | Stripped |
Controlled via DEXT_TOOL_PROFILE. Lean mode saves significant prompt tokens per turn. A separate toolset profile is selected by --toolset or DEXT_TOOLSET: default hides specialized tools and full exposes the complete catalog. Frugal/tiny reduce context and result budgets without overriding explicit toolset or schema selections.
Tool Classification
| Category | Tools |
|---|---|
| Read-only (parallel-safe) | read_file, read_symbol, fd, rg, jq, fzf, git_diff, git_log, todo_read |
| Needs permission | bash, write_file, edit_file, multi_edit, http, awk, csvkit, git_commit, todo_write |
| External process | fd, rg, jq, fzf, awk, csvkit, git_diff, git_log |
Wire Format Adapters
wire_tools()— Anthropic format withcache_control: ephemeralwire_tools_oai()— OpenAIfunctiontype formatwire_tools_chatgpt()— ChatGPT flattened format withstrict: null
Runtime-only pack and shelf commands are intentionally separate from provider-visible tools. Packs act as modular battery packs: Dext creates, discovers, inspects, maintains, and invokes shelf-contained workflows through the existing tool, approval, and sandbox surface. Dext ships no pack content and adds no pack-specific provider-visible tools.
Tool_policy.rs — Risk & Guards .rs
Validates tool inputs, classifies command risk, and enforces bash guardrails.
Command Risk Levels
| Risk | Description | Examples |
|---|---|---|
Read | Read-only operations | ls, cat, git status, http GET |
Write | Modifies files or state | write_file, edit_file, non-dangerous bash |
Danger | Destructive or sensitive operations | sudo, rm -rf, git push, HTTP POST/DELETE |
Bash Guardrails
- Auto-injects
set -o pipefailif missing - Blocks
--break-system-packagespip flag (overridable) - Detects sudo commands needing password and routes to local auth prompt
- Bash calls are atomic: Unix roots run in detached sessions/process groups; Windows roots start suspended, enter kill-on-close Job Objects, then resume. Dext cleans the full child tree after completion, timeout, or interrupt.
- On Windows, shell-backed tools skip Windows/WSL app aliases and select a real
bash.exefromPATH(for example Git for Windows);DEXT_BASH_PATHprovides an explicit override. - Advisories: prefer
rgovergrep -r, preferfdoverfind
Input Validation
Every tool call is validated for required fields before execution. Missing/empty required fields, type mismatches, and mutually exclusive params are caught early with descriptive errors.
Auth Failure Detection
Tool output is scanned for auth failure markers (unauthorized, 401, 403, invalid api key) to trigger circuit breakers and prevent repeated credential burn on failing hosts.
Tui.rs — Terminal UI .rs
An inline TUI built on Ratatui + Crossterm that renders in the regular terminal buffer and preserves native terminal scrollback. The backend output viewer is the only alternate-screen surface.
Layout
- Transcript area — Scrollable message history with user, assistant, tool, thinking, and steering lines
- Live status bar — Provider, model, thinking effort, approval profile, context pressure, usage stats
- Input panel — Multi-line text input with history (200 entries), completion for slash commands
- Work map drawer — Collapsible work-ledger visualization
Startup Welcome
The startup welcome remains inline transcript content, so it scrolls away naturally with the conversation. One transcript-owned blank separator row keeps it visually distinct from CLI approval and sandbox diagnostics, including after inline viewport placement or replay. Its brand row shows Dext and the version, plus the working directory and cached Git branch/state at 80 columns or wider; narrower terminals drop that right segment. Exactly two facts, Model and Approval, sit between horizontal rules, followed by one rotating tip selected from verified commands and key bindings. Terminal-cell width controls alignment and path truncation. Git status uses one git status --porcelain=v1 --branch probe off the render loop, with only an 8 ms startup wait before path-only fallback. The empty composer reads ❯ Type a request… @ files · / commands.
Permission Prompts
Tool calls requiring permission show inline prompts with risk tier color coding (yellow for Read/Write, red for Danger). Choices: Once, Always (session), Deny.
Key Bindings
| Key | Action |
|---|---|
Enter | Submit input |
Shift+Enter / Alt+Enter | Insert newline |
Ctrl+O | Toggle the latest expandable tool output |
Ctrl+B | Open backend output viewer while bash runs |
Ctrl+L | Open the read-only current todo list without entering the alternate screen |
Ctrl+D | Quit |
Ctrl+C | Interrupt current turn |
Up/Down | Navigate input history |
Scroll | Navigate transcript |
? | Show keymap help |
Status and Active Time
The main status row presents the exact main branch label as Main, including Main (dirty) when the working tree is dirty, without renaming the branch or changing any other branch casing. It reserves its right edge for a live cumulative agent-active clock while Dext handles a turn. The clock advances during provider waits, tool calls, permission/auth waits, and in-turn compaction; while Dext is idle awaiting user input, it pauses and is hidden, then resumes on the next turn. It updates through the existing redraw cadence and uses compact forms such as 7s, 7m 05s, and 1h 07m without adding a timer thread.
Todo View
Ctrl+L opens a clean read-only modal during ordinary idle or busy work. Security-critical permission and local-auth prompts intentionally retain input and rendering priority and must be resolved or canceled first. The modal loads persisted session/project todos at startup, refreshes after todo_read/todo_write, scrolls with arrows, Page Up/Down, Home/End, or the mouse wheel, and closes with Ctrl+L, Esc, or q. Empty-state parsing matches Dext's generated sentinel lines exactly, so ordinary todo text cannot clear the modal accidentally. When todo progress is the live-status fallback above the composer, the battery follows the list length up to seven cells: Todos 3/4 ■■■□ maps one cell to each short-list item, while a longer list such as Todos 15/20 ■■■■■□□ stays capped and proportional. Partial progress retains at least one filled and one empty cell, and the active task remains visible when space permits. Editing remains on the existing todo_write path so validation, approval, checkpoint, and session-state behavior are not duplicated. The backend viewer remains the only alternate-screen surface.
Tool Result Rendering
Tool results are rendered as collapsible blocks with density grouping. Long outputs are compressed with head+tail preservation and JSON shape hints. Failed native write_file, edit_file, and multi_edit blocks explicitly state that no edits were applied, matching the atomic prepare-and-replace invariant. The alternate-screen backend viewer normalizes CRLF across arbitrary output chunks without introducing blank rows and visually matches the main TUI with a Dext header, agent-active clock, command summary, styled stdout/stderr lanes, output panel, command position, and compact controls. It continues to use the existing bounded ring buffer, selection, scrolling, event stream, and permission/auth priority.
Markdown Rendering
Assistant text blocks are rendered using tui-markdown with sanitization and terminal-safe formatting rules. Rendering preserves readability under narrow widths and avoids alternate-screen dependence.
Dependency and resize contract
The exact stack is ratatui 0.30.2, ratatui-core 0.1.2, tui-markdown 0.3.8, crossterm 0.29.0, and unicode-width 0.2.2. Dext selects exact versions and patches exact vendored ratatui-core source to avoid synchronous cursor-position queries during inline replay and whole-display clears during horizontal shrink.
The real-PTY regression suite verifies editable input during streaming, resize survival with populated history, zero whole-screen resize clears, bounded cursor queries, terminal-height-bounded replay chunks, and completed output after resize. Its final stream marker has a bounded 10-second wait so slower macOS CI hosts do not create false negatives. See docs/TUI.md and vendor/ratatui-core/DEXT_PATCH.md for the maintained contract and patch rationale.
Safety & Recovery
Git_checkpoints.rs .rs
Git-native recovery checkpoints created before approved non-read-risk tool calls in Git workspaces.
Checkpoint Lifecycle
- Create — Before a tool executes, a checkpoint is created under
refs/dext/checkpoints/<session>/<timestamp>-<ordinal>-<tool> - Dirty state capture — If the worktree is dirty,
git stash createcaptures a snapshot without touching the working tree or reflog - Untracked sidecar — For direct file tools, untracked files are saved to owner-private
.dext/checkpoints/<id>/storage; symlinked storage paths are rejected on Unix - Manifest — Appended to owner-private
.dext/checkpoints/manifest.txt;/.dext/is added to the repository-local Git exclude
Restore Modes
| Mode | Description |
|---|---|
Preview | Show diff vs current worktree without modifying anything |
Worktree | Checkout affected paths from checkpoint OID |
WorktreeAndIndex | Full worktree checkout from checkpoint OID |
ResetHead | Hard reset HEAD to checkpoint's original HEAD |
Pruning
Default: keep the 20 newest checkpoints and remove entries older than 168 hours (7 days). Pruning rebuilds local manifests, removes orphaned refs/dext/checkpoints/*, and deletes associated sidecar directories for bounded disk growth. Never mirror-push refs/dext/*.
Checkpoint Triggers
Always checkpointed: write_file, edit_file, multi_edit, todo_write, git_commit. Other tools are checkpointed when tool_policy::classify_command_risk() returns Write or Danger (for example write-risk bash/awk/csvkit or non-GET http).
Mutation_preview.rs .rs
Generates in-memory line-level mutation previews before applying direct file mutations. Shows the preview during permission prompts without touching disk.
Preview Flow
- Read the current file content (or empty for new files)
- Compute the proposed content (apply edit/multi-edit transforms in memory)
- Generate a simple line-level diff with one context line around changed hunks
- Cap at 4,096 bytes with a truncation notice
- Show added/removed line counts and whether it's a new file
Sandbox Validation
All paths are canonicalized and validated to be within the sandbox root. Paths outside the sandbox are rejected. Cross-platform display and Git pathspec rendering strips Windows verbatim prefixes and normalizes separators to forward slashes; work-ledger filtering recognizes both native and foreign-platform absolute paths.
Extensibility
Orchestrator.rs — Runtime Intelligence .rs
Per-turn runtime state that guards against loops, manages external resource access, and tracks objectives.
Work Phases
| Phase | Description |
|---|---|
Probe | Initial exploration — reading files, searching, understanding the codebase |
Scale | Expanded collection — triggered when probe passes for external hosts |
Synthesize | Final delivery — writing files, committing, producing the answer |
Guard Systems
- Dedupe cache — Short-circuits identical external requests within a turn
- Similarity guard — Blocks after 3+ similar unproductive bash/file operations
- Tool retry budget — Circuit breaker after 3+ failures with same error signature
- Empty tool call loop detection — Detects provider bug where tool arguments are dropped (threshold: 4 consecutive empty calls)
- Auth circuit breaker — Blocks hosts after 2 auth failures
- Feasibility guard — Requires single-item probes before bulk external collection
Objective Tracker
Parses user prompts to extract checkpoints (plan, analyze, implement, verify, document). Tracks satisfaction by examining tool usage patterns, bash commands, and assistant text.
Adaptive Caps
Tool UI content and result caps scale down dynamically based on context pressure: ≥90% → 25%, ≥75% → 50%, ≥60% → 75% of default. This preserves critical evidence near context limits while reducing prompt bloat.
Packs.rs — Pack System .rs
Packs are shelf-contained workflow documents, not plugin binaries. Dext supplies the create, discover, inspect, maintain, and run lifecycle; users own the content. The runtime reads PACK.md and executes through the existing Dext tool surface, keeping packs provider-neutral and auditable without bloating the core binary.
Design Contract
- No provider-visible tool expansion: packs orchestrate existing tools (
bash,read_file,rg, etc.). - Source-first reviewability: every pack is plain files in a directory.
- Deterministic discovery and precedence: first resolved name wins after ordered search roots.
- Optional hooks via
phooks.json, isolated from projecthooks.json.
<shelf>/packs/<name> in a user, project, or explicitly configured shelf root.Pack Object Model (PackInfo)
packs.rs normalizes each discovered pack into PackInfo with:
name,description, declaredcredential_envnames (from front matter or directory defaults)path,pack_md_path, optionalphooks_pathsourcelabel (project/env/user) and shelf ownership
Invocation wraps this as PackInvocation { pack, task } so the task is explicit and auditable.
Discovery and Creation
- Project shelves:
.dext/shelves/*/packs - Explicit shelf roots:
DEXT_SHELVES_DIR - User shelves:
~/.dext/shelves/*/packs
Create reusable packs with dext pack create <shelf>/<name>; add --project only for an explicitly project-local pack. The scaffold creates a minimal PACK.md, refuses overwrite, and is immediately available to normal inspection and invocation. Direct packs/, .dext/packs, ~/.dext/packs, DEXT_PACKS_DIR, and per-pack override roots are not discovery inputs.
The resolver deduplicates by canonicalized path and normalized pack name. Name collisions are resolved by precedence order, not random filesystem order.
Pack Layout and Front Matter
my-pack/
├── PACK.md # required; markdown workflow with YAML front matter
├── phooks.json # optional hook template for this pack
├── bin/ # optional helper scripts
└── README.md # optional human docs
---
name: my-pack
description: One-line workflow summary
credential-env: [SERVICE_TOKEN]
---
# Workflow
1) Setup
2) Probe
3) Transform
4) Verify
5) Deliver
Only PACK.md is required. Front matter stays minimal: identity/description plus an optional inline credential-env list of exact credential-shaped names required by the pack's own helper. That field is honored only for user and DEXT_SHELVES_DIR packs; project-local declarations are ignored.
Prompt Injection Model
pack_prompt() builds a bounded invocation prompt (cap: PACK_PROMPT_CAP = 32_000 bytes) containing:
- pack identity and source metadata
- paths for workflow and optional hooks
- pack-scoped environment names (
DEXT_PACK_DIR,DEXT_PACK_<NAME>_DIR), which the runtime supplies to active-packbashcalls and hook processes - declared credential names only, never their values
- full
PACK.mdworkflow body - explicit user task text
This gives the model procedural guidance without changing core runtime policy. The selected pack remains active for the session: its phooks.json entries are added to the hook set, and pack-scoped environment variables are passed to subsequent bash tool commands and hook processes. Declared credential values are narrower: for user and DEXT_SHELVES_DIR packs, they reach only a simple direct invocation of the active pack's own native bin/ helper, never hooks, arbitrary bash, pipelines/redirections, prompts, logs, or sessions; provider-auth names remain excluded. Project-local declarations are ignored. Changing the sandbox root clears active pack state.
Execution Paths
- CLI:
dext pack create <shelf>/<name>,list,inspect, andrun - Interactive:
/pack create,list,inspect, andrun - Conversational detection:
invoke <name>/run <name> on ...patterns mapped by selector inference
Operational Guidance for Pack Authors
- Write reproducible loops: inputs, stop conditions, verification gates.
- Install reusable packs under user-global Dext scope by default; use project-local roots only for intentionally repo-scoped packs.
- Keep shell helpers idempotent; prefer deterministic outputs for agent reuse.
- Use
phooks.jsononly when needed; packs must still function without hooks. - Treat pack workflows as code: version, test on disposable repos, and review diffs.
Outside the active sandbox, native mutation tools may write only below a concrete user pack directory (~/.dext/shelves/<shelf>/packs/<pack>/...) containing a regular PACK.md. Shelf manifests and loose files directly under packs/ remain outside that exception. Dext revalidates the destination and marker before atomic replacement; same-user path races remain outside the isolation boundary and are tracked in the risk register.
Shelves.rs — Shelf Registry .rs
Shelves are typed metadata registries over packs. They describe capabilities and signal/effect behavior without adding provider-visible tools.
Why Shelves Exist
- Give the model structured capability hints (commands/hooks/context) with low token cost.
- Separate extension metadata from prompt prose.
- Enable scoped override rules across core/user/project/run environments.
Manifest and Type System
shelf.json is parsed into ShelfManifest → PackManifest → Ability enums:
| Type | Purpose |
|---|---|
ShelfManifest | Identity, description, origin/scope, mode, and contained packs |
PackManifest | Pack id/name/version/description with typed abilities |
Ability | Tool, Command, Hook, Context |
Grant | Read/Write/Network/Process/Secret/Browser permission intent metadata |
Exposure | Hidden / OnDemand / Visible model-facing exposure level |
Signal and Effect Types
The shelf module defines a typed signal/effect vocabulary for in-process shelf implementations. Filesystem shelf.json manifests are declarative metadata: a matching load/prompt hook declaration can opt declared context into bounded prompt injection, but manifests do not register executable tools or slash commands and do not supply arbitrary effect handlers.
| Signals | Typical Use |
|---|---|
load, prompt, tool(before|after), turn(start|end), compact, shutdown | Typed lifecycle vocabulary for in-process shelves |
| Effects | Behavior |
|---|---|
note | Diagnostic annotation |
context | Inject prioritized context text |
block | Hard-stop signal flow with explicit reason |
rewrite_tool | Typed input-rewrite effect for an in-process shelf; not executed from a static manifest |
state | Typed state effect for an in-process shelf; static manifests do not persist it |
Block effects terminate in-process signal flow early. Static manifest shelves only produce context/note data for opted-in load or prompt signals.
Discovery and Scope Precedence
| Scope | Rank | Location | Intent |
|---|---|---|---|
Core | 0 | Bundled shelves | Base defaults |
User | 1 | ~/.dext/shelves | User-level customization |
Project | 2 | .dext/shelves | Repo-specific policy/context |
Run | 3 | DEXT_SHELVES_DIR | Per-invocation highest-priority overrides |
resolve() keeps one winning ability per key using tuple ordering by scope rank and stable discovery order. This gives deterministic override semantics.
Prompt and CLI Surfaces
render_registry_listing()powersdext shelves//shelvesoperator visibility.registry_summary_for_prompt()injects compact typed ability summaries into model context.- Ability metadata is provider-neutral and does not modify the external tool schema.
Methodology for Building Shelf Ecosystems
- Start with pure packs; add shelf metadata only for reusable capability contracts.
- Define ability keys as stable API-like surfaces.
- Use project scope for repository policy, user scope for personal defaults, run scope for experiments.
- Treat
shelf.jsonas versioned interface documentation and test precedence resolution.
Testing & Performance
Testing
Unit Tests (main_tests.rs)
The test suite covers provider catalogs and request shaping, auth and state formats, stream/tool-call assembly, tool policy, sandboxing, side-effect journals, recovery checkpoints, TUI rendering, and runtime orchestration. Git fixture subprocesses explicitly clear ambient repository-routing variables such as GIT_DIR and GIT_WORK_TREE, so parallel environment-isolation tests cannot redirect unrelated temporary repositories.
- Provider catalog loading, normalization, and model resolution
- Auth store operations (save, load, normalize)
- Session header parsing and backwards compatibility
- Tool input validation and risk classification
- Bash guardrails and sudo detection
- Checkpoint creation and restore logic
- Objective tracking and satisfaction assessment
- URL host extraction, proxy isolation, destination policy, and exact redirect limits; redirect fixtures use bounded blocking reads on accepted sockets for consistent Windows behavior
Run with: cargo test --release --locked
Real-PTY TUI Regression Suite (tests/tui_smoke.rs)
Spawns the real Dext binary in a Unix PTY at narrow and wide terminal sizes and verifies:
- Application launch, banner/composer rendering, help, multiline input, and clean Ctrl+D exit
- Editable input while output streams and process survival during populated-history resize bursts
- Zero whole-screen clears, resize-bounded cursor queries, and terminal-height-bounded replay chunks
- Completed stream output and accepted input after resize, with no crash markers
Run with: cargo test --release --locked --test tui_smoke -- --nocapture
The complete verification gate also runs formatting, Clippy with warnings denied across the Linux, macOS, and Windows CI matrix, vulnerability auditing, dependency-license policy checks, the vendored ratatui-core unit tests, and a locked release build. Release publication generates dext.cdx.json, includes it in SHA256SUMS, and attests and verifies it alongside the four platform archives. The first successful tag run remains tracked in docs/RELEASING.md until the publication path has end-to-end evidence. On Windows CI and release builders, the scheduler-sensitive fast_bash_command_returns_without_100ms_poll_tail regression runs alone after the remaining release tests. Its original <90 ms assertion remains unchanged; isolation prevents unrelated suite load from obscuring the process-wait regression it measures. The tool-call mock provider consumes its bounded Content-Length request body before responding so Windows does not reset the connection with unread request data. See docs/TUI.md for renderer-specific live-terminal checks.
GitHub Pages
The public site at siliconstate.github.io/Dext is deployed from the static docs/ tree by .github/workflows/pages.yml. The workflow validates local links and anchors, uploads an immutable Pages artifact, and deploys with only pages: write and id-token: write in the deployment job. Third-party actions are pinned to full commit hashes and checkout credentials are not persisted.
bash tool under workspace-write. The sandbox's shared-temp denial can create many follow-on test failures after a common environment lock is poisoned; PTY denial prevents this smoke test from creating terminals; and Cargo-home protection blocks local installation metadata. These denials demonstrate confinement, but do not count as a successful release gate. Rerun from a trusted host terminal or CI.Benchmarks (benches/dext_bench.rs)
Criterion benchmarks for performance-critical paths:
| Benchmark | What it measures |
|---|---|
production_sse_decode/coalesced_provider_read | Production SSE framing for 512 events delivered in one provider read |
production_sse_decode/fragmented_97_byte_reads | The same production decoder under fragmented network reads |
Run with cargo bench; CI and the release quality job compile the benchmark with cargo bench --no-run --locked.
Build Profile
Release builds use: lto = false, codegen-units = 16, strip = "symbols" — optimized for build speed while keeping binary size small.
Reference
CLI Reference
| Command | Description |
|---|---|
dext | Start interactive session |
dext "prompt" | One-shot task |
dext -p | Read prompt from stdin |
dext --resume | Resume latest session |
dext --fork | Fork latest session into new session |
dext session ... | Brief/map/packet/focus/track/export/analyze/grep/failures/verification/decision operations |
dext doctor [...] | Inspect effective safety policy and bounded local state without repair or provider calls |
dext pack list|inspect|run ... | Discover or invoke source-first packs |
dext shelves | List typed shelf manifests and ability metadata |
dext --cd <dir> | Change working directory |
dext --no-session | Don't save session |
dext --pack <name> "task" | Invoke a pack in one-shot mode |
dext --frugal / dext --tiny | Select reduced-context modes |
dext --context-mode standard|frugal|tiny | Choose context/cap mode |
dext --toolset default|full | Choose provider-visible tool count profile |
dext --tool-profile lean|full | Choose provider tool schema verbosity |
dext --preview off|simple|git | Choose mutation preview mode |
dext --sandbox read-only|workspace-write|danger-full-access | Set sandbox profile |
dext --eval | Run eval harness |
dext --output json|stream-json | Machine-readable output |
dext --effort off|low|medium|high|xhigh|max | Thinking effort |
dext --approval ask|auto-read|auto-write|never|always | Approval profile |
dext --trust | Explicitly select approval always |
dext --no-trust | Explicitly select the default ask approval profile |
dext --budget <amount> | Session budget cap (e.g., $0.50, 100ktok) |
Auth Subcommands
| Command | Description |
|---|---|
dext auth providers | List available providers |
dext auth login <provider> [key] | Login to a provider |
dext auth logout <provider> | Remove stored credentials |
dext auth status | Show auth status for all providers |
Other Subcommands
| Command | Description |
|---|---|
dext undo --list | List recovery checkpoints |
dext undo --preview <id> | Preview checkpoint restore without modifying files |
dext undo --apply <id> | Apply a checkpoint restore |
dext undo --prune | Remove expired and excess checkpoints |
dext pack list | List available packs |
dext pack inspect <name> | Show pack details |
dext pack run <name> "task" | Run a pack |
dext shelves | List shelf manifests and abilities |
Slash Commands
| Command | Description |
|---|---|
/help | Show available commands |
/quit, /exit | Exit Dext |
/reset | Clear conversation history |
/tools [default|full] | List or switch provider-visible tools |
/history | Show turn count and last 5 messages |
/system [text] | Show or replace system prompt |
/allow <tool> | Auto-approve a specific tool for this session |
/revoke <tool> | Remove auto-approval for a tool |
/allowed | List auto-approved tools |
/trust [on|off|status] | Auto-approve all gated tools |
/approval [profile] | Set approval profile |
/sandbox [path] | Show or change sandbox root |
/sandbox-profile [profile] | Set sandbox: read-only, workspace-write, danger-full-access |
/privacy [on|strict|off|status] | Control local redaction and optional strict native-read path blocking |
/effort [level] | Set thinking effort: off, low, medium, high, xhigh, max |
/model [name] | Show or change model |
/provider [id] | Show or change provider |
/models | List available models |
/providers | List providers and auth status |
/login <provider> [key] | Login to a provider |
/logout <provider> | Logout from a provider |
/compact [N%] | Run compaction or set threshold |
/context [mode] | Set context mode: standard, frugal, tiny |
/tool-profile [lean|full] | Set provider tool schema verbosity |
/usage | Show cumulative token usage |
/status | Show runtime diagnostics |
/tokens | Approximate tokens per message and top context hogs |
/diagnostics | Run rust-analyzer diagnostics, falling back to cargo check |
/save <name> | Save history/config to named JSONL session |
/export [html|jsonl] [path] | Export the current session |
/resume [name] | Resume latest or named session |
/sessions ... | List/analyze/map/grep/focus/export session history |
/plan <task> | Run read-only planning and seed the plan into history |
/budget [cap] | Set or show budget cap |
/pack create|list|inspect|run | Create or use shelf-contained packs |
/shelves | Show shelf registry |
/undo [--list|--apply|<id>] | Recovery checkpoint preview/apply management |
Tool Reference
Dext implements 18 provider-visible tools. The default profile contains 13 core tool names. Specialized tools (jq, fzf, awk, git_log, csvkit) require dext --toolset full, DEXT_TOOLSET=full, or /tools full. User-authored shelf packs orchestrate this existing surface and do not modify the tool count.
File Operations
| Tool | Permission | Description |
|---|---|---|
read_file | Read | Read file with line numbers. Explicit offset+limit gets larger cap. |
read_symbol | Read | Locate a source symbol or block around a line number. |
write_file | Write | Write content to file, creating parent dirs. Overwrites existing. |
edit_file | Write | Replace exactly one occurrence of old_string with new_string. |
multi_edit | Write | Batch of exact-string edits applied atomically to one file. |
Search & Discovery
| Tool | Permission | Description |
|---|---|---|
fd | Read | Find files by regex pattern. Subprocess-execution flags are rejected. |
rg | Read | Search file contents. Preprocessor and subprocess-capable flags are rejected. |
fzf | Read, full toolset | Non-interactive fuzzy filter. |
Shell & Process
| Tool | Permission | Description |
|---|---|---|
bash | Varies | Execute shell command with pipefail. Risk classified. |
awk | Varies, full toolset | AWK text processor. Optional stdin. |
Data Processing
| Tool | Permission | Description |
|---|---|---|
jq | Read, full toolset | Query/transform JSON. |
csvkit | Varies, full toolset | CSV processing suite: csvcut, csvstat, csvgrep, csvjson, etc. |
HTTP
| Tool | Permission | Description |
|---|---|---|
http | Varies | HTTPie-style client. Loopback, private/CGNAT, unique-local, link-local, and metadata destinations are blocked after DNS resolution and across redirects unless narrowly opted in. |
Git Operations
| Tool | Permission | Description |
|---|---|---|
git_diff | Read | Show git diff. Prefer stat=true first. |
git_log | Read, full toolset | Show recent git log entries. |
git_commit | Write | Stage files and create commit. |
Task Management
| Tool | Permission | Description |
|---|---|---|
todo_read | Read | Read project todo list. |
todo_write | Write | Replace project todo list. |
Environment Variables
| Variable | Default | Description |
|---|---|---|
DEXT_HOME | ~/.dext | Dext state directory |
DEXT_SESSIONS_DIR | Project-scoped | Override sessions directory |
DEXT_LOGS_DIR | Project-scoped | Override logs directory |
DEXT_LOG_ARCHIVES | 0 | Number of log archives to keep (max 16) |
DEXT_PROVIDER | Catalog active | Active provider ID |
DEXT_PROFILE | Catalog active | Alias for DEXT_PROVIDER |
DEXT_API_PROVIDER | Catalog active | Provider selection by API family |
DEXT_API_KEY | — | Override API key for any provider |
DEXT_MODEL | Profile default | Override model for any provider |
DEXT_MODEL_FORCE | false | Force DEXT_MODEL even if incompatible |
DEXT_PROVIDER_CONNECT_TIMEOUT_SECS | 15 | Provider TCP/TLS connection deadline |
DEXT_PROVIDER_FIRST_BYTE_TIMEOUT_SECS | 180 cloud · 600 local | Deadline through response headers; one positive override applies to all providers |
DEXT_PROVIDER_STREAM_IDLE_TIMEOUT_SECS | 90 cloud · 300 local | Maximum idle interval between provider body/stream chunks |
DEXT_MODEL_{PROVIDER} | — | Provider-specific model override |
DEXT_BASE_URL | Profile default | Override base URL for any provider |
ANTHROPIC_BASE_URL | Profile default | Override Anthropic-family base URL |
OPENAI_BASE_URL | Profile default | Override OpenAI-family base URL |
DEXT_CONTEXT_MODE | standard | Context mode: standard, frugal, tiny |
DEXT_TOOLSET | default | Provider-visible tool count profile: default, full |
DEXT_TOOL_PROFILE | lean | Tool schema profile: full, lean |
DEXT_MUTATION_PREVIEW | simple | Mutation preview mode: off, simple, git |
DEXT_APPROVAL | ask | Approval profile: ask, auto-read, auto-write, never, always |
DEXT_SANDBOX_PROFILE | workspace-write | Sandbox profile: read-only, workspace-write, danger-full-access. On supported Linux/macOS hosts, confined profiles preserve reads available to the Dext process user; workspace-write permits writes only under the sandbox, scratch roots, and explicit toolchain cache/package roots. macOS Seatbelt profiles allow both canonical /private/... scratch paths and their /var or /tmp aliases so standard temp APIs remain confined but usable. |
DEXT_PRIVACY | true | Before model context and session logging, replace private-key blocks, real secret assignments, and explicitly labeled SSNs, payment-card numbers, and account identifiers while keeping user-readable files readable. Set to strict to also block sensitive-looking native read paths; disable only for intentionally raw output. |
DEXT_INHERIT_TOOL_CREDENTIALS | false | High-trust opt-in to pass credential-shaped parent environment variables to model-invoked bash/external tools. Hooks and Dext-owned subprocesses remain scrubbed. |
DEXT_BUDGET_CAP | — | Session budget cap (e.g., $0.50, 100ktok) |
DEXT_CONTEXT_WINDOW_TOKENS | Profile default | Override context window size |
DEXT_CONTEXT_WINDOW | Profile default | Alias override for context window size |
DEXT_BASH_TIMEOUT_SECS | 60 | Default bash command timeout |
DEXT_BASH_PATH | bash | Explicit Bash executable. On Windows, the default resolver skips Windows/WSL app aliases and selects a real bash.exe from PATH. |
DEXT_ALLOW_BREAK_SYSTEM_PACKAGES | false | Allow the otherwise-blocked pip --break-system-packages flag |
DEXT_EXTERNAL_TIMEOUT_SECS | 60 | Default timeout for external tools |
DEXT_HOOK_TIMEOUT_SECS | 60 | Default timeout for hook commands |
DEXT_TRUST | false | Explicit alias for approval always when set to a true value; false values do not override the default ask profile. |
DEXT_HTTP_ALLOW_LOOPBACK | false | Built-in HTTP tool only: allow loopback and unspecified/local destinations. |
DEXT_HTTP_ALLOW_PRIVATE | false | Built-in HTTP tool only: allow private, CGNAT, and IPv6 unique-local destinations. |
DEXT_HTTP_ALLOW_LINK_LOCAL | false | Built-in HTTP tool only: allow link-local and cloud-metadata destinations. |
DEXT_NO_TUI | false | Disable inline TUI even when a terminal is available |
DEXT_SYSTEM | Built-in prompt | Override the base system prompt |
DEXT_SANDBOX | . | Override sandbox root path |
DEXT_HOOKS_FILE | hooks.json | Override project hook configuration file |
DEXT_SUDO_ASKPASS | — | Custom askpass helper for sudo |
DEXT_SHELVES_DIR | — | Additional shelf directories |
DEXT_SESSION_TAG | PID | Session tag for checkpoint ref names |
ANTHROPIC_API_KEY | — | Anthropic API key |
OPENAI_API_KEY | — | OpenAI API key |
KIMI_API_KEY | — | Kimi Code plan API key; distinct from MOONSHOT_API_KEY |
ZAI_API_KEY | — | ZAI GLM API key |
CHATGPT_ACCESS_TOKEN | — | ChatGPT/Codex access token override |
DEEPSEEK_API_KEY | — | DeepSeek API key |
Provider Details
GLM (ZAI)
- Default built-in provider. Uses the Anthropic-compatible API at
api.z.ai/api/anthropic - Catalog models: glm-5.2[1m] (default), glm-5.2, glm-5.1, glm-5.0, and glm-4.6. The 5.2 variants declare 1M context; the provider fallback is 200K.
- Auth: API key via
ZAI_API_KEYordext auth login glm <key>
ChatGPT / Codex
- Uses the OpenAI OAuth flow with a local callback server on port 1455
- Catalog models include GPT-5.6 Sol/Terra/Luna, gpt-5.4 and 5.4-mini, gpt-5.5, Codex variants, gpt-5/mini, gpt-4.1, gpt-4o/mini, o3/o3-mini, and o4-mini.
- GPT-5.6 variants declare 1.05M context and 128K output metadata; other models use the provider fallback or explicit model overrides. Auth:
dext auth login chatgptorCHATGPT_ACCESS_TOKEN.
OpenAI API
- Standard OpenAI Platform API using API-key auth
- Catalog models include the official gpt-5.6 Sol alias plus Sol/Terra/Luna variants, gpt-5/mini, gpt-4.1/mini, gpt-4o/mini, o3/o3-mini, and o4-mini. Model-specific metadata overrides the 400K provider fallback.
- Auth: API key via
OPENAI_API_KEYordext auth login openai <key>
Anthropic
- The catalog includes current Sonnet, Opus, Fable, and Haiku model variants.
- Context fallback: 200K tokens. Auth:
ANTHROPIC_API_KEYordext auth login anthropic <key>.
Kimi Code
- Uses Anthropic Messages semantics at
api.kimi.com/coding; default model K3 declares 1,048,576-token context, 131,072-token output metadata, and adaptivemaxthinking. - Auth: Kimi Code plan API key via
KIMI_API_KEYordext auth login kimi <key>. This key is distinct fromMOONSHOT_API_KEY.
DeepSeek
- OpenAI-compatible API
- Models: deepseek-chat, deepseek-reasoner — Context: 128K tokens — Auth:
DEEPSEEK_API_KEY
Local (llama.cpp)
- OpenAI-compatible local server at
127.0.0.1:8080— No API key required — accepts the configured server model alias; local providers default to frugal context and probe llama.cpp for the live runtime context window without model-specific built-in context values. If the local server is offline, discovery falls back cleanly and the later provider request reports the ordinary connection error.
Configuration Files
Provider catalogs and auth stores are read through bounded non-symlink regular-file checks. On Unix, foreign ownership is rejected; group/world-writable provider catalogs are rejected; owner-owned auth files with loose mode are repaired to 0600 before parsing. dext doctor uses bounded, no-follow, inode-stable inspection and reports the same ownership/mode policy without repairing files.
providers.json (~/.dext/providers.json)
Provider catalog with merged built-in + custom profiles. Editable via /provider and /model commands. Auto-normalized on load.
Catalog v2 profiles may set request_contract to anthropic-messages, openai-chat-completions, or chatgpt-responses. Optional model_aliases, model_defaults, and model_specs provide canonical model ids, limits, effort levels, capabilities, and pricing. Explicit per-model metadata wins; context hints in model names such as -128k and [1m] win over provider-wide context defaults. Built-in metadata only fills omissions, and v1 profile fields remain accepted. DEXT_PROMPT_CACHE=on|off overrides catalog prompt-cache capabilities for Anthropic-style requests; auto mode uses catalog metadata.
auth.json (~/.dext/auth.json)
API-key entries may reference a parent environment variable by name or intentionally run a !command through bash -lc. Treat write access to this store as code-execution authority.
Stored credentials per provider. Set to mode 0600 on Unix. Supports ApiKey and OAuth credential types. Credential-shaped parent environment variables are removed from agent-run subprocesses by default. DEXT_INHERIT_TOOL_CREDENTIALS=1 opts in only trusted model-invoked bash/external tools; hooks and Dext-owned subprocesses remain scrubbed.
.env (~/.dext/.env or $DEXT_HOME/.env)
Optional user-owned Dext settings. Project .env files and parent directories are never auto-loaded, so repository content cannot silently alter runtime policy.
DEXT.md (sandbox ancestry)
Tracked machine-facing project guidance auto-injected into the system prompt. Dext scans the sandbox root and ancestors and does not modify the file automatically.
recall.md (optional sandbox ancestry)
Optional ignored prompt cache. It is auto-injected only when present; Dext does not create or update it automatically.
hooks.json (project root or DEXT_HOOKS_FILE)
Project-root hooks configuration loaded from hooks.json by default, or from DEXT_HOOKS_FILE when set. This is not the same as pack phooks.json.