EN 中文

# Architecture & Design

# 设计与架构

How seek works under the hood.

seek 的底层工作原理。

1

### Three-Tier Memory (L / M / S)

### 三层记忆 (L / M / S)

seek doesn't start from zero every session. Three layers of persistence capture knowledge at different timescales:

seek 不会每次会话从零开始。三层持久化以不同时间尺度捕捉知识：

- Soul (L) — `~/.seek/soul.md`. Cross-project user preferences and thinking habits. ~500 token hard cap, resident in system prompt. Written by `seek -dream` → user review.
- Project (M) — `~/.seek/projects/<hash>/memory.jsonl`. Key decisions and rationale per project. Index injected into every prompt; full content fetched on demand via `memory_recall`.
- Session (S) — `~/.seek/sessions/<id>.jsonl` (or `$SEEK_HOME/sessions/`). Full message history with auto-save. `/distill` at session end extracts reusable decisions into M.

📁 `pkg/agent/memory/` · `internal/memory/` · `docs/guide-memory.md`
2

### Permission System (Pref × Workflow, two axes)

### 权限系统（Pref × Workflow 双轴）

After R1 refactor, permission lives on two orthogonal axes — never crammed into a single enum:

R1 重构后，权限走两条正交轴——不再合并成一个 enum：

- Preference (`Deny` / `Ask` / `Yolo`) — your standing posture. "How strict am I." Chosen at startup (`--yolo`, `--no-perm`) or toggled via `/yolo`.
- Workflow (`None` / `PlanAnalyze` / `PlanExecute`) — the ceremony you've entered. "What am I doing." Toggled via `/plan` and the propose-tool flow.

Workflow trumps Preference where they conflict. `PrefYolo + WorkflowPlanAnalyze` is still read-only — that's plan mode's raison d'être. The workflow is a user-chosen safety boundary; pref can't override it.

Workflow 永远 trump Preference。`PrefYolo + WorkflowPlanAnalyze` 仍然是只读——这正是 plan mode 存在的意义。Workflow 是用户选定的安全边界，pref 不能反过来覆盖。

Permission denials are tool results, not errors — the agent sees the denial message and asks the user (or reconsiders), rather than crashing the loop.

权限拒绝是工具结果，而非错误——agent 看到拒绝消息后会询问用户（或重新考虑），而不是中断循环。

📁 `internal/permission/` · see `docs/prd/feature-permission-refactor.md`
3

### Tool System

### 工具系统

seek exposes tools to the LLM as JSON schema definitions. Current tools:

seek 以 JSON schema 定义向 LLM 暴露工具。当前工具列表：

- `read` / `grep` / `list_dir` — filesystem exploration (grep first, read offset-limited segments)
- `write` / `edit` — file mutation (edit requires exact `old_string`, unique match)
- `bash` / `git` — shell + git porcelain (denied without `--yolo` or in plan-analyze workflow)
- `fim_complete` — DeepSeek-specific fill-in-the-middle (cheaper than chat for small gaps)
- `think` — DeepSeek reasoning mode for planning and self-review
- `webfetch` — HTTPS GET with SSRF guard (works in plan-analyze; private-IP + redirect-target validation)
- `mcp` — bridge to external MCP servers (stdio / SSE / WebSocket transports)
- `ask_user` — open a TUI picker to gather user choice mid-loop
- `Skill` / `skill_fetch` / `skill_commit` — discover, install, and invoke skills
- `memory_observe` / `memory_recall` / `memory_amend` / `memory_archive` — M-layer read/write
- `propose` / `plan` — plan-mode v2 confirmation-gated workflow (analyze → propose → execute → adjust → report)
- `agent` / `enter_worktree` / `exit_worktree` — spawn subagents (v5 柱 G); marked ReadOnly so multiple `agent` calls dispatch in parallel
- `schedule_wakeup` — model self-schedules a future check-in (v5 柱 H one-shot cron)

Key constraint: Tool schemas are `[]byte` constants at package level (built once at init, not at call time). This ensures identical bytes across turns → DeepSeek's prefix cache hits.

关键约束：工具 schema 是包级别的 `[]byte` 常量（在 init 时构建一次，而非每次调用）。这确保跨轮次的字节一致性，从而命中 DeepSeek 的前缀缓存。

