# CLI reference

> All `executor` subcommands and flags: `install`, `web`, `daemon`, `service`, `mcp`, `call`, `resume`, `tools`, `server`, `login`, and auto-start behavior.

- Repository: RhysSullivan/executor
- GitHub: https://github.com/RhysSullivan/executor
- Human docs: https://grok-wiki.com/public/docs/rhyssullivan-executor-564383868052
- Complete Markdown: https://grok-wiki.com/public/docs/rhyssullivan-executor-564383868052/llms-full.txt

## Source Files

- `apps/cli/src/main.ts`
- `apps/cli/bin/executor.ts`
- `apps/cli/src/daemon.ts`
- `apps/cli/src/daemon-state.ts`
- `apps/cli/src/service.ts`
- `apps/cli/src/server-profile.ts`
- `README.md`

---

---
title: "CLI reference"
description: "All `executor` subcommands and flags: `install`, `web`, `daemon`, `service`, `mcp`, `call`, `resume`, `tools`, `server`, `login`, and auto-start behavior."
---

The `executor` binary (`apps/cli/bin/executor.ts`) is the local entry point for installing a background service, opening the web UI, managing the daemon, invoking tools, resuming paused executions, exposing an MCP stdio server, and targeting hosted or local HTTP APIs. Commands are defined in `apps/cli/src/main.ts` using Effect CLI. Default local daemon port is **4788**; the OS-supervised service defaults to **4789**.

## Command overview

| Command | Purpose |
| --- | --- |
| `executor install` | Install and start the OS-supervised background service |
| `executor web` | Open the running web UI (or start a temporary foreground server) |
| `executor open` | Open the running web app in the browser with `?_token=` pre-filled |
| `executor daemon` | Run, stop, restart, or inspect the local daemon |
| `executor service` | Install, uninstall, restart, or inspect the OS-supervised service |
| `executor mcp` | Start an MCP server over stdio |
| `executor call` | Invoke a tool by dot-separated path segments |
| `executor resume` | Resume a paused execution (auth or approval) |
| `executor tools` | Search, list sources, or describe tools |
| `executor server` | Manage named server connection profiles |
| `executor login` | Sign in to a hosted server via OAuth device flow |
| `executor logout` | Clear stored credentials for a server profile |
| `executor whoami` | Show the authenticated account for a server |

## Global options

<ParamField body="-v" type="flag">
Print the CLI version and exit. Defined in `apps/cli/package.json` (currently `1.5.18`).
</ParamField>

<ParamField body="--log-level" type="string">
When set to `debug`, `trace`, or `all`, error output includes full stack traces. Otherwise errors are normalized to a short message with a hint to re-run with `--log-level debug`.
</ParamField>

## Shared server targeting flags

Several commands accept these flags to choose which Executor HTTP server to talk to:

<ParamField body="--base-url" type="string">
Executor server origin (for example `http://localhost:4788` or `https://cloud.example.com`). For local `http://` origins without stored credentials, the CLI may auto-start a daemon. Mutually exclusive with `--server`.
</ParamField>

<ParamField body="--server" type="string">
Named server profile from `~/.executor/server-connections.json`. Mutually exclusive with `--base-url`.
</ParamField>

<ParamField body="--scope" type="string">
Path to a workspace directory containing `executor.jsonc`. Sets `EXECUTOR_SCOPE_DIR` for the command.
</ParamField>

**Server resolution order** (when neither flag is passed):

1. Default server profile (if configured)
2. Active local server manifest (`~/.executor/server-control/server.json`)
3. Implicit default `http://localhost:4788`

Environment fallbacks for bearer auth when a profile has no stored credential:

- `EXECUTOR_API_KEY` (hosted API key)
- `EXECUTOR_AUTH_TOKEN` (local/desktop bearer token)

## `executor install`

Installs Executor as an OS-supervised background service. Alias of `executor service install`.

```bash
executor install [--port <port>]
```

<ParamField body="--port" type="integer" default="4789">
Loopback port the supervised daemon binds. Clients discover the live port from `server.json`.
</ParamField>

**Behavior:**

- Registers a service with the OS manager: **launchd** (macOS), **systemd --user** (Linux), or **Windows Task Scheduler** (Windows).
- Runs `<executor> daemon run --foreground --port <port> --hostname 127.0.0.1`.
- Waits up to 45 seconds for a reachable `cli-daemon` manifest at `http://127.0.0.1:<port>`.
- Idempotent: if the same version, port, and executable are already running, prints a noop message.
- **Requires the compiled binary** in production. In a dev checkout (`bun run src/main.ts`), fails with a message to use `executor daemon run --foreground` instead.

