# CLI, Skills & Extension Points

> The orca CLI binary (src/cli/), built-in skill discovery and metadata (src/main/skills/, src/shared/skills.ts), the agent-hook relay for external automations, SSH remote-runtime support, and the operational surfaces developers use to extend or automate Orca (runtime environments, setup scripts, MCP config).

- Repository: stablyai/orca
- GitHub: https://github.com/stablyai/orca
- Human wiki: https://grok-wiki.com/public/wiki/stablyai-orca-47ffb1f68457
- Complete Markdown: https://grok-wiki.com/public/wiki/stablyai-orca-47ffb1f68457/llms-full.txt

## Source Files

- `src/cli/index.ts`
- `src/cli/dispatch.ts`
- `src/main/skills/discovery.ts`
- `src/shared/skills.ts`
- `src/shared/agent-hook-types.ts`
- `src/shared/mcp-config.ts`
- `src/shared/runtime-environments.ts`
- `src/shared/setup-script-imports.ts`
- `skills/orchestration/`

---

<details>
<summary>Relevant source files</summary>
The following files were used as context for generating this wiki page:

- [src/cli/index.ts](src/cli/index.ts)
- [src/cli/dispatch.ts](src/cli/dispatch.ts)
- [src/cli/runtime-client.ts](src/cli/runtime-client.ts)
- [src/cli/runtime/client.ts](src/cli/runtime/client.ts)
- [src/cli/handlers/agent-hooks.ts](src/cli/handlers/agent-hooks.ts)
- [src/cli/handlers/core.ts](src/cli/handlers/core.ts)
- [src/cli/handlers/environment.ts](src/cli/handlers/environment.ts)
- [src/cli/handlers/orchestration.ts](src/cli/handlers/orchestration.ts)
- [src/cli/specs/index.ts](src/cli/specs/index.ts)
- [src/cli/specs/core.ts](src/cli/specs/core.ts)
- [src/cli/specs/environment.ts](src/cli/specs/environment.ts)
- [src/cli/specs/agent-hooks.ts](src/cli/specs/agent-hooks.ts)
- [src/cli/specs/orchestration.ts](src/cli/specs/orchestration.ts)
- [src/main/skills/discovery.ts](src/main/skills/discovery.ts)
- [src/main/agent-hooks/managed-agent-hook-controls.ts](src/main/agent-hooks/managed-agent-hook-controls.ts)
- [src/main/agent-hooks/server.ts](src/main/agent-hooks/server.ts)
- [src/shared/skills.ts](src/shared/skills.ts)
- [src/shared/agent-hook-types.ts](src/shared/agent-hook-types.ts)
- [src/shared/mcp-config.ts](src/shared/mcp-config.ts)
- [src/shared/runtime-environments.ts](src/shared/runtime-environments.ts)
- [src/shared/setup-script-imports.ts](src/shared/setup-script-imports.ts)
- [src/shared/setup-script-import-providers.ts](src/shared/setup-script-import-providers.ts)
- [skills/orchestration/SKILL.md](skills/orchestration/SKILL.md)
</details>

# CLI, Skills & Extension Points

The Orca `orca` CLI binary exposes every runtime capability as a composable command surface — from launching the desktop app to managing worktrees, orchestrating multi-agent workflows, and toggling agent status hooks. It is the primary integration surface for automation scripts, AI coding agents (Claude Code, Codex, Gemini, etc.), and CI pipelines.

This page covers the structure and responsibilities of `src/cli/`, the skill discovery system (`src/main/skills/discovery.ts` + `src/shared/skills.ts`), the agent-hook relay that injects Orca state into external agents, SSH remote-runtime support, and the extension points developers use to wire Orca into custom workflows (MCP config detection, setup-script import, pairing environments).

---

## Architecture Overview

```text
┌─────────────────────────────────────────────────────────┐
│                    orca CLI binary                      │
│  src/cli/index.ts  →  dispatch.ts  →  handlers/        │
│                              │                          │
│  specs/          (command definitions + flag schemas)   │
│  runtime-client.ts  (local IPC or remote WebSocket)     │
└──────────────┬──────────────────────────────────────────┘
               │ RPC calls
       ┌───────▼────────────────────────┐
       │       Orca Runtime (main proc) │
       │  ┌────────────────────────┐    │
       │  │  skills/discovery.ts   │    │
       │  │  agent-hooks/server.ts │    │
       │  │  orchestration engine  │    │
       │  └────────────────────────┘    │
       └────────────────────────────────┘
               │ pairing / WebSocket
       ┌───────▼──────────────────────┐
       │    Remote Orca Runtime       │
       │  (SSH host, Tailscale, LAN)  │
       └──────────────────────────────┘
```