📁 `internal/tools/` · each tool in its own package with a `New(...)` constructor
4

### Prefix Cache Optimization

### 前缀缓存优化

DeepSeek charges ~10× less per token on cache hits. The cache key is an exact byte sequence of the entire prior message history. This drives several architecture decisions:

DeepSeek 对缓存命中收取约 1/10 的价格。缓存键是完整历史消息的精确字节序列。这驱动了以下架构决策：

- System prompt is immutable within a session — changing it invalidates the prefix cache for the entire history.
- No in-transit message mutation — even "compression" of old tool results would break byte identity.
- Token optimisation happens at write-time (tool output size limits), not at send-time.
- Status bar shows real-time cache hit ratio + saved tokens, making cache-friendly prompts an observable optimisation target.
- Off-peak countdown — 50% discount during 00:30–08:30 Beijing time, shown in the status bar.

📁 `internal/pricing/` · `pkg/deepseek/` (cache stats in API response)
5

### Multi-Provider Layer

### 多 Provider 层

seek is DeepSeek-first but provider-agnostic. The architecture splits into two tiers:

seek 以 DeepSeek 为第一优先，但与 Provider 无关。架构分为两层：

- `pkg/deepseek` — first-class client with DeepSeek-specific fields: cache metadata, FIM endpoint, reasoner content. Zero external dependencies.
- `pkg/llm` — thin generic interface for Anthropic, OpenAI, Gemini, and OpenAI-compatible endpoints.

Critical rule (CI-enforced): `pkg/deepseek` must not import `pkg/llm`. DeepSeek-specific optimisations must never be lowered into a generic interface.

关键规则（CI 强制）：`pkg/deepseek` 不能导入 `pkg/llm`。DeepSeek 专属优化绝不能被降级到通用接口中。

📁 `pkg/deepseek/` · `pkg/llm/` · `pkg/agent/` (type switch between tiers)
6

### Session Persistence

### 会话持久化

Sessions are stored as JSONL files (`schema_version=2`):

会话以 JSONL 格式存储（`schema_version=2`）：

- Line 1 — header with all scalar metadata (model, timestamps, token counts). `loadMeta()` reads only this line — no need to load the full file for the session list.
- Lines 2..N — one `deepseek.Message` per line in JSON.
- Auto-save after every turn. `/branch` forks to a new file; `/compact` summarises old history.
- Durability: write-tmp-rename pattern with `f.Sync()` before `f.Close()`.

📁 `internal/session/` · `docs/guide-sessions.md`
7

### Plan Mode v2 — confirmation-gated workflow

### Plan Mode v2——确认门工作流

`/plan` is more than read-only exploration. The model analyzes context, proposes a problem definition + step list via the `propose` tool, waits for user approve / adjust / cancel, then enters EXECUTE substate with per-step gating via the `plan` tool.

`/plan` 不只是只读探索。模型分析上下文 → 通过 `propose` 工具提议问题定义 + step list → 等待用户 approve / adjust / cancel → 进入 EXECUTE 子态，通过 `plan` 工具按步审批。

- State machine via transcript — substate is reconstructed on `seek -resume` by replaying `propose` args + `plan(start|complete|skip)` events. No parallel state file.
- 状态机由 transcript 重建——`seek -resume` 通过 replay `propose` 参数 + `plan(start|complete|skip)` 事件重建子态，无并行状态文件。
- Plan artifact — every approve writes a read-only markdown snapshot to `~/.seek/projects/<id>/plans/`. Audit trail of "at moment X, approved these steps for problem Y."
- Plan artifact——每次 approve 写入只读 markdown 快照到 `~/.seek/projects/<id>/plans/`。"在 X 时刻、对 Y 问题、批准了哪几步"的审计记录。
- approve_batch (auto-approve-per-step) — opt-in fast-path: bash/edit/write inside an active step auto-pass without re-prompting. Status bar shows substate + `N/M` progress.
- approve_batch（按步预批准）——可选 fast-path：活跃步骤内的 bash/edit/write 自动通过，不再询问。状态栏显示子态 + `N/M` 进度。

📁 `internal/tools/propose/` · `internal/tools/plan/` · `docs/prd/feature-plan-mode.md`
8

### Subagent & Worktree (v5 柱 G)