<RequestExample>

```bash
executor install
executor install --port 4789
```

</RequestExample>

<Check>
After install, open the UI with `executor web` or `executor open`.
</Check>

## `executor service`

Manages the same OS-supervised daemon as `install`, with explicit lifecycle commands.

| Subcommand | Description |
| --- | --- |
| `service install [--port <port>]` | Same as `executor install` |
| `service uninstall` | Stop and remove the OS service registration |
| `service status` | Show platform, registration, running state, serving origin, and version drift |
| `service restart` | Restart via the OS manager (`launchctl kickstart`, `systemctl --user restart`, or Task Scheduler) |

Service label: `sh.executor.daemon`. Logs: `~/.executor/logs/daemon.log` and `daemon.error.log`.

<Warning>
On Windows, `service install` may require an **Administrator** PowerShell because boot-triggered Scheduled Tasks need elevation.
</Warning>

## `executor web`

Opens the Executor web UI.

```bash
executor web [--foreground] [--port <port>] [--hostname <host>] [--allowed-host <origin>...] [--auth-token <token>] [--scope <dir>]
```

**Default (no `--foreground`):** reads the active local server manifest and opens the browser to `{origin}/?_token={bearer}`. If nothing is running, prints install instructions.

**With `--foreground`:** starts a temporary in-process server, publishes a `foreground` manifest, and blocks until Ctrl+C.

<ParamField body="--foreground" type="boolean" default="false">
Run a temporary web server in the current terminal instead of opening the installed background service.
</ParamField>

<ParamField body="--port" type="integer" default="4788">
Port for the `--foreground` server.
</ParamField>

<ParamField body="--hostname" type="string" default="127.0.0.1">
Bind address for `--foreground`. Use `0.0.0.0` to listen on all interfaces (only on trusted networks).
</ParamField>

<ParamField body="--allowed-host" type="string" repeatable>
Grant an extra CORS origin for `--foreground`. Localhost is always allowed; bearer token is the access gate.
</ParamField>

<ParamField body="--auth-token" type="string">
Override the bearer token for `--foreground`. Defaults to the stable token in `auth.json`.
</ParamField>

<RequestExample>

```bash
executor web
executor web --foreground
executor web --foreground --port 4788 --hostname 0.0.0.0
```

</RequestExample>

## `executor open`

Same browser-open behavior as `executor web` without `--foreground`: reads `server.json`, prints the URL, and opens `{origin}/?_token={token}`.

## `executor daemon`

Manages the local Executor HTTP daemon (distinct from the OS-supervised service, though both run `daemon run` under the hood).

| Subcommand | Description |
| --- | --- |
| `daemon run` | Start the daemon (background by default) |
| `daemon status [--base-url <url>]` | Show running state, PID, and scope |
| `daemon stop [--base-url <url>]` | SIGTERM the recorded PID and clean up state files |
| `daemon restart [--base-url <url>] [--scope <dir>]` | Stop then ensure the daemon is reachable again |

### `daemon run` flags

<ParamField body="--port" type="integer" default="4788">
Preferred listen port. If busy, an ephemeral port is chosen and reported on stderr.
</ParamField>

<ParamField body="--hostname" type="string" default="127.0.0.1">
Bind address. Keep local unless you trust the network.
</ParamField>

<ParamField body="--foreground" type="boolean" default="false">
Run in the current process (used by OS service managers). Without it, spawns a detached child.
</ParamField>

<ParamField body="--allowed-host" type="string" repeatable>
Extra CORS origins (repeatable).
</ParamField>

<ParamField body="--auth-token" type="string">
Override bearer token; defaults to `auth.json` under `EXECUTOR_DATA_DIR`.
</ParamField>

**State files** (under `EXECUTOR_DATA_DIR`, default `~/.executor`):

- `daemon-{host}-{port}.json` — PID record for a specific port
- `daemon-active-{host}-{scope-hash}.json` — scope-scoped pointer with token
- `server-control/server.json` — active server manifest with bearer token (mode `0600`)

<RequestExample>

```bash
executor daemon run
executor daemon run --foreground --port 4788
executor daemon status
executor daemon stop
executor daemon restart
```

</RequestExample>

## `executor mcp`

Starts an MCP server over stdio for Cursor, Claude Code, OpenCode, and other MCP clients.

```bash
executor mcp [--scope <dir>] [--elicitation-mode browser|model]
```

<ParamField body="--elicitation-mode" type="choice" default="model">
`browser`: approval pauses open `{baseUrl}/resume/{executionId}` in the browser. `model`: exposes a CLI resume tool to the model.
</ParamField>

**Behavior:**

- Acquires a local server startup lock, picks an available port (preferred 4788), and starts an in-process server.
- Reroutes stdout to stderr so JSON-RPC on stdout stays clean.
- Publishes a `foreground` manifest for the MCP session.
- Stops the server when the MCP session ends.

<Tip>
Example MCP client config: `"command": "executor", "args": ["mcp"]`. See [Connect MCP clients](/connect-mcp-clients).
</Tip>

## `executor call`

Invokes a tool by dot-separated path segments. The CLI compiles the path and trailing JSON args into TypeScript, executes it via the `/executions/execute` API, and prints the result.

```bash
executor call <segment> [<segment> ...] ['{"key":"value"}']
```

### Browse mode (`--help`)

```bash
executor call <path...> --help [--match "<text>"] [--limit <n>] [--base-url <url>] [--server <profile>] [--scope <dir>]
```

`--match` filters large namespaces; `--limit` caps listed subcommands.

<RequestExample>

```bash
executor call github issues create '{"owner":"octocat","repo":"Hello-World","title":"Hi"}'
executor call github --help
executor call cloudflare --help --match dns --limit 20
```

</RequestExample>

**Paused executions:** when a call pauses for auth or approval, the CLI prints the execution ID, a browser approval URL, and suggested `executor resume` commands.

## `executor resume`

Resumes a paused execution.

```bash
executor resume --execution-id <id> [--action accept|decline|cancel] [--content '<json>'] [--base-url <url>] [--server <profile>] [--scope <dir>]
```

<ParamField body="--execution-id" type="string" required>
Execution ID from a paused `call` or MCP elicitation.
</ParamField>

<ParamField body="--action" type="choice" default="accept">
`accept`, `decline`, or `cancel`.
</ParamField>

<ParamField body="--content" type="string">
JSON object payload when `--action accept` and the pause requested form input.
</ParamField>

<RequestExample>

```bash
executor resume --execution-id exec_abc123
executor resume --execution-id exec_abc123 --action accept --content '{"approved":true}'
executor resume --execution-id exec_abc123 --action decline
```

</RequestExample>

## `executor tools`

| Subcommand | Description |
| --- | --- |
| `tools search <query> [--namespace <ns>] [--limit <n>]` | Search tools by natural-language query (default limit 12) |
| `tools sources [--query <text>] [--limit <n>]` | List configured sources and tool counts (default limit 50) |
| `tools describe <path>` | Show a tool's TypeScript and JSON schema |

All `tools` subcommands accept `--base-url`, `--server`, and `--scope`, and auto-start a local daemon when needed.

<RequestExample>

```bash
executor tools search "send email"
executor tools sources
executor tools describe github.issues.list
```

</RequestExample>

## `executor server`

Manages named connection profiles in `~/.executor/server-connections.json`.

| Subcommand | Description |
| --- | --- |
| `server add <name> <origin> [--display-name <label>] [--kind http\|desktop-sidecar] [--default]` | Add or update a profile |
| `server list` | List profiles (`*` marks default) |
| `server use <name>` | Set the default profile |
| `server remove <name>` | Remove a profile |
| `server rotate-token` | Rotate the local server bearer token in `auth.json` |

Profile names: letters, numbers, dots, underscores, dashes (`^[A-Za-z0-9_.-]+$`).

Stored auth kinds: `basic`, `bearer`, `oauth` (from device login).

<RequestExample>

```bash
executor server add local http://localhost:4788 --default
executor server list
executor server use cloud
executor server rotate-token
```

</RequestExample>

## `executor login`

Signs in to a hosted Executor server using OAuth device flow (browser verification).

```bash
executor login [--base-url <origin>] [--server <profile>] [--name <profile-name>] [--no-browser]
```

<ParamField body="--base-url" type="string">
Hosted server origin. Mutually exclusive with `--server`.
</ParamField>

<ParamField body="--server" type="string">
Existing profile to re-authenticate.
</ParamField>

<ParamField body="--name" type="string">
Profile name to save under. Defaults to account email or user ID.
</ParamField>

<ParamField body="--no-browser" type="boolean" default="false">
Print the verification URL instead of opening a browser.
</ParamField>

