#OpenSeek CLI

    This package is the deprecated compatibility entry point for OpenSeek. Use moonx moonbitlang/openseek or moon run . from the repository root. The old coordinate remains supported and prints one warning to stderr.

    The openseek binary is a subcommand tree for the headless engine (the interactive terminal UI is the separate openseek_tui binary, in openseek_tui/). It parses arguments with moonbitlang/core/argparse, reads defaults from environment variables, and drives turns through moonbitlang/openseek/agent.run_turn_in_scope (both one-shot run and durable sessions).

    Both executable packages call the same application entry point and share process-level error handling. Command parsing, handlers, and shared setup live under internal/openseek.

    openseek run [options] TASK run one task headlessly; answer on stdout, progress on stderr openseek serve JSONL command server (stdin: prompt/steer/cancel/compact) openseek mcp list configured MCP servers and their tools openseek sessions list|show <id>|compact <id> … manage durable sessions

    The whole CLI is one moonbitlang/core/argparse command tree: run/serve/mcp/sessions are subcommands (argparse owns parsing, --help, and rejecting unknown or missing subcommands). There is no free-form top-level prompt and no default action — a bare openseek is rejected; launch the UI with openseek_tui. The options shared with the engine (--api-key, --model, …) sit on the root as globals; the UI's own options (--prompt, --engine, --continue) live on the openseek_tui binary, along with the prompt-file flags it forwards to serve.

    #openseek run

    moon run . -- run [--api-key sk-...] [--model deepseek-flash] [--api-url https://api.deepseek.com/chat/completions] [--dir .] [--max-steps N] [--system-prompt-file prompt.md] [--system-prompt-addendum-file addendum.md] [--session session-id] [--session-root .openseek] "task text"

    Runs require --api-key or the provider-specific environment variable: DEEPSEEK for DeepSeek models, KIMI for Kimi models, and GLM for Z.AI GLM models. --model can also be supplied with OPENSEEK_MODEL; it accepts deepseek-flash, the retired deepseek-v4-flash alias, deepseek-v4-pro, kimi-k2.7-code, kimi-k2.7-code-highspeed, glm-5.3, and glm-5.3-flash, and defaults to deepseek-flash. --max-steps can also be supplied with OPENSEEK_MAX_STEPS; when omitted, turns are bounded by the model's context window instead of a step count. --api-url can also be supplied with OPENSEEK_API_URL; when omitted, OpenSeek uses the official endpoint for the model's provider. The run exits non-zero unless its turn completes: running out of steps, stopping at the model's context window, an agent abort, and a failure each end with error: run did not complete: … on stderr, after the last JSONL event. --dir defaults to . and becomes the workspace root for relative prompt files, sessions, workspace skills, and agent tools. If the directory itself is missing but its parent exists, OpenSeek creates that final component and logs a workspace_created event. Missing parents are rejected, so --dir a/b/c creates only c when a/b already exists. --system-prompt-file and --system-prompt-addendum-file can also be supplied with OPENSEEK_SYSTEM_PROMPT_FILE and OPENSEEK_SYSTEM_PROMPT_ADDENDUM_FILE. --session explicitly creates or resumes that session under --session-root (default .openseek). Relative session roots are resolved under --dir. --review-deadline bounds one automatic --review-gate audit to that many milliseconds; the default is 900000 (15 minutes). Model-initiated reviews run the bundled @builtin/review.mbtx workflow through mbtx, auditing the live standing goal (handed over by the engine) and/or the criteria in args; its child has the hosted default deadline of 600000 (10 minutes), independent of this flag. See the hosted review notes. Hosted delegation requires a durable session; --no-session cannot delegate. A read-only code review of REF...HEAD runs as the review preset, with the report as the result file's output:

    printf '{"version":1,"input":{"base":"origin/main"}}' | openseek run --kind review --input-format json --result-file review.json

    Every run records a durable session: without --session, a generated cli-YYYYMMDD-HHMMSS-mmm id is used and announced on a session line on stderr, so the conversation is reviewable afterwards with openseek sessionslist / openseek sessions show <id> (or the viz server) and resumable with --session <id>. Pass --no-session to run ephemerally; combining it with --session is rejected.

    Without an explicit prompt file, the CLI uses the built-in prompt (prompt/default_prompt.mbt.md) for every supported DeepSeek, Kimi, and GLM model name.

    #openseek sessions

    The session-management subcommands are offline and do not require --api-key:

    moon run . -- sessions list --session-root .openseek moon run . -- sessions list --format=json --session-root .openseek moon run . -- sessions show parser-fix --session-root .openseek moon run . -- sessions compact parser-fix --file summary.txt --from 1 --to 120 moon run . -- sessions fork parser-fix --as parser-fix-retry

    sessions list --format=json is the machine-readable form of the listing, consumed by clients such as the desktop app's sidebar: one JSON array of {id, title, updated_at_ms} objects, most recently active first. title is the first line of the session's first user prompt; updated_at_ms is null for a directory whose session files cannot be stat-ed (such husks sort last, like the human-readable listing).

    sessions compact <id> --file <f> --from <n> --to <n> appends a typed summary event. It does not delete raw events from the session file; agent_session.Session::chat_messages uses the summary to compact model context on replay.

    sessions fork <id> [--as <new-id>] [--through <n>] copies a session into a new one and prints the new id, so the conversation can be continued another way with --session <new-id> while the original stays as it is. The copy carries every finished turn and whatever was recorded between turns since; a turn still in flight is left out, so forking a session that is running is safe. Sub-run sessions are not copied, and the fork does not record which session it came from: a viewer's link from a copied review result to its sr-N transcript is dead in the fork, and leads to the fork's own sr-N once it has run one. --through <n> stops at the turn whose terminal event has sequence n (sessions show lists the sequences). Without --as the new session gets a generated cli-… id; an id that already exists is refused.

    The fork's system prompt is not the source's: it is the prompt a new session started by this command line would get — from --dir, --model, --system-prompt-file, --system-prompt-addendum-file, and --global-skills-dir, with the fork's own scratch directory. A session does not record which of these it was created with, so pass the ones the source was started with, and the ones the fork will be resumed with. The fork's first request does not reuse the source's cached prefix past the point where the two prompts differ.

    The copied history ends with a [session forked] runtime notice, which the model reads before the fork's first prompt: the files were not copied with the history, so earlier tool results may not describe what is in --dir now. A caller that knows more about the fork's environment — the desktop app, which makes a new git worktree for a fork and knows what the source left uncommitted — passes it with --notice <text>, which the notice carries after its standard part as given.

    #openseek serve

    In serve mode, controllers can ask the engine to generate and append a summary without using a temporary file:

    {"command":"compact"}

    The engine handles this in command order, waits for any active turn to finish, generates the summary with the configured model endpoint, appends a Summary event covering the current session, and emits compaction_started, compaction_finished, or compaction_failed JSONL events. With --session, the summary is persisted to the durable session log. With --no-session, it only updates the live in-memory session for the current serve process.

    serve is what the terminal UI spawns for each session; it is also the stable protocol for other integrations.

    #Examples

    export DEEPSEEK=sk-... moon run . -- run "run moon test and summarize the result"

    OPENSEEK_MODEL=deepseek-flash moon run . -- run "inspect the package docs"

    moon run . -- run --max-steps 200 "write tests, fix failures, and summarize"

    moon run . -- run --dir ../another-workspace "run moon test"

    moon run . -- run --session parser-fix "continue from the last run"

    run performs one run. For best-of-N, run the same task in separate checkouts of the workspace from a script, then compare how each ended:

    for i in 1 2 3; do git -C myproject worktree add --detach "$PWD/attempt_$i" moon run . -- run --dir "attempt_$i" "fix the failing test" \ > "answer_$i.md" 2> "progress_$i.log" & done wait

    Each attempt gets its own worktree, index and HEAD. A plain cp -R of a checkout that is itself a linked worktree keeps its .git pointer, so the copies would share the original's index and interfere with each other.

    share/examples/best-of-n.mbtx is the same as a MoonBit script (moon run best-of-n.mbtx): it creates the worktrees, runs the attempts concurrently, and reports which ones completed, from run's exit status.

    #Package Boundary

    This package should stay minimal: main.mbt hands control to internal/openseek and turns a failure into an exit status. Subcommand dispatch, argument parsing, environment-backed defaults, model parsing, prompt override file loading, session-store setup, and the command handlers live under internal/openseek, which documents its own package layout. The interactive UI is the separate openseek_tui binary (openseek_tui/), its own module in this workspace; the prompt package owns built-in prompt selection; the agent package owns tool definitions and the execution loop.

    This package has no tests of its own; the CLI's tests live with the packages that own the behavior:

    moon test internal/openseek/options internal/openseek/setup internal/openseek/execution internal/openseek/run internal/openseek/serve internal/openseek/commands --target native

    Source Files