### 子代理 & Worktree（v5 柱 G）

The parent agent can spawn subagents — each with its own session, token budget, and optionally an isolated git worktree — to run parallel research, drafting, or experimentation. Only the summary crosses back, so the parent's prefix cache stays warm.

父 agent 可派生子代理——各自独立 session、token 账户，可选 git worktree 隔离——并行调研、起方案或试验。只有 summary 回到父，父的 prefix cache 不被击穿。

- Permission monotonic-tighten — a child's `Pref × Workflow` can only be tighter than the parent's. `Policy.Spawn(restriction)` enforces it at the type level.
- 权限单调收紧——子的 `Pref × Workflow` 只能比父更严。`Policy.Spawn(restriction)` 在类型层强制。
- Cost rolled up — `cache.Tracker.AdoptChild` wires the child's per-turn usage into the parent's cumulative cost. Status bar shows the full picture.
- 成本归集——`cache.Tracker.AdoptChild` 把子的每轮 token 累加到父的 cumulative cost。状态栏展示完整画面。
- Spawn depth = 1 — subagents cannot themselves spawn. Prevents fan-out runaway.
- 派生深度 = 1——子不能再派生。防止 fan-out 失控。
- ReadOnly dispatch marker — the `agent` tool is marked `ReadOnly` so multiple `agent` calls in one assistant turn run concurrently, not sequentially.
- ReadOnly 派发标记——`agent` 工具标 `ReadOnly`，让一轮多个 `agent` 调用并行跑，不串行。

📁 `internal/subagent/` · `internal/worktree/` · `internal/tools/agent/` · 📖 Subagent docs
9

### Cron / Wakeup / Triggers (v5 柱 H)

### 定时 / 唤醒 / 触发（v5 柱 H）

seek runs no resident daemon. Scheduling delegates to the OS (launchd / systemd / cron / Task Scheduler), which invokes `seek cron tick` once a minute. tick reads `jobs.jsonl` + `triggers/`, fires what's due, exits.

seek 零常驻 daemon。调度委派给 OS（launchd / systemd / cron / Task Scheduler），每分钟调用 `seek cron tick`。tick 读 `jobs.jsonl` + `triggers/`，触发所有到期，退出。

- Three input sources — scheduled jobs (`seek cron create`), model self-scheduled wakeups (`schedule_wakeup` tool, max_runs=1), and external triggers (CI / IDE writes JSON to `~/.seek/cron/triggers/`).
- 三类输入——定时任务（`seek cron create`）、模型自调用唤醒（`schedule_wakeup` 工具，max_runs=1）、外部触发（CI / IDE 写 JSON 到 `~/.seek/cron/triggers/`）。
- Explicit env injection — OS schedulers hand seek a near-empty env. Opt-in `~/.seek/cron/env` overlay (dotenv format) supplies `DEEPSEEK_API_KEY` and friends. Parse errors fail spawn loudly.
- 显式 env 注入——OS 调度器 env 极简。可选 `~/.seek/cron/env` 覆盖文件（dotenv 格式）注入 `DEEPSEEK_API_KEY` 等。解析错误明确报错。
- OS notifications — macOS `osascript` ✅ / Linux `notify-send` ✅ (auto no-op when headless) / Windows ⚠️ no-op pending BurntToast adapter (v0.6.x dot).
- OS 通知——macOS `osascript` ✅ / Linux `notify-send` ✅（headless 自动 no-op）/ Windows ⚠️ no-op，BurntToast 适配在 v0.6.x dot。
- Two-axis GC — `runs/<id>.jsonl` keeps 100 recent + 30 days max-age; `.malformed/` keeps 20 recent + 14 days. Suffix filter ensures live `<job>.lock` files in `runs/` are NEVER deleted.
- 双轴 GC——`runs/<id>.jsonl` 保留 100 个最近 + 30 天最老；`.malformed/` 保留 20 个最近 + 14 天。后缀过滤确保 `runs/` 中活跃的 `<job>.lock` 文件永远不被删。

📁 `internal/routines/` · `internal/routinescli/` · 📖 Cron docs · guide-cron.md
📖 For the full design rationale, see docs/prd/v0.md and the book series. 📖 完整设计原理见 docs/prd/v0.md 和 系列丛书。