# clrun — The Interactive CLI for AI Agents > Persistent. Deterministic. Project-Scoped Execution. > No more --yes flags or command retries. clrun gives AI agents full control over interactive terminal sessions — TUI prompts, select lists, checkboxes, confirms, long-running processes — with structured YAML responses, contextual hints, and auto-suspend/restore. - GitHub: https://github.com/cybertheory/clrun - npm: https://www.npmjs.com/package/clrun - Website: https://clrun.dev ## Installation ``` npm install -g clrun ``` Or use without installing: ``` npx clrun ``` --- # Core Skill Reference ## Overview `clrun` is a project-scoped, persistent, deterministic CLI execution substrate designed for AI coding agents. It provides interactive PTY sessions with queued input, priority control, keystroke navigation, and crash recovery. All responses are **structured YAML** with contextual `hints` that tell you exactly what to do next. Every error includes recovery steps. Every success includes the full set of valid next actions. ## Commands ### Run a Command (bare shorthand) ``` clrun clrun run "" ``` Creates a new interactive PTY session. Returns YAML with `terminal_id`. The session starts in the **current working directory**. **Examples:** ``` clrun npm init clrun "npx create-vue@latest" clrun run "docker compose up" ``` ### Send Text Input ``` clrun "" clrun input "" [--priority ] [--override] ``` Sends text to a running session followed by Enter. Use the bare shorthand (`clrun "text"`) for quick input, or `clrun input` for priority/override. - **--priority **: Higher number = higher priority (default: 0) - **--override**: Cancel all pending inputs, send this immediately **Examples:** ``` clrun abc123 "my-project-name" clrun abc123 "yes" clrun input abc123 "force-reset" --override ``` ### Send Keystrokes (for TUI navigation) ``` clrun key [...] ``` Sends named keystrokes to navigate TUI prompts — select lists, multi-select checkboxes, confirm dialogs, and more. Keys are sent as raw escape sequences **without** a trailing Enter (unless you include `enter` explicitly). **Available keys:** `up`, `down`, `left`, `right`, `enter`, `tab`, `escape`, `space`, `backspace`, `delete`, `home`, `end`, `pageup`, `pagedown`, `ctrl-c`, `ctrl-d`, `ctrl-z`, `ctrl-l`, `ctrl-a`, `ctrl-e`, `y`, `n` **Examples:** ``` clrun key abc123 down down enter # Navigate a select list → pick 3rd item clrun key abc123 space down space enter # Toggle 1st + 2nd checkbox, confirm clrun key abc123 enter # Accept the default / confirm clrun key abc123 ctrl-c # Interrupt/cancel the running process ``` ### View Output ``` clrun tail [--lines ] # Last N lines (default: 50) clrun head [--lines ] # First N lines (default: 50) clrun # Shorthand for tail ``` ### Check Status ``` clrun status ``` Returns YAML with all terminal sessions, states, and queue depths. ### Kill a Session ``` clrun kill ``` Terminates a running PTY session. --- # Interacting with TUI Prompts Modern CLI tools use rich TUI frameworks (@clack/prompts, inquirer, etc.) that render interactive widgets. Here's how to handle each type: ## Text Input Prompts ``` ◆ Project name: │ default-value ``` **Action:** Send text — it replaces the default and presses Enter automatically. ``` clrun "my-project" ``` To **accept the default**, send an empty Enter: ``` clrun key enter ``` ## Single-Select Lists ``` ◆ Select a framework: │ ● Vanilla ← currently highlighted │ ○ Vue │ ○ React │ ○ Svelte ``` **Action:** Use `down`/`up` to move the highlight, then `enter` to select. ``` clrun key down down enter # Selects "React" (3rd item) ``` To **accept the default** (first item): ``` clrun key enter ``` ## Multi-Select (Checkbox) Lists ``` ◆ Select features: (space to select, enter to confirm) │ ◻ TypeScript ← cursor here │ ◻ Router │ ◻ Linter │ ◻ Prettier ``` **Action:** Use `space` to toggle each checkbox, `down`/`up` to move, then `enter` to confirm. ``` # Select TypeScript (1st), skip Router, select Linter (3rd), confirm: clrun key space down down space enter ``` To **skip all** (select none): ``` clrun key enter ``` ## Yes/No Confirm Prompts ``` ◆ Use TypeScript? │ ● Yes / ○ No ``` **Action:** `enter` accepts the highlighted default. Use `left`/`right` or `down`/`up` to switch between Yes/No first if needed. ``` clrun key enter # Accept default (Yes) clrun key right enter # Switch to No, then confirm ``` ## Readline-Style Prompts (simple text) ``` package name: (my-project) ``` **Action:** Send text directly — these are basic line-buffered prompts. ``` clrun "my-custom-name" # Type and press Enter clrun "" # Accept the default (just Enter) ``` ## Prompt Identification Table | You see | Type | Action | |---------|------|--------| | `◆ Name: │ default` | Text input | `clrun "value"` or `clrun key enter` | | `● Opt1 ○ Opt2 ○ Opt3` | Single-select | `clrun key down... enter` | | `◻ Opt1 ◻ Opt2 ◻ Opt3` | Multi-select | `clrun key space down... enter` | | `● Yes / ○ No` | Confirm | `clrun key enter` or `right enter` | | `(y/n)` | Simple confirm | `clrun "y"` or `clrun "n"` | | `name: (default)` | Readline | `clrun "value"` or `clrun ""` | ## Counting Items in Select Lists - The **first item** is always highlighted by default (●) - Each `down` moves one position - To select the Nth item: send N-1 `down` presses, then `enter` --- # Real-World Interactive Workflows ## Scaffolding a Vue App (create-vue) ``` clrun "npx create-vue@latest" # → Project name prompt clrun "my-vue-app" # → Feature multi-select (TypeScript, Router, Pinia, Linter, etc.) clrun key space down down space down space down down down space down down enter # → Experimental features multi-select clrun key enter # Skip all # → Blank project confirm clrun key enter # Accept default (No) # → Scaffolding done! Install deps: clrun "cd my-vue-app && npm install" clrun "npm run dev" ``` ## Scaffolding a React App (create-vite) ``` clrun "npx create-vite@latest" # → Project name prompt clrun "my-react-app" # → Framework select list (Vanilla, Vue, React, ...) clrun key down down enter # Select React # → Variant select list (TypeScript, JS, SWC, ...) clrun key enter # Accept default (TypeScript) # → Install confirm clrun key enter # Yes ``` ## Running npm init ``` clrun "npm init" # → package name: clrun "my-package" # → version: clrun "" # Accept default (1.0.0) # → description: clrun "A cool project" # → entry point: clrun "" # Accept default # Continue for each prompt... ``` ## Monitoring a Dev Server ``` clrun "npm run dev" # → Wait for server to start, then read output clrun tail --lines 20 # → Look for "ready" / URL in output # Session stays alive — the dev server keeps running clrun kill # Stop when done ``` ## Environment Variable Persistence ``` clrun "bash" clrun "export API_KEY=sk-12345" clrun "export NODE_ENV=development" clrun 'echo $API_KEY' # → Output: sk-12345 # Variables survive suspension too — sessions auto-restore on input ``` --- # Session Lifecycle ## Session States | State | Meaning | |-------|---------| | `running` | PTY is active and accepting input | | `suspended` | Idle timeout — env saved, PTY shut down, auto-restores on input | | `exited` | Command completed (check `last_exit_code`) | | `killed` | Session was manually terminated | | `detached` | Session lost due to crash (not recoverable) | ## Suspended Sessions (Auto-Restore) Sessions automatically suspend after **5 minutes of inactivity**: - Environment variables and working directory are captured - Buffer logs are preserved (`clrun tail` still works) - **Sending any input auto-restores the session transparently** - The response includes `restored: true` ``` # Session suspended after idle timeout clrun tail # Still works — reads preserved buffer clrun echo $MY_VAR # Auto-restores, runs command, returns output ``` --- # Queue System Inputs are queued deterministically: 1. **Priority DESC** — higher number sends first 2. **FIFO** for equal priority 3. **Override** cancels all pending and sends immediately | Property | Behavior | |----------|----------| | Ordering | Priority DESC, then FIFO | | Default priority | 0 | | Override mode | Cancels all pending, sends immediately | | Processing interval | 200ms | --- # Agent-Native Response Design Every clrun response includes: - **`hints`** — the complete set of valid next actions as copy-pasteable commands - **`warnings`** — issues detected with your input or the output (e.g. likely shell-expanded variables, residual ANSI codes) - **Rich errors** — not just an error message, but the reason, alternatives, and exact recovery commands ## Example Error Response ```yaml error: "Session not found: abc123..." hints: list_sessions: clrun status start_new: clrun active_sessions: f5e6d7c8-... note: Found 1 active session(s). ``` ## Example Warning ```yaml input: "" warnings: - "Input is empty. If you intended to send a shell variable like $MY_VAR, use single quotes: clrun 'echo $MY_VAR'" ``` --- # Shell Variable Quoting When sending commands containing `$` variables, use **single quotes** to prevent your shell from expanding them before clrun receives them: ``` clrun 'echo $MY_VAR' # Correct — variable reaches the session clrun "echo $MY_VAR" # Wrong — your shell expands it first ``` --- # Best Practices for AI Agents 1. **Use bare shorthand** — `clrun ` to start, `clrun "text"` to interact 2. **Use `clrun key` for TUI navigation** — arrow keys, space to toggle, enter to confirm 3. **Read the `hints`** — every response tells you exactly what to do next 4. **Read the `warnings`** — they catch quoting errors, empty inputs, and output artifacts 5. **Use single quotes for `$` variables** — `clrun 'echo $MY_VAR'` prevents shell expansion 6. **Parse YAML** — all responses are structured YAML, never plain text 7. **Poll with `tail`** to observe progress and detect prompts 8. **Use `key enter` to accept defaults** — don't send empty text for TUI prompts 9. **Use `key space` to toggle checkboxes** in multi-select lists 10. **Use priority** when queuing multiple inputs 11. **Use override** for emergency abort / flow change 12. **Just send input to suspended sessions** — they auto-restore, no pre-check needed --- # State Files All state lives in `.clrun/` within the project root: ``` .clrun/ sessions/.json # Session metadata queues/.json # Input queue buffers/.log # Raw PTY output ledger/events.log # Event audit trail skills/ # Skill definitions clrun-skill.md # Core skill claude-code-skill.md openclaw-skill.md clrun/SKILL.md # Agent Skills format (agentskills.io) clrun/references/ # Reference docs ``` --- # Agent-Specific Integration Skills ## Claude Code Integration This skill teaches Claude Code how to use `clrun` for interactive command execution. Use `clrun` whenever you need to run commands that require interactive input, TUI navigation, long-running processes, or deterministic execution control. ### When to Use clrun - **Interactive scaffolders** — create-vue, create-vite, create-astro, npm init - **TUI tools** with select lists, checkboxes, and confirm dialogs - **Long-running processes** — dev servers, test suites, docker builds - **Stateful sessions** — setting env vars, then querying them later - **Any command that prompts** for user input ### Lifecycle Pattern (Claude Code) ``` 1. START → clrun → get terminal_id 2. OBSERVE → clrun tail → read output, identify prompt 3. INTERACT → clrun "text" / clrun key → send input 4. REPEAT → go to 2 until done 5. VERIFY → clrun status → check exit codes 6. CLEANUP → clrun kill → if needed ``` ### Important Rules (Claude Code) 1. **Parse YAML** — all responses are structured YAML 2. **Read the hints** — they tell you exactly what to do next 3. **Use `key` for TUI prompts** — never type escape sequences as text 4. **Use text input for readline prompts** — `clrun "text"` 5. **Single-quote `$` variables** — prevents premature shell expansion 6. **Accept defaults with `key enter`** — not with empty text for TUI prompts 7. **Count items from top** for select lists — N-1 `down` presses for item N --- ## OpenClaw Integration This skill provides OpenClaw agents with the knowledge to use `clrun` for interactive, persistent command execution within coding projects. ### Agent Workflow Pattern (OpenClaw) ``` 1. EXECUTE → result = shell("clrun ") 2. PARSE → terminal_id = yaml_parse(result).terminal_id 3. OBSERVE → output = shell("clrun tail " + id + " --lines 30") 4. IDENTIFY → what type of prompt is showing? (text/select/multi/confirm) 5. INTERACT → shell("clrun 'text'") or shell("clrun key down enter") 6. REPEAT → go to 3 until the task is complete 7. VERIFY → status = shell("clrun status") 8. CLEANUP → shell("clrun kill " + id) ``` ### Key Rules for OpenClaw Agents 1. **Use `clrun key` for TUI prompts** — select lists, checkboxes, confirms 2. **Use `clrun "text"` for text prompts** — readline and text fields 3. **Read the `hints`** in every response — they tell you exactly what to do next 4. **Read the `warnings`** — they catch quoting errors and output artifacts 5. **Single-quote `$` variables** — `clrun 'echo $MY_VAR'` 6. **Count items from top** for select lists — target position minus 1 = number of `down` presses 7. **Accept defaults with `key enter`** — not empty text for TUI prompts 8. **Parse YAML** — all responses are structured YAML, never plain text 9. **Store terminal_ids** — needed for all subsequent operations 10. **Just send input to suspended sessions** — they auto-restore, no pre-check needed