On success, stores OAuth tokens in the profile and sets it as default. Tokens refresh automatically ~60 seconds before expiry.

### `executor logout` and `executor whoami`

```bash
executor logout [--base-url <origin>] [--server <profile>]
executor whoami [--base-url <origin>] [--server <profile>]
```

`logout` clears stored credentials for the resolved profile. `whoami` prints server origin, account email (from profile display name), user ID, organization, and token expiry.

## Auto-start behavior

Commands that talk to a local HTTP server without stored credentials may spawn a daemon automatically: **`call`**, **`resume`**, **`tools`**, and any command using default local targeting.

```mermaid
sequenceDiagram
  participant CLI as executor CLI
  participant Lock as daemon-active lock
  participant Daemon as daemon process
  participant Health as GET /api/health

  CLI->>Health: Probe target origin
  alt Already reachable
    Health-->>CLI: ok
    CLI->>CLI: Use active manifest bearer
  else Local host, no auth, not reachable
    CLI->>Lock: acquireDaemonStartLock
    CLI->>Daemon: spawnDetached daemon run --foreground
    loop up to 15s
      CLI->>Health: Probe
    end
    Lock-->>CLI: release lock
    CLI->>CLI: Read server.json bearer token
  end
```

### When auto-start runs

| Condition | Auto-start |
| --- | --- |
| `http://` origin on `localhost`, `127.0.0.1`, `::1`, or `[::1]` | Yes |
| Connection has stored or env auth (`oauth`, `bearer`, `basic`) | No — uses remote server directly |
| `https://` or non-local hostname | No — fails with manual start instructions |
| Another local server already owns the data directory | No — fails with conflict error |

### Port selection

1. Try the requested port (default **4788** from URL or implicit default).
2. If busy, pick an ephemeral port and print: `Port 4788 is in use. Starting daemon on available port <N> instead.`
3. Track the chosen port in daemon pointer and manifest files.

### Concurrency

- `daemon-active-*.json.lock` serializes daemon spawns across concurrent CLI invocations.
- `server-control/startup.lock` serializes local server starts (foreground web, MCP, supervised daemon).

### Commands that do **not** use daemon auto-start

- `executor web` (without `--foreground`) — requires an already-running service
- `executor install` / `executor service install` — registers OS service instead
- `executor mcp` — starts its own ephemeral foreground server, not the scope daemon
- `executor daemon run --foreground` — you start it explicitly

<Note>
`executor mcp` always starts a dedicated foreground server on an available port. It does not attach to an existing daemon.
</Note>

## Runtime paths and environment

| Variable / path | Role |
| --- | --- |
| `EXECUTOR_DATA_DIR` | Data root (default `~/.executor`) |
| `EXECUTOR_SCOPE_DIR` | Workspace scope for daemon pointer and DB isolation |
| `EXECUTOR_WEB_BASE_URL` | Web UI base URL override (set automatically during local sessions) |
| `EXECUTOR_API_KEY` / `EXECUTOR_AUTH_TOKEN` | Bearer fallback for server connections |
| `EXECUTOR_SUPERVISED` | Set by OS service managers; daemon reclaims stale manifests on boot |
| `~/.executor/server-connections.json` | Named server profiles |
| `~/.executor/server-control/server.json` | Active local server manifest |
| `~/.executor/auth.json` | Stable local bearer token (mode `0600`) |

See [Configuration reference](/configuration-reference) for the full environment variable list.

## Error handling

- Most failures exit with code `1`.
- Normalized error text strips ANSI sequences and repeated `Error:` prefixes.
- Use `--log-level debug` for full `Cause.pretty` output.
- Paused executions exit `0` from `resume` when still paused after an interaction.

## Related pages

<CardGroup>
<Card title="Installation" href="/installation">
Install the published CLI and verify the background service starts.
</Card>
<Card title="Quickstart" href="/quickstart">
Install, open the web UI, add an integration, and call your first tool.
</Card>
<Card title="Tools" href="/tools">
Tool addresses, discovery, and invocation across CLI, HTTP, and MCP.
</Card>
<Card title="Connect MCP clients" href="/connect-mcp-clients">
Wire Cursor, Claude Code, and other clients to `executor mcp`.
</Card>
<Card title="Configuration reference" href="/configuration-reference">
Environment variables, ports, and data directory layout.
</Card>
<Card title="Troubleshooting" href="/troubleshooting">
Daemon port conflicts, unreachable servers, and recovery commands.
</Card>
</CardGroup>