---

## CLI Entry Point and Dispatch

### `src/cli/index.ts` — Entry point

`main()` is the entry point for the installed binary. It:

1. Parses `argv` via `normalizeCommandPositionals` + `parseArgs`.
2. Resolves help paths and prints help when `--help` or an unknown path is given.
3. Validates command + flags against `COMMAND_SPECS` before performing any runtime lookup, so typos produce a useful error before "Orca is not running" is ever reported.
4. Constructs a `RuntimeClient` with the appropriate remote-pairing context.
5. Calls `dispatch(commandPath, ctx)`.

Three top-level command groups bypass remote-environment selection entirely: `environment`, `serve`, and `agent`. The `shouldIgnoreRemoteSelection` guard passes `null` explicitly for `pairingCode` and `environmentSelector` so the `RuntimeClient` constructor cannot re-activate the `ORCA_PAIRING_CODE` / `ORCA_ENVIRONMENT` env-var fallback for those local-only commands.

Sources: [src/cli/index.ts:18-73]()

### `src/cli/dispatch.ts` — Handler registry

`dispatch.ts` assembles a flat `Map<string, CommandHandler>` at module load time by iterating over every handler group in declaration order. It throws at startup on any duplicate key, preventing silent handler shadowing.

```typescript
// src/cli/dispatch.ts (simplified)
const groups = [
  CORE_HANDLERS, AUTOMATION_HANDLERS, REPO_HANDLERS,
  WORKTREE_HANDLERS, FILE_HANDLERS, TERMINAL_HANDLERS,
  BROWSER_NAV_HANDLERS, /* … browser variants … */
  ORCHESTRATION_HANDLERS, COMPUTER_HANDLERS,
  AGENT_HOOK_HANDLERS, ENVIRONMENT_HANDLERS
]
```

The `dispatch` function looks up the handler by the `commandPath` joined with spaces (`"orchestration send"`, `"agent hooks on"`, etc.) and calls it with a `HandlerContext` containing `{ flags, client, cwd, json }`.

Sources: [src/cli/dispatch.ts:1-63]()

### Command Specs

Every command is formally declared in `src/cli/specs/`. Each `CommandSpec` carries a `path` (the command words), `summary`, `usage` string, `allowedFlags`, optional `notes`, and `examples`. The merged array `COMMAND_SPECS` in `src/cli/specs/index.ts` is the single source of truth for help text, validation, and auto-completion.

Sources: [src/cli/specs/index.ts](), [src/cli/specs/core.ts]()

---

## Command Surface Reference

### Core Commands

| Command | Description |
|---|---|
| `orca open` | Launch the Orca desktop app and wait until the runtime is reachable |
| `orca serve` | Start a headless runtime server (foreground); supports `--port`, `--pairing-address`, `--mobile-pairing`, `--no-pairing` |
| `orca status` | Report app/runtime/graph readiness; exits non-zero when runtime is unreachable |

### Repository & Worktree Commands

| Command | Description |
|---|---|
| `orca repo list / add / show / set-base-ref / search-refs` | Manage registered repositories |
| `orca worktree list / show / current / create / set / rm / ps` | Manage Git worktrees; `current` resolves `$PWD` to an Orca worktree selector |

### Terminal Commands

| Command | Description |
|---|---|
| `orca terminal list / show / read / send / wait` | Inspect and interact with live PTY sessions |
| `orca terminal create / split / close / stop / switch / focus / rename` | Lifecycle management |

`terminal wait --for tui-idle` detects the working→idle OSC title transition for recognized agent CLIs (Claude Code, Codex, Gemini, etc.), enabling race-free agent coordination without sleep loops.

### Orchestration Commands

Orchestration commands require the Orca runtime to be running and the experimental orchestration feature to be enabled.

| Command Group | Description |
|---|---|
| `orchestration send / check / reply / inbox` | SQLite-backed inter-agent message passing with group addressing (`@all`, `@idle`, `@claude`, `@codex`, etc.) |
| `orchestration task-create / task-list / task-update` | DAG task tracking; tasks auto-promote to `ready` when all deps complete |
| `orchestration dispatch / dispatch-show` | Assign a ready task to a terminal, optionally injecting a preamble |
| `orchestration ask` | Block until a named terminal replies with an answer; outputs bare JSON for `jq` piping |
| `orchestration gate-create / gate-resolve / gate-list` | Human-in-the-loop decision gates that block task dispatch |
| `orchestration run / run-stop` | Automated background coordinator loop |
| `orchestration reset` | Clear tasks, messages, or all orchestration state |

`orchestration check --wait` emits JSON heartbeat lines to stderr every 15 s (configurable via `ORCA_HEARTBEAT_INTERVAL_MS`) while polling, so the parent agent process never mistakes silence for a stall.

Sources: [src/cli/handlers/orchestration.ts:1-50](), [src/cli/specs/orchestration.ts:1-40](), [skills/orchestration/SKILL.md]()

---

## Remote Runtime and Environment Management

### `RuntimeClient` — Local vs Remote transport

`RuntimeClient` (src/cli/runtime/client.ts) transparently routes RPC calls either to the local Orca socket or to a remote Orca instance over an encrypted WebSocket.

Remote mode is activated by:
- `--pairing-code <orca://pair#...>` flag on any command
- `--environment <selector>` flag
- `ORCA_PAIRING_CODE` / `ORCA_REMOTE_PAIRING` environment variable
- `ORCA_ENVIRONMENT` environment variable

When remote, the client checks runtime protocol compatibility (`evaluateRuntimeCompat`) before the first non-`status.get` call, so stale CLI binaries talking to newer runtimes report actionable version errors.

Sources: [src/cli/runtime/client.ts:1-70]()

### Environment Commands

`environment add / list / show / rm` manage a persistent store of named remote environments (saved to `orca-data.json` in the user-data directory). Each environment holds one or more `RuntimeAccessEndpoint` records of kind `websocket`, each carrying an `endpoint` URL, `deviceToken`, and `publicKeyB64`.

```
orca environment add --name work-laptop --pairing-code orca://pair#...
orca environment list
orca environment rm --environment work-laptop
```

The `--environment` flag (or `ORCA_ENVIRONMENT`) on any ordinary command selects the environment by name or ID, routing that command to the remote runtime over WebSocket.

Sources: [src/shared/runtime-environments.ts:1-80](), [src/cli/handlers/environment.ts](), [src/cli/specs/environment.ts]()

### `orca serve` — Headless SSH Runtime

`orca serve` starts the Orca runtime server without opening a desktop window. The `--pairing-address` flag overrides the announced endpoint address so remote clients connecting via SSH port forward, Tailscale, or a public tunnel see the correct reachable address instead of `localhost`.

```bash
# On the remote host:
orca serve --pairing-address 100.64.1.20 --port 6768

# On the local machine:
orca environment add --name ssh-host --pairing-code <emitted code>
orca worktree list --environment ssh-host
```

Sources: [src/cli/specs/core.ts:12-31]()

---

## Agent-Hook Relay

### Purpose

The agent-hook relay injects Orca's view of agent state (idle/working/done) into external AI agents. Each supported agent tool has a managed hook service that installs a lightweight script into the agent's config directory; when the agent transitions state, it POSTs to Orca's loopback HTTP endpoint.

### Supported Agents

`AGENT_HOOK_TARGETS` in `src/shared/agent-hook-types.ts` enumerates the ten currently managed agents:

| Agent | Service file |
|---|---|
| `claude` | `src/main/claude/hook-service` |
| `codex` | `src/main/codex/hook-service` |
| `gemini` | `src/main/gemini/hook-service` |
| `cursor` | `src/main/cursor/hook-service` |
| `grok` | `src/main/grok/hook-service` |
| `copilot` | `src/main/copilot/hook-service` |
| `droid` | `src/main/droid/hook-service` |
| `command-code` | `src/main/command-code/hook-service` |
| `antigravity` | `src/main/antigravity/hook-service` |
| `hermes` | `src/main/hermes/hook-service` |

Sources: [src/shared/agent-hook-types.ts:5-15](), [src/main/agent-hooks/managed-agent-hook-controls.ts:1-60]()

### Protocol Version

`ORCA_HOOK_PROTOCOL_VERSION = '1'` is shared between the main-process server and each hook service. The server logs a warning when it receives a request from a different version, making stale installed scripts diagnosable rather than silently producing partial payloads.

Sources: [src/shared/agent-hook-types.ts:29-42]()

### CLI Commands

```bash
orca agent hooks status   # Show enabled state and per-agent install status
orca agent hooks on       # Enable hooks; applies to running runtime or writes to disk
orca agent hooks off      # Disable hooks and remove managed hook entries
```

