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

Section Related Pages

Continue reading this section for the full explanation and source context.

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

Section Related Pages

Continue reading this section for the full explanation and source context.

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:

ParameterValue / RangePurpose
maxSteps20Hard cap on tool-calling turns per request
permissionMode'auto' or 'ask'Whether tools run without prompting
signalAbortSignalCancellation for client disconnects
usageMeta{ sessionId, source: 'repl' }Tags telemetry for cost tracking
onEvent(e: AgentEvent) => voidStreams 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 chunks
  • tool-call β†’ human title via describeToolCall(tool, detail) plus optional diff
  • tool-result β†’ tool-finished notification
  • status β†’ ephemeral progress text
  • error β†’ redacted message (secrets stripped via redactKey)

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:

  • remember tool calls contribute a string fact that is pushed into a per-request rememberedFacts buffer and surfaced to the dashboard.
  • Other tool calls are summarized via describeToolCall(tool, detail), producing a title and optional diff.

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:

FolderRole
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:

  1. Read Shared/AI-Context-Index.md first.
  2. Choose the destination from Vault Structure Map.md.
  3. Open that folder's _Index.md and 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 response

Failure Modes & Limits

  • Dead SSE socket: sseSend checks res.destroyed || res.writableEnded before writing; closed sockets are skipped silently. Source: src/dashboard/terminal.ts.
  • OAuth / subscription keys: assertDirectApiKey rejects tokens like sk-ant-oat… or ya29.… 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 HISTORY map 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() returns null rather 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/models fetches 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-cli or npx sanook-cli and 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

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Architecture

Continue reading this section for the full explanation and source context.

Section Supported Providers

Continue reading this section for the full explanation and source context.

Section Spec Resolution

Continue reading this section for the full explanation and source context.

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.

ProviderLabelEnv VariableNotes
anthropicAnthropic (Claude)ANTHROPIC_API_KEYDirect API key; OAuth reuse rejected
googleGoogle (Gemini)GOOGLE_API_KEYDirect API key; OAuth reuse rejected
openaiOpenAIOPENAI_API_KEYBearer key; ChatGPT/Codex OAuth banned
xaixAI GrokXAI_API_KEYFormat /^xai-[A-Za-z0-9]{16,}$/
mistralMistralMISTRAL_API_KEYFree-format key
groqGroqGROQ_API_KEYFormat /^gsk_[A-Za-z0-9]{20,}$/
openai-compatibleOpenAI-compatiblevariesCustom baseURL
ollamaOllama (local)β€”No key required
lmstudioLMStudio (local)β€”No key required
codexCodex 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… causes hasUsableEnvKey() to return false, 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-4 retired 2026-05-15); the registry redirects aliases to current IDs but users can always override with the explicit provider:full-id form. Source: src/providers/registry.ts:80-95.
  • PTY unavailable: When node-pty is 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 is default. Source: src/providers/models.ts:70-100.

See Also

Source: https://github.com/Sir-chawakorn/sanook-cli / Human Manual

Gateway, Dashboard, TUI & Deployment

Related topics: Overview & Quickstart, Providers, MCP, Tools & Skills

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Agent Console (SSE)

Continue reading this section for the full explanation and source context.

Section Raw Shell (WebSocket + PTY, Optional)

Continue reading this section for the full explanation and source context.

Section Install Helper API

Continue reading this section for the full explanation and source context.

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-pty or ws are not installed, the dashboard's raw shell section reports available: false with a reason string; the agent console still works because it uses only Node's built-in http. 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_DESTROYED from 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: false and a placeholder key, and listRemoteModels short-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 npm as the recommended path; alternative channels (curl, homebrew, winget) are listed for discoverability but flagged ready: false until their infrastructure is published. Source: src/dashboard/api-helpers.ts:16-35

See Also

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.

medium Configuration risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Capability evidence risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Maintenance risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Security or permission risk requires verification

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.

Sources 2

Count of project-level external discussion links exposed on this manual page.

Use Review before install

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.

Source: Project Pack community evidence and pitfall evidence