OpenSeek is a small MoonBit foundation for a DeepSeek-backed coding agent. The module is split into pure data, HTTP transport, agent orchestration, and a CLI entry point so request encoding can be tested without network access.
For a picture of how the pieces fit together — module architecture, the core
data model, and the life of one agent turn — see
docs/architecture.md.
The root moon.work develops OpenSeek, the desktop app, and the
moonbitlang/editor source together. The editor keeps its
smaller editor/moon.work as a scoped entry point for editor-only builds and
browser tests; root Moon commands are the integration gate across both projects.
A fresh checkout needs the MoonBit toolchain and just; just check also
requires jq to inspect structured compiler diagnostics. Initialize the Lepus
submodule before running the root integration gates:
git submodule update --init desktop/lepus
just check # native + JS workspace checks and formatting
just test # native + JS workspace tests and OpenSeek cram tests
just build # native + JS MoonBit builds
just editor-build # editor web distribution and server
just editor-test # editor-only tests on every supported target
just editor-test-browserThe editor browser suites additionally need Node.js 18 or newer, the locked npm dependencies, and a Playwright-managed Chromium installation:
cd editor
npm ci
npx playwright install chromiumLinux hosts that lack Playwright's system dependencies can use the CI form,
npx playwright install --with-deps chromium.
Neither editor reference submodule is needed for the normal build, test, or browser smoke gates. Initialize CodeMirror only for source-reference research; initialize VS Code only for the opt-in editor performance suite:
git submodule update --init editor/codemirror # source-reference research
git submodule update --init editor/vscode # opt-in performance suite| Package | Purpose | Docs |
|---|---|---|
bobzhang/openseek |
Root package and module overview. | README.mbt.md |
bobzhang/openseek/deepseek |
Pure DeepSeek chat data, JSON encoding, and response decoding. | deepseek/README.mbt.md |
bobzhang/openseek/deepseek/client |
Native-only HTTP transport for DeepSeek chat completions. | deepseek/client/README.mbt.md |
bobzhang/openseek/agent_runtime |
Native-only agent task-group and extensible runtime event queue. | agent_runtime/README.mbt.md |
bobzhang/openseek/agent_session |
Typed durable conversation state and DeepSeek message projection. | agent_session/README.mbt.md |
bobzhang/openseek/agent_session/store |
Native filesystem-backed append-only session store. | agent_session/store/README.mbt.md |
bobzhang/openseek/agent_session/log |
Lenient session-file reader: header plus events, with per-line error capture. | — |
bobzhang/openseek/agent_session/compact |
Context-checkpoint (compaction) request building and summary handling. | — |
bobzhang/openseek/agent_tool |
Tool registry, executor, output, and control-action types; one subpackage per built-in tool. | agent_tool/README.mbt.md |
bobzhang/openseek/agent_skill |
Workspace skills: markdown playbooks discovered from skill libraries and listed in the system prompt. | agent_skill/README.mbt.md |
bobzhang/openseek/jsonrpc |
Duplex JSON-RPC 2.0 client (concurrent requests, notifications, out-of-order replies). | — |
bobzhang/openseek/mcp (+ config, stdio, streamhttp, tools) |
MCP client: mcp.json decoding, stdio and Streamable HTTP transports, and the bridge that namespaces server tools into the registry. |
— |
bobzhang/openseek/prompt |
Built-in system prompt text (generated from Markdown) and prompt-selection policy. | prompt/README.mbt.md |
bobzhang/openseek_protocol |
Typed engine event stream (own module): the openseek run/serve stdout wire contract, decodable on every backend. |
protocol/README.mbt.md |
bobzhang/openseek_protocol/emit |
Native-only writer for that stream: owns each event's log level. | protocol/emit/README.mbt.md |
bobzhang/openseek/agent |
Native-only OpenSeek agent loop and local tool dispatch. | agent/README.mbt.md |
bobzhang/openseek/agent_review |
Read-only, compiler-grounded code-review engine behind openseek review. |
agent_review/README.mbt.md |
bobzhang/openseek/cmd/openseek |
Native-only command-line entry point. | cmd/openseek/README.md |
bobzhang/openseek/cmd/tui |
Native-only terminal UI library, the default mode of openseek (and openseek tui). |
cmd/tui/README.md |
bobzhang/openseek/tui |
Reusable terminal-UI framework (transcript, composer, rendering) the OpenSeek TUI builds on. | tui/README.md |
bobzhang/openseek/viz |
Browser viewer for durable session logs (JS). | viz/README.md |
bobzhang/inspect (in inspect/, own module) |
HTTP server (native or wasm) that serves the visualizer over recorded sessions. | inspect/README.md |
bobzhang/openseek-viz-app (in cmd/viz_app/, own module) |
JS entry point compiled into the visualizer bundle. | viz/README.md |
moonbitlang/editor (in editor/, own module) |
Reusable readonly editor plus its reference browser shell and server. | editor/README.md |
bobzhang/openseek/internal/{cli,workspace_path} |
Shared CLI accessors and workspace-path resolution for the command mains. | — |
bobzhang/openseek/testkit/filesystem |
JSON-backed virtual filesystem for tests and eval fixtures. | testkit/filesystem/README.mbt.md |
bobzhang/openseek/eval/report |
Shared Markdown/JSON report primitive for deterministic and model evals. | eval/report/README.mbt.md |
bobzhang/openseek/eval/tool_harness |
Deterministic host-side harness that dispatches every built-in tool. | eval/tool_harness/README.mbt.md |
bobzhang/openseek/eval/file_edit/cases |
Deterministic file-editing eval case definitions. | eval/file_edit/README.md |
bobzhang/openseek/eval/file_edit/harness |
Reusable file-editing eval runner, oracle, and reporter. | eval/file_edit/README.md |
bobzhang/openseek/eval/file_edit/cmd/main |
Native-only CLI wrapper for the file-editing eval harness. | eval/file_edit/README.md |
bobzhang/openseek/eval/prompt_task/harness |
Prompt-task eval: runs the real agent over isolated per-trial workspaces. | eval/prompt_task/README.md |
bobzhang/openseek/eval/session_analyzer |
Post-hoc session-log analyzer producing Markdown/HTML/JSON reports. | — |
openseek_desktop (in desktop/, own module) |
Desktop app: CEF shell (lepus submodule) plus a JS frontend driving the engine over JSONL. | desktop/README.md |
The deepseek subpackage is pure and exposes chat data plus JSON helpers:
ModelandRoleChatMessage(role, content=...)with strongly typedRolevaluesToolDefinition(name, description, parameters, strict?)for native tool callsChatResponsewithFromJsonresponse decoding
It has no HTTP dependency and is suitable for blackbox tests and portable request/response handling.
The deepseek/client subpackage exposes the HTTP client:
Client(api_key~, model?, api_url?)Client::chat(messages, tools?)
It depends on moonbitlang/async/http and is native-only.
The agent_tool package exposes the local tool registry and typed executor
boundary. Tool executors return ToolAction: normal tools use
Respond(ToolOutput(...)), while control tools such as finish use
Control(Finish(...)).
The agent_runtime package owns loop-scoped task-group access and an extensible
event queue available to stateful tools.
The agent_session package owns typed durable conversation state, append-only
session events, JSON round-tripping, and projection from a session into
DeepSeek chat messages. It is separate from TUI transcript rendering so
resumable sessions can be type-safe and process-independent. The native
agent_session/store package persists those sessions as a small header plus an
append-only JSONL event log.
The agent subpackage contains the OpenSeek agent loop, native DeepSeek
tool-call handling, and local tool dispatch. It depends on deepseek/client,
filesystem, and process APIs.
The cmd/openseek package is the single-binary entry point — a subcommand tree
(default: the terminal UI; run/serve/review/sessions for the headless
engine; mcp to validate MCP configuration). openseek run parses arguments
and runs the agent package. The agent sends DeepSeek native function tools and
supports twelve local tools: shell (with shell_output and shell_stop for
background jobs — on Windows the plain foreground shell only), read, edit,
multi_edit, write, remove, plan, goal, run_moonbit, and finish.
export DEEPSEEK=sk-...
moon run cmd/openseek -- run "inspect this project and finish with a short summary"For Kimi models, set KIMI instead:
export KIMI=sk-...
moon run cmd/openseek -- --model kimi-k2.7-code-highspeed run "inspect this project"OPENSEEK_MODEL is optional and defaults to deepseek-v4-pro.
OPENSEEK_MAX_STEPS is optional; when omitted, turns are bounded by the
model's context window (a checkpoint summary carries each turn into the
next) rather than a step count. Pass --max-steps to cap steps for one run. --thinking no|high|max controls DeepSeek
thinking mode and effort (default: max).
Pass --dir <workspace> or set OPENSEEK_DIR to run one-shot commands against
another workspace while still launching from the current shell. The default is
.; if the final directory component is missing and its parent exists,
OpenSeek creates it and logs workspace_created.
OpenSeek can use tools from MCP servers.
Point --mcp-config (or OPENSEEK_MCP_CONFIG) at a JSON file in the de-facto
standard shape — an existing Claude/Cursor-style mcp.json works as-is:
{
"mcpServers": {
"codex": { "command": "codex", "args": ["mcp-server"] },
"remote": { "url": "https://example.com/mcp", "headers": { "Authorization": "Bearer …" } }
}
}A command entry is launched as a stdio subprocess (in the agent's workspace,
inheriting the environment plus any env overrides); a url entry speaks the
Streamable HTTP transport. Each server's tools join the agent's registry as
mcp__<server>__<tool> for run, serve, and the TUI (which forwards
OPENSEEK_MCP_CONFIG to its engine). A server that fails to start, handshake,
or list its tools is logged and skipped — MCP never breaks a session. Tool
results are size-capped, calls are bounded by a timeout, and tool names are
sanitized to the provider's function-name rules.
Validate a configuration without starting a session:
moon run cmd/openseek -- mcp --mcp-config mcp.jsonResources and prompts (the other MCP capabilities) are not consumed: openseek's agent is tool-driven, and a server that wants to feed it context can expose a tool. This keeps the surface small; revisit if a concrete need appears.
Reusable markdown playbooks the agent loads on demand. A skill is a
<name>.md file or a <name>/SKILL.md directory layout with optional
name:/description: frontmatter. Two libraries are merged: the global one
(~/.openseek/skills, or --global-skills-dir) and the workspace one
(.openseek/skills), with workspace skills shadowing same-named global ones.
The system prompt lists each skill's name, description, and file path; the
agent reads the file before applying it. See agent_skill/README.mbt.md.
The terminal UI is the default mode of the single openseek binary (the
cmd/tui library, also reachable as openseek tui): a scrolling transcript with
a live composer. It spawns the openseek engine (by default this same binary in
serve mode) and renders its JSONL event stream — streamed answer text appears
live on the activity line, and each turn's reasoning is kept as a dim ✻
transcript aside above its answer.
export DEEPSEEK=sk-...
moon run cmd/openseek -- tuiEvery launch converses in a durable session. The engine only carries
context between prompts through the session store, so the UI generates a session
id per launch (tui-YYYYMMDD-HHMMSS-mmm, named in the startup banner) and stores
the conversation under --session-root (default .openseek/). Follow-up prompts
remember earlier ones, and a conversation outlives the process:
moon run cmd/openseek -- tui --continueresumes the most recently active session.moon run cmd/openseek -- tui --session <id>resumes (or creates) a specific one.moon run cmd/openseek -- sessions listshows what is resumable — tab-separated id, last-activity time, and the session's first prompt, newest first.
See each package README for API boundaries, examples, and package-specific test notes.
The CLI behaviour is documented as executable cram tests under tests/, built
and run with moon cram test. The wrapper compiles the native cmd/* packages
and exposes each on PATH as <name>.exe (e.g. openseek.exe).
tests/cram/cli.md— offlineopenseeksubcommand examples (top-level andrunhelp, and therun/serve/sessionsbehaviors). They make no network calls and run in CI viamoon cram test tests/cram.tests/cram/tui.md— offlineopenseek tuiexamples (the help banner and the missing-API-key error). The argument parser runs before the terminal UI starts, so these need no API key and no TTY.tests/cram/subrun.md— the offline internal child-mode wire contract: JSON input on stdin, JSONL events on stdout, typed reports, and failure-event delivery. It uses the modellessechokind and needs no API key.tests/live/deepseek.md— a real, non-mock DeepSeek round trip. It is opt-in (DEEPSEEK=sk-... moon cram test tests/live) and parses the agent's JSONL log with MoonBit itself: amoon run -escript reads the stream through the publishedbobzhang/jsonlpackage and asserts on typedJsonvalues — nojq— without pinning nondeterministic content such as token counts or model phrasing.
For the evaluation-backed roadmap, see
agent-improvement-guide.md. It explains why the
next highest-ROI work is semantic CLI validation, native CLI/error-handling
guidance, MoonBit command routing, shaped IDE output, and manifest/debug/edit
guardrails.
The file-editing eval harness is available under eval/file_edit. It runs the
real agent against isolated fixtures and checks exact final file state, making
it suitable for cheap Flash baselines such as 8 successful edits out of 10.
The deterministic tool harness under eval/tool_harness exercises each built-in
tool through agent_tool.execute_tool_call with temporary fixtures. It is meant
for ordinary moon test coverage of tool wiring and observable side effects,
not for model quality scoring.
The testkit/filesystem package provides reusable JSON-backed text fixtures for
mock tests and evals. It materializes flat path-to-content JSON objects under a
temporary root and compares listed files against disk.