The `on`/`off` commands first attempt to update the running runtime via RPC (`settings.update`). If the runtime is not reachable, they fall back to writing the setting directly into `orca-data.json` and re-applying hook install/remove locally. The `appliedBy` field in the output (`runtime` vs `offline`) reports which path was taken.

Sources: [src/cli/handlers/agent-hooks.ts:75-120](), [src/cli/specs/agent-hooks.ts]()

### Hook Server (`src/main/agent-hooks/server.ts`)

The main-process hook server runs a loopback HTTP listener protected by a bearer token. It:
- Parses incoming hook payloads with the shared `normalizeHookPayload` pipeline from `src/shared/agent-hook-listener.ts`.
- Writes endpoint files to disk so agents not using the HTTP path can read state via filesystem.
- Fans out `AgentStatusIpcPayload` to registered listeners (UI panes).
- Persists `last-status.json` atomically (write-then-rename) so the dashboard can replay retained rows on Orca restart.
- Exposes an `ingestRemote` entry point for relay-forwarded events arriving over SSH/WebSocket, bypassing HTTP.

Sources: [src/main/agent-hooks/server.ts:1-60]()

---

## Skill Discovery

### Type Model (`src/shared/skills.ts`)

Skills are file-system packages with a `SKILL.md` entry point. The shared type layer defines:

| Type | Purpose |
|---|---|
| `DiscoveredSkill` | A fully resolved skill package (id, name, description, providers, paths, install status, file count) |
| `SkillDiscoverySource` | A scan root with label, path, `sourceKind`, and a flag for whether it exists |
| `SkillDiscoveryResult` | The aggregate output of a scan: `skills[]`, `sources[]`, `scannedAt` |
| `SkillProvider` | `'codex' \| 'claude' \| 'agent-skills'` |
| `SkillSourceKind` | `'home' \| 'repo' \| 'bundled' \| 'plugin'` |

Sources: [src/shared/skills.ts]()

### Discovery Algorithm (`src/main/skills/discovery.ts`)

`discoverSkills({ repos, homeDir, cwd })` performs a parallel multi-root filesystem scan:

**Scan roots (built by `buildSkillDiscoverySources`):**

| Root ID | Path | `sourceKind` | Providers |
|---|---|---|---|
| `home-codex` | `~/.codex/skills` | `home` | `codex` |
| `home-agents` | `~/.agents/skills` | `home` | `agent-skills` |
| `home-claude` | `~/.claude/skills` | `home` | `claude` |
| `codex-plugin-cache` | `~/.codex/plugins/cache` | `plugin` | `codex`, `agent-skills` |
| `repo-agents-<hash>` | `<repoPath>/.agents/skills` | `repo` | `agent-skills` |
| `repo-claude-<hash>` | `<repoPath>/.claude/skills` | `repo` | `claude` |

Remote repos (with a `connectionId`) are excluded from scanning — only local paths are traversed.

`findSkillFiles` walks each root up to a depth of 4 (9 for `plugin` roots), following symlinks with realpath deduplication to prevent loops. Skills under `~/.agents/skills/.system/` are re-classified as `sourceKind: 'bundled'`. The scan is capped at `MAX_SKILL_FILES = 200` files per skill package and reads at most `MAX_MARKDOWN_BYTES = 256 KiB` of each `SKILL.md` for frontmatter extraction.

Each discovered skill is assigned a stable `id` — a 16-character SHA-1 hex digest of its file path — so the UI can refer to skills by a durable opaque key.

Sources: [src/main/skills/discovery.ts:1-230]()

### Orchestration Skill

`skills/orchestration/SKILL.md` is a bundled skill that teaches AI agents the full orchestration command surface: message groups (`@all`, `@idle`, `@claude`, etc.), the task DAG lifecycle, dispatch circuit-breaking, decision gates, and the coordinator loop pattern. It is available to any agent-skills-capable provider and documents `ORCA_TERMINAL_HANDLE` auto-resolution, the `--inject` preamble mechanism, and the heartbeat stderr protocol.

Sources: [skills/orchestration/SKILL.md]()

---

## MCP Config Detection

`src/shared/mcp-config.ts` provides a provider-neutral MCP server configuration inspector used both by the CLI and the UI. It recognises four candidate config file formats:

| Format | Relative path | Key |
|---|---|---|
| `workspace` | `.mcp.json` | `mcpServers` |
| `cursor` | `.cursor/mcp.json` | `mcpServers` |
| `claude` | `.claude.json` | `mcpServers` |
| `claude` (workspace) | `.claude/mcp.json` | `mcpServers` |

`inspectMcpConfigContent` parses whichever file exists, classifies each server entry as `stdio` (has `command`), `http` (has `url` or `type: 'http'`), or `unknown` (missing both), and marks entries `enabled` / `disabled` / `invalid`. Sensitive environment values are automatically masked by `maskMcpEnv` using a pattern that matches common secret key names and value shapes (`sk-`, `ghp_`, `xoxb-`, etc.), preventing accidental exposure in CLI output or logs.

Sources: [src/shared/mcp-config.ts:1-60](), [src/shared/mcp-config.ts:62-80]()

---

## Setup Script Import

`src/shared/setup-script-imports.ts` discovers existing dev-environment bootstrap configs in the current repository and converts them into a normalized `SetupScriptImportCandidate` for Orca's worktree setup hook.

**Supported import providers:**

| Provider | Config file(s) |
|---|---|
| `superset` | `.superset/config.json`, `.superset/config.local.json` |
| `conductor` | `conductor.json` |
| `codex` | Codex environment config |
| `cmux` | `.cmux/cmux.json` or `cmux.json` |

Each provider is inspected in parallel via `Promise.all`. For `cmux`, the inspector scans the `commands` array for an entry whose `name`, `title`, or `keywords` match setup-related terms (`setup`, `init`, `initialize`, `install`). Unsupported config fields are collected and surfaced as `unsupportedFields` warnings rather than hard failures, allowing partial imports.

Sources: [src/shared/setup-script-imports.ts:1-40](), [src/shared/setup-script-import-providers.ts]()

---

## Data Flow: CLI Invocation to RPC Call

```mermaid
sequenceDiagram
    participant Shell
    participant CLI as src/cli/index.ts
    participant Dispatch as dispatch.ts
    participant Handler as handlers/<group>.ts
    participant Client as RuntimeClient
    participant Runtime as Orca Runtime

    Shell->>CLI: orca <command> [flags]
    CLI->>CLI: parseArgs + validateCommandAndFlags
    CLI->>Client: new RuntimeClient(pairingCode, envSelector)
    CLI->>Dispatch: dispatch(commandPath, ctx)
    Dispatch->>Handler: handler(ctx)
    Handler->>Client: client.call('method', params)
    alt Local runtime
        Client->>Runtime: Unix socket / named pipe IPC
    else Remote runtime
        Client->>Runtime: WebSocket (encrypted, bearer-token auth)
    end
    Runtime-->>Client: RPC response
    Client-->>Handler: RuntimeRpcSuccess<TResult>
    Handler->>Shell: printResult (text or JSON)
```

Sources: [src/cli/index.ts:42-77](), [src/cli/runtime/client.ts:30-70]()

---

## Global Flags

All commands accept two universal flags:

| Flag | Effect |
|---|---|
| `--json` | Emit machine-readable JSON output instead of human-readable text |
| `--pairing-code <code>` | Override remote runtime connection for this invocation |
| `--environment <selector>` | Select a saved named environment for this invocation |

The `--json` flag is threaded through `HandlerContext` and passed to `printResult`, which chooses between a formatter function and `JSON.stringify` of the raw RPC success payload.

---

## Extension Points Summary

| Surface | How to use |
|---|---|
| **Custom MCP servers** | Add entries to `.mcp.json` / `.cursor/mcp.json` / `.claude.json`; Orca inspects them on repo load |
| **Agent skills** | Drop a directory containing `SKILL.md` under `~/.agents/skills/`, `~/.claude/skills/`, `~/.codex/skills/`, or `<repo>/.agents/skills/` |
| **Agent status hooks** | `orca agent hooks on` installs managed scripts; toggle with `orca agent hooks off` |
| **Remote automation** | `orca serve --pairing-address <host>` + `orca environment add` wires a remote runtime into any CLI invocation via `--environment` or `ORCA_ENVIRONMENT` |
| **Orchestration automation** | `orca orchestration *` commands are scriptable from any shell; `ORCA_TERMINAL_HANDLE` is injected into Orca-managed terminals automatically |
| **Setup script import** | Place `conductor.json`, `.superset/config.json`, `.cmux/cmux.json`, or a Codex environment config in the repo root; Orca imports the `setup` command into the worktree hook on first load |

The CLI is fully scriptable and JSON-output-capable on every command, making it suitable for use inside agent tool calls, CI pipelines, and external automation scripts without any proprietary SDK dependency.

Sources: [src/cli/dispatch.ts](), [src/main/skills/discovery.ts:175-220](), [src/shared/mcp-config.ts:39-55](), [src/shared/setup-script-import-providers.ts]()
