Doramagic Project Pack Β· Human Manual
sanook-cli
πͺ A terminal AI coding agent β BYOK, 12 providers, MCP, and a second-brain that gives the AI durable cross-session memory. Built from scratch in TypeScript.
Overview & Quickstart
Related topics: Agent Loop, Memory & Second Brain, Gateway, Dashboard, TUI & Deployment
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Agent Loop, Memory & Second Brain, Gateway, Dashboard, TUI & Deployment
Overview & Quickstart
What is sanook-cli
sanook-cli is a terminal-based AI coding agent distributed as a single npm package. The description field in package.json:3 characterises it as "A terminal AI coding agent β BYOK, 9 providers, MCP, cron gateway, skills, and git awareness. Built from scratch in TypeScript." Version 0.5.7 ships two CLI entry points, sanook and sanookai, both pointing at the compiled binary dist/bin.js (Source: package.json:8-11).
The package targets Node.js 22 or later and is licensed under Apache-2.0 (Source: package.json:23-31). The terminal UI is rendered with Ink and React 19, while language-model requests flow through the Vercel AI SDK (ai: ~6.0), giving the project pluggable support for multiple model providers (Source: package.json:33-47).
Installation
The only currently-ready installation method is npm, confirmed by the dashboard helper test that asserts npm is ready: true and recommended: true (Source: src/dashboard/api-helpers.test.ts:6-12) and by the install table that lists it first (Source: src/dashboard/api-helpers.ts:14-26):
npm install -g sanook-cli
# or run without installing
npx sanook-cli
Curl, Homebrew, and winget entries exist in the same helper module but are marked ready: false with infrastructure notes, since they require hosted install scripts (Source: src/dashboard/api-helpers.ts:27-43, src/dashboard/api-helpers.test.ts:14-22). The build pipeline defined in scripts.build recompiles TypeScript, copies dashboard static assets, and sets the binary executable bit before publishing (Source: package.json:12-22).
First Run & Provider Setup
On first run sanook-cli inspects the environment for usable provider keys. The hasUsableEnvKey helper checks each provider's envVar, validates the value with assertDirectApiKey to reject OAuth or subscription tokens, and skips the setup wizard when a valid key is already present (Source: src/providers/registry.ts:148-165). Supported cloud providers include Anthropic, OpenAI, Google, xAI, Mistral, and Groq, each declared as a ProviderConfig entry in the PROVIDERS table (Source: src/providers/registry.ts:55-110). Local providers such as Ollama do not require an API key.
Model selection accepts three spec forms: a global alias like gpt, a provider alias like anthropic:haiku, or a raw provider:model-id string. The parseSpec function normalises all of them, canonicalSpec produces the provider:model-id form that the REPL stores as state, and fastSibling returns the cheaper sibling of a model for mechanical tasks such as summarisation (Source: src/providers/registry.ts:111-145).
The setup wizard can also fetch live model lists per provider through listRemoteModels, which issues an authenticated GET /models request with a 6 s timeout and falls back to curated aliases on failure. The companion mergeModelOptions function de-duplicates alias and remote entries so the picker never shows two options pointing at the same model id (Source: src/providers/models.ts).
Architecture at a Glance
flowchart LR
User[Terminal User] --> CLI[sanook REPL]
CLI -->|events| Loop[runAgent loop]
Loop -->|spec| Registry[Provider Registry]
Registry -->|BYOK keys| SDK[Vercel AI SDK]
SDK --> Anthropic
SDK --> OpenAI
SDK --> Google
SDK --> xAI
SDK --> Mistral
SDK --> Groq
SDK --> Ollama
CLI -->|optional| Dash[Local Web Dashboard]
Dash -->|SSE| Terminal[src/dashboard/terminal.ts]
Loop --> Brain[second-brain vault]The REPL sits at the centre: it streams text, reasoning, and tool events back to the terminal, persists multi-turn history server-side per browser session, and emits remembered facts or auto-created skills during the loop (Source: src/dashboard/terminal.ts:1-15). The local dashboard reuses the same runAgent entry point over Server-Sent Events, so web and terminal sessions share identical agent behaviour (Source: src/dashboard/terminal.ts:5-12).
A second major surface is the Obsidian-style "second brain" vault scaffolded by the CLI. The vault README describes a folder layout with Projects/, Sessions/, Shared/, Goals/, Areas/, Research/, Skills/, and Playbooks/ directories, plus constitution files (CLAUDE.md, GEMINI.md, AGENTS.md, SANOOK.md) that govern how the agent writes to the vault. Shared/AI-Context-Index.md is loaded before any vault work, and every folder exposes an _Index.md that defines its AI routing contract (Source: second-brain/README.md).
Verifying the Install
A few quick smoke tests confirm a healthy install. Running sanook --help should print the REPL banner; launching the agent without a key triggers the setup wizard rather than a raw error. The unit test for resolveEmbedder shows that the provider layer returns null when no embedding credential is present and degrades to null instead of accepting an OAuth-style key β the same defensive policy that protects the live REPL (Source: src/providers/registry.test.ts:13-33).
See Also
- Providers & Models
- Dashboard & Web Terminal
- Second-Brain Vault
- Skills & Cron Gateway
Source: https://github.com/Sir-chawakorn/sanook-cli / Human Manual
Agent Loop, Memory & Second Brain
Related topics: Overview & Quickstart, Providers, MCP, Tools & Skills
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview & Quickstart, Providers, MCP, Tools & Skills
Agent Loop, Memory & Second Brain
Sanook CLI is a terminal AI coding agent built in TypeScript with BYOK (Bring Your Own Key) support, nine provider integrations, MCP, cron, skills, and git awareness. This page documents the agent loop, in-process conversation memory, and the Obsidian-backed second brain vault that gives the agent persistent memory across sessions.
Source: package.json β project metadata, bin: sanook, Node >=22.
Agent Loop
The core loop is exposed as runAgent and imported into the web dashboard. Each call receives a prompt, prior history, and a streaming onEvent callback that emits AgentEvent records.
Source: src/dashboard/terminal.ts β import { runAgent, type AgentEvent } from '../loop.js'.
Key parameters observed at the call site:
| Parameter | Value / Range | Purpose |
|---|---|---|
maxSteps | 20 | Hard cap on tool-calling turns per request |
permissionMode | 'auto' or 'ask' | Whether tools run without prompting |
signal | AbortSignal | Cancellation for client disconnects |
usageMeta | { sessionId, source: 'repl' } | Tags telemetry for cost tracking |
onEvent | (e: AgentEvent) => void | Streams events to REPL or SSE |
Source: src/dashboard/terminal.ts β runAgent({ model, prompt, history, maxSteps: 20, permissionMode, signal, usageMeta, onEvent }).
AgentEvent is a discriminated union. The dashboard's SSE bridge maps each variant:
text/reasoningβ streamed model output chunkstool-callβ human title viadescribeToolCall(tool, detail)plus optionaldifftool-resultβ tool-finished notificationstatusβ ephemeral progress texterrorβ redacted message (secrets stripped viaredactKey)
Source: src/dashboard/terminal.ts β onEvent switch and describeToolCall import.
Provider selection flows through resolveModel(spec), which parses provider:model specs, validates direct API keys (OAuth/subscription tokens are rejected by assertDirectApiKey), and constructs a LanguageModel via the per-provider factory. Aliases like gpt, sonnet, or groq:fast are normalized via canonicalSpec and fastSibling.
Source: src/providers/registry.ts β resolveModel, canonicalSpec, fastSibling, hasUsableEnvKey.
A kind: 'delegate' variant exists for providers that run as a subprocess rather than through the Vercel AI SDK. The Codex integration spawns the codex CLI, parses JSONL output for thread.started, item.completed (agent_message), and turn.completed events, and streams them back through the same AgentEvent shape.
Source: src/providers/codex.ts β spawn('codex', args, β¦) and JSONL parsing.
In-Process Conversation Memory
For the web dashboard, multi-turn history is held server-side, scoped by a browser session id. The store is an in-memory Map<string, ModelMessage[]> capped at 20 simultaneous sessions.
const HISTORY = new Map<string, ModelMessage[]>(); // sessionId β conversation
const MAX_HISTORY_SESSIONS = 20;
Source: src/dashboard/terminal.ts β history store.
Each turn calls runAgent with the accumulated history plus the new prompt. Because the loop returns messages and the store is in-process, conversation context survives across page reloads until the server restarts or the session is evicted.
π§ remember & β¨ Auto-Created Skills
Two side channels are captured from the tool-call stream:
remembertool calls contribute a stringfactthat is pushed into a per-requestrememberedFactsbuffer and surfaced to the dashboard.- Other tool calls are summarized via
describeToolCall(tool, detail), producing atitleand optionaldiff.
Source: src/dashboard/terminal.ts β case 'tool-call' branch.
These captures are short-lived. For persistence across sessions, the agent writes to the second brain vault.
The Second Brain (Obsidian Vault)
sanook brain scaffolds an Obsidian vault that acts as long-term, cross-session memory. The structure separates concerns into dedicated folders:
| Folder | Role |
|---|---|
Projects/ | One folder per real project |
Sessions/ | Flat, date-stamped AI work logs |
Shared/ | Central memory, rules, decisions, state |
Intake/, Runbooks/, Templates/, Bugs/, Handoffs/ | Core workflow surfaces |
Goals/, Areas/ | North-star + ongoing domains |
Research/, Learning/, Distillations/ | Knowledge pipeline |
Skills/, Playbooks/, Evals/, Entities/ | Frontier loops (self-improving) |
Source: second-brain/README.md β folder table.
The AI routing contract is enforced by per-folder _Index.md files. Before creating or relocating a note, an AI agent must:
- Read
Shared/AI-Context-Index.mdfirst. - Choose the destination from
Vault Structure Map.md. - Open that folder's
_Index.mdand follow its routing rules.
Source: second-brain/README.md β usage section.
The constitution (behavioral rules for the AI) lives in CLAUDE.md, GEMINI.md, AGENTS.md, and SANOOK.md. User identity and preferences are stored in USER.md and Shared/User-Memory/user-preferences.md.
Data Flow
sequenceDiagram
participant U as User
participant UI as REPL / Dashboard
participant L as runAgent
participant P as Provider
participant B as Second Brain
U->>UI: prompt + history
UI->>L: invoke (maxSteps=20)
loop until done or cap
L->>P: stream chat completion
P-->>L: text / reasoning / tool-call
L-->>UI: AgentEvent via onEvent
L->>B: remember facts / auto-create skills
end
L-->>UI: final messages
UI->>U: rendered responseFailure Modes & Limits
- Dead SSE socket:
sseSendchecksres.destroyed || res.writableEndedbefore writing; closed sockets are skipped silently. Source: src/dashboard/terminal.ts. - OAuth / subscription keys:
assertDirectApiKeyrejects tokens likesk-ant-oatβ¦orya29.β¦so a "ready" status never reports for unusable credentials. Source: src/providers/registry.ts βhasUsableEnvKey. - History eviction: When the 20-session cap is reached, the oldest entry in the
HISTORYmap is effectively dropped on the next overwrite (Map insertion order is preserved). - Embedder auto-detect: If no embedding-capable provider key is present in env,
resolveEmbedder()returnsnullrather than failing the run. Source: src/providers/registry.test.ts βauto-detect returns null when no embedding provider key is present. - Remote model listing:
/v1/modelsfetches require a usable API key and base URL; on failure, only locally-registered aliases appear in the model picker. Source: src/providers/models.ts βfetchRemoteModels. - Install prerequisites: The dashboard advertises
npm install -g sanook-cliornpx sanook-cliand notes Node.js β₯ 22. Source: src/dashboard/api-helpers.ts βdashboardInstall.
See Also
- Providers & Model Resolution (registry, key policy, aliases)
- Dashboard / Web Terminal (SSE streaming, optional PTY shell)
- Skills & Auto-Creation (β¨ skill synthesis pipeline)
- Obsidian Vault Conventions (
Vault Structure Map.md)
Source: https://github.com/Sir-chawakorn/sanook-cli / Human Manual
Providers, MCP, Tools & Skills
Related topics: Agent Loop, Memory & Second Brain, Gateway, Dashboard, TUI & Deployment
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Agent Loop, Memory & Second Brain, Gateway, Dashboard, TUI & Deployment
Providers, MCP, Tools & Skills
Overview
The sanook-cli project is a terminal-based AI coding agent designed around four interconnected capability layers: Providers (model backends), MCP (Model Context Protocol servers), Tools (agent-callable functions), and Skills (reusable behavior packs). Together, these layers allow the agent to communicate with multiple LLM vendors, expose external capabilities through a standardized protocol, execute local actions, and persist self-improving knowledge across sessions.
The package exposes two binaries β sanook and sanookai β both pointing to the same entrypoint, and is published under the Apache-2.0 license with Node.js β₯ 22 as the runtime. Source: package.json:1-40.
Provider System
Architecture
The provider system is implemented as a single registry table, PROVIDERS, where each entry declares its SDK factory, environment variable, key policy, and model alias map. Adding a new vendor requires only adding one record β no changes to the agent loop, pricing, or key-resolution code. Source: src/providers/registry.ts:30-60.
flowchart LR REPL[REPL / Dashboard] -->|spec string| Parser[parseSpec] Parser -->|provider:model| Registry[PROVIDERS table] Registry -->|factory call| SDK[Vercel AI SDK] SDK -->|HTTPS| Cloud[(Cloud LLM API)] Registry -.->|optional| Local[(Ollama / LMStudio)] Registry -.->|delegate| CodexCLI[Codex CLI subprocess] Keys[resolveKeyFromEnv] --> Registry Keys -->|OAuth reject| Blocked[hasUsableEnvKey β false]
Supported Providers
The package ships SDK adapters for seven providers plus a delegate to the Codex CLI. Source: package.json:33-42.
| Provider | Label | Env Variable | Notes |
|---|---|---|---|
anthropic | Anthropic (Claude) | ANTHROPIC_API_KEY | Direct API key; OAuth reuse rejected |
google | Google (Gemini) | GOOGLE_API_KEY | Direct API key; OAuth reuse rejected |
openai | OpenAI | OPENAI_API_KEY | Bearer key; ChatGPT/Codex OAuth banned |
xai | xAI Grok | XAI_API_KEY | Format /^xai-[A-Za-z0-9]{16,}$/ |
mistral | Mistral | MISTRAL_API_KEY | Free-format key |
groq | Groq | GROQ_API_KEY | Format /^gsk_[A-Za-z0-9]{20,}$/ |
openai-compatible | OpenAI-compatible | varies | Custom baseURL |
ollama | Ollama (local) | β | No key required |
lmstudio | LMStudio (local) | β | No key required |
codex | Codex CLI (delegate) | β | Spawns subprocess agent |
Source: src/providers/registry.ts:60-180.
Spec Resolution
Model references use a provider:model syntax. parseSpec accepts three forms: provider:model, provider:alias, or a bare global alias (e.g., sonnet). Aliases resolve through each provider's models map, while bare model IDs default to anthropic. The canonicalSpec function normalizes aliases to provider:full-id before reaching REPL state. Source: src/providers/registry.ts:120-145.
The fastSibling() function returns a provider's cheaper tier for cost-sensitive tasks (e.g., summarization). It inspects a priority chain of aliases: fast β flash β haiku β air, returning the original spec if no fast tier exists. Source: src/providers/registry.ts:15-25.
Key Policy
hasUsableEnvKey() is the authoritative gate for whether a provider is ready. It rejects OAuth-prefixed keys and tokens failing the declared regex format, ensuring the first-run wizard is not bypassed when an unusable key is present. Source: src/providers/registry.ts:100-115.
Remote Model Discovery
The listRemoteModels() function queries each provider's /models endpoint and returns the canonical model IDs the user actually owns, rather than relying on a static curated list. It handles three response shapes: Google's ?key= query with models[].name, Anthropic's x-api-key header form, and the OpenAI-compatible Bearer form with data[].id. On failure, timeout, or for local/delegate providers, it returns [] so callers fall back to the curated alias map. Source: src/providers/models.ts:10-60.
The mergeModelOptions() function combines remote-discovered IDs with the curated alias map, grouping aliases by their resolved model ID. This prevents duplicate Select entries when one model ID is exposed under multiple aliases (e.g., haiku and fast pointing to the same underlying model). Source: src/providers/models.ts:70-100.
MCP, Tools & Dashboard Integration
The dashboard exposes a web terminal backend that streams the agent loop over Server-Sent Events at POST /api/terminal/run, reusing runAgent and forwarding text, reasoning, tool-call events, remembered facts, and auto-created skills exactly like the REPL. Multi-turn conversation history is maintained server-side, keyed by browser session ID, with a maximum of 20 concurrent sessions (localhost, single-user). Source: src/dashboard/terminal.ts:10-25.
A raw shell endpoint at /api/terminal/shell upgrades to a real PTY when both node-pty and ws are installed (listed as optionalDependencies in package.json); otherwise the UI degrades gracefully. The shellStatus() helper reports availability and reason for the absence. Source: src/dashboard/api-helpers.test.ts:20-28.
Tool activity is rendered through describeToolCall(), which produces human-readable summaries shown alongside streamed events. Source: src/dashboard/terminal.ts:5-10.
Skills & Second Brain
The second-brain vault scaffolded by sanook brain provides persistent storage for agent knowledge across sessions. It defines folders for Skills/, Playbooks/, Evals/, and Entities/, collectively described as "frontier loops (self-improving)" β meaning the agent can write, refine, and re-evaluate its own behavior artifacts. Source: second-brain/README.md:10-15.
The vault routing contract requires AI agents to read Shared/AI-Context-Index.md before any task, and to consult the target folder's _Index.md before creating or moving notes. This enforces consistent placement across Projects/, Sessions/, Goals/, Areas/, Research/, Learning/, and Distillations/ folders. Source: second-brain/README.md:20-25.
Constitution files (CLAUDE.md, GEMINI.md, AGENTS.md, SANOOK.md) define AI conduct rules, while USER.md and Shared/User-Memory/user-preferences.md hold personalization. Source: second-brain/README.md:25-28.
Common Failure Modes
- OAuth key rejection: Setting
ANTHROPIC_API_KEY=sk-ant-oatβ¦causeshasUsableEnvKey()to returnfalse, forcing the wizard to run instead of marking the provider ready. Source: src/providers/registry.ts:100-115. - Stale model IDs: Providers retire models (e.g.,
grok-4retired 2026-05-15); the registry redirects aliases to current IDs but users can always override with the explicitprovider:full-idform. Source: src/providers/registry.ts:80-95. - PTY unavailable: When
node-ptyis not installed (e.g., in CI), the shell endpoint reports a reason matching/node-pty|ws/, and the dashboard UI degrades. Source: src/dashboard/api-helpers.test.ts:20-28. - Duplicate model entries: Without
mergeModelOptions()grouping aliases by resolved ID, the model picker shows duplicate entries or misses models whose only alias isdefault. Source: src/providers/models.ts:70-100.
See Also
- Project Architecture Overview
- Configuration & Environment
- Dashboard & Web Terminal
- Second Brain Vault Guide
Source: https://github.com/Sir-chawakorn/sanook-cli / Human Manual
Gateway, Dashboard, TUI & Deployment
Related topics: Overview & Quickstart, Providers, MCP, Tools & Skills
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview & Quickstart, Providers, MCP, Tools & Skills
Gateway, Dashboard, TUI & Deployment
Overview and Purpose
Sanook CLI exposes the same agent loop through three coordinated surfaces: a long-running Gateway for HTTP/SSE and scheduled jobs, a browser-based Dashboard for interactive control, and an in-terminal TUI for keyboard-driven REPL use. All three are built and shipped through a single TypeScript pipeline that produces a dist/ bundle ready for npm distribution.
The agent core is reused everywhere: the dashboard's /api/terminal/run route streams runAgent over Server-Sent Events, forwarding text, reasoning, and tool events (including the π§ remember facts and β¨ auto-created skills) just like the REPL. Source: src/dashboard/terminal.ts:1-15
Multi-turn history is kept server-side, keyed by browser session id, which keeps the dashboard a localhost single-user surface simple. Source: src/dashboard/terminal.ts:10-13
Dashboard (Web UI)
The dashboard is a Node HTTP server that ships with the CLI. It bundles two distinct surfaces that share the same agent backend.
Agent Console (SSE)
The agent console accepts a POST body, runs the agent via runAgent from ../loop.js, and streams events as data: <json>\n\n SSE frames. The handler guards against dead sockets: if the response is already destroyed or ended, it returns silently to avoid writing to a closed connection. Source: src/dashboard/terminal.ts:17-25
Body parsing is intentionally minimal β a buffered JSON reader used by the request body β and the handler enforces a bounded history per session to protect memory on long-running localhost instances. Source: src/dashboard/terminal.ts:27-33
Raw Shell (WebSocket + PTY, Optional)
The raw shell feature upgrades ws://β¦/api/terminal/shell to a real PTY session when both node-pty and ws are installed. Both are declared as optionalDependencies in package.json:65-68, so the dashboard degrades gracefully when they are absent. The helper shellStatus() reports availability and a reason string (e.g. node-pty/ws not installed) that the UI surfaces to the user. Source: src/dashboard/api-helpers.test.ts:20-25
Install Helper API
The dashboard exposes installation metadata for first-time users via dashboardInstall(). It returns an array of install methods, each tagged ready: boolean and an optional note explaining infrastructure dependencies. The npm method is ready: true and recommended: true; curl, homebrew, and winget entries are returned with ready: false and a note describing the missing infrastructure (hosted install scripts, formula, manifest). Source: src/dashboard/api-helpers.ts:1-35 and verified by src/dashboard/api-helpers.test.ts:9-18.
The install commands are templated around the NPM_PKG constant (sanook-cli) and a placeholder INSTALL_DOMAIN (sanook.ai) that the project should swap in once the install-script infrastructure is hosted. Source: src/dashboard/api-helpers.ts:11-34
Terminal User Interface (TUI)
The TUI runs in the user's terminal and is the canonical keyboard-driven surface. It is built on Ink (React 19 renderer for CLIs) and the @inkjs/ui component library, which together provide the box-drawing, text input, and select primitives used by the REPL. Source: package.json:43-47
Cosmetic components come from ink-big-text (the brand banner) and ink-gradient, layered on top of the Ink renderer. Source: package.json:44-46
The TUI is started in development through tsx src/bin.ts and, after build, by the compiled entry dist/bin.js, which is shipped as the npm bin for both sanook and sanookai commands. Source: package.json:6-10, 18-19
The dashboard static assets are copied into dist/ by scripts/copy-dashboard-static.mjs as part of the build, then dist/bin.js is marked executable (0o755). Source: package.json:19-19
Provider Backbone and Sub-Agent Delegation
The gateway, dashboard, and TUI all call into the same provider registry. The PROVIDERS table is the single point of truth for which models are addressable, their env-var names, key formats, and factories. ToS-sensitive providers (Anthropic, Google) explicitly reject OAuth/subscription tokens via assertDirectApiKey so that the same code path is safe across surfaces. Source: src/providers/registry.ts:60-82
For models whose identities change frequently, the registry exposes a remote listing endpoint via listRemoteModels, which calls each provider's GET /models, handles the three shape variants (Google ?key= with models[].name, Anthropic x-api-key header, OpenAI-compatible Bearer with data[].id), and falls back to a curated alias list on failure, timeout, or for local providers. Source: src/providers/models.ts:7-19
A separate kind: 'delegate' entry exists for the OpenAI Codex CLI, which is reached by spawning codex exec and parsing JSONL events. This lets Sanook forward coding work to a subprocess agent while reusing the same runAgent boundary for SDK-backed providers. Source: src/providers/registry.ts:36-42 and src/providers/codex.ts:1-15
Deployment
Deployment is driven by the npm scripts block. A clean build runs in order: wipe dist/, run tsc -p tsconfig.build.json, copy dashboard static assets, and chmod the bin. A prepublish gate (prepublishOnly: npm run build) ensures the published tarball always contains a fresh dist/. Source: package.json:18-22
The published package ships dist/, skills/, second-brain/, the postinstall script, the README, the changelog, the license, and .env.example. The postinstall hook (scripts/postinstall.mjs) runs after install to perform first-run scaffolding such as writing a default config or seeding the second-brain vault. Source: package.json:11-17, 23-25
The runtime contract is strict: engines.node: ">=22" is enforced to keep modern node:fs, node:http, and the AI SDK runtime available. Source: package.json:26-28
flowchart LR
User[Operator] --> TUI["TUI (Ink + @inkjs/ui)"]
User --> Dashboard["Dashboard (browser)"]
Cron[Scheduler / Cron gateway] --> Gateway["Gateway (HTTP + SSE)"]
TUI --> Loop["runAgent (loop.js)"]
Dashboard -->|POST /api/terminal/run| Loop
Gateway --> Loop
Loop --> Registry["Provider Registry"]
Registry --> SDK["AI SDK providers"]
Registry --> Delegate["codex exec subprocess"]
Dashboard -. optional .-> PTY["Raw shell (node-pty + ws)"]Operational Notes and Failure Modes
- Optional deps absent. If
node-ptyorwsare not installed, the dashboard's raw shell section reportsavailable: falsewith a reason string; the agent console still works because it uses only Node's built-inhttp. Source: src/dashboard/api-helpers.test.ts:20-25 - Dead SSE clients. The SSE writer early-exits when the response is destroyed or ended, preventing
ERR_STREAM_DESTROYEDfrom a tab being closed mid-stream. Source: src/dashboard/terminal.ts:18-25 - OAuth/subscription keys rejected. The provider policy refuses Anthropic/Google OAuth tokens even when the env var is set, so the wizard cannot be silently skipped on a token that will not work. Source: src/providers/registry.ts:90-105
- Local providers. Ollama and LM Studio use
requiresKey: falseand a placeholder key, andlistRemoteModelsshort-circuits for local providers by returning[]and letting the curated alias list win. Source: src/providers/registry.ts:48-60 and src/providers/models.ts:11-12 - First-run UX. The dashboard install helper advertises
npmas the recommended path; alternative channels (curl, homebrew, winget) are listed for discoverability but flaggedready: falseuntil their infrastructure is published. Source: src/dashboard/api-helpers.ts:16-35
See Also
- Provider registry and key policy: src/providers/registry.ts
- Remote model listing: src/providers/models.ts
- Codex CLI sub-agent integration: src/providers/codex.ts
- Dashboard terminal backend: src/dashboard/terminal.ts
- Dashboard install helpers: src/dashboard/api-helpers.ts
- Project manifest and scripts: package.json
Source: https://github.com/Sir-chawakorn/sanook-cli / Human Manual
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
Doramagic Pitfall Log
Found 7 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Configuration risk - Configuration risk requires verification.
1. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.host_targets | https://github.com/Sir-chawakorn/sanook-cli
2. Capability evidence risk: Capability evidence risk requires verification
- Severity: medium
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.assumptions | https://github.com/Sir-chawakorn/sanook-cli
3. Maintenance risk: Maintenance risk requires verification
- Severity: medium
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://github.com/Sir-chawakorn/sanook-cli
4. Security or permission risk: Security or permission risk requires verification
- Severity: medium
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: downstream_validation.risk_items | https://github.com/Sir-chawakorn/sanook-cli
5. Security or permission risk: Security or permission risk requires verification
- Severity: medium
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: risks.scoring_risks | https://github.com/Sir-chawakorn/sanook-cli
6. Maintenance risk: Maintenance risk requires verification
- Severity: low
- Finding: issue_or_pr_quality=unknownγ
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://github.com/Sir-chawakorn/sanook-cli
7. Maintenance risk: Maintenance risk requires verification
- Severity: low
- Finding: release_recency=unknownγ
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://github.com/Sir-chawakorn/sanook-cli
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using sanook-cli with real data or production workflows.
- v0.5.7 - github / github_release
- Configuration risk requires verification - GitHub / issue
Source: Project Pack community evidence and pitfall evidence