# switchdesk CLI reference

Source: https://switchdesk.org/docs/ai/cli

> Every switchdesk command and flag (CLI 0.1.0): to-dos, meetings, notes and approvals from the terminal, login, Keychain, exit codes and switchdesk mcp.

## Install and sign in {#install}

```sh
npm install -g switchdesk
switchdesk login
switchdesk whoami
```

1. In SwitchDesk on your Mac: **Settings → AI Access → Connect an AI → Terminal & coding tools (CLI)**, pick what it may do, **Continue**. “Copy the key now. It won’t be shown again.”
2. Run `switchdesk login` and paste the key. Nothing shows while you paste. The key is checked, then saved in your macOS Keychain (service `switchdesk`, account `$USER`), never in a plain file.
3. `switchdesk whoami` shows the connection and what it may do. `switchdesk logout` removes the Keychain copy; to end a key, revoke it in SwitchDesk.

Needs Node.js 20 or newer and SwitchDesk Pro. Keys never go on the command line (shell history): `login --stdin` reads one from a pipe.

## Where the key comes from {#key}

1. `SWITCHDESK_TOKEN`, if set (Linux, CI, a cloud agent’s secret store).
2. The macOS Keychain item `switchdesk` / `$USER` (what `switchdesk login` writes; the app’s “Without the CLI” setup uses the same item).
3. A token file you made yourself: `~/.config/switchdesk/token` (or under `$XDG_CONFIG_HOME`), refused unless it is `chmod 600`.

| Variable | Does |
|---|---|
| `SWITCHDESK_TOKEN` | The key, read first |
| `SWITCHDESK_API_URL` | Another API base (https only, or http on loopback for tests) |
| `SWITCHDESK_KEYCHAIN_SERVICE` | Another Keychain service name |
| `SWITCHDESK_DEBUG` | `switchdesk mcp` logs method names and HTTP statuses to stderr (never arguments, results or the key) |

## Output and exit codes {#exit-codes}

Output is a table; `--json` on any command prints the API’s JSON (errors too, on stdout). Server text is stripped of control characters before it reaches your terminal. Writes send an idempotency key, so the one automatic retry after a network error can’t act twice.

| Exit | Means |
|---|---|
| `0` | ok |
| `1` | error |
| `2` | not allowed |
| `3` | waiting for approval |
| `4` | not available, not shared or needs confirm |
| `5` | rate limited |

Error codes behind 2, 4 and 5: `capability_off` → 2, `plan_required` → 2, `paused` → 2, `missing_key` → 2, `invalid_key` → 2, `revoked` → 2, `expired` → 2, `not_available_yet` → 4, `copy_off` → 4, `transcripts_off` → 4, `needs_confirm` → 4, `no_mac` → 4, `brain_off_for_ai` → 4, `brain_off` → 4, `secret` → 2, `rate_limited` → 5. Everything else is 1. Codes: [Errors](/docs/ai#errors).

## Shortcuts {#shortcuts}

| Shortcut | Same as |
|---|---|
| `switchdesk ls` | `switchdesk todos list` |
| `switchdesk add` | `switchdesk todos add` |
| `switchdesk show` | `switchdesk todos get` |
| `switchdesk edit` | `switchdesk todos update` |
| `switchdesk done` | `switchdesk todos done` |
| `switchdesk undone` | `switchdesk todos undone` |
| `switchdesk start` | `switchdesk todos start` |
| `switchdesk rm` | `switchdesk todos delete` |
| `switchdesk todo` | `switchdesk todos` |
| `switchdesk ask` | `switchdesk approvals ask` |
| `switchdesk proposals` | `switchdesk approvals list` |
| `switchdesk proposal` | `switchdesk approvals get` |
| `switchdesk propose` | `switchdesk approvals propose` |
| `switchdesk meeting` | `switchdesk meetings` |
| `switchdesk note` | `switchdesk notes` |
| `switchdesk recap` | `switchdesk recap` |
| `switchdesk category` | `switchdesk categories` |
| `switchdesk remember` | `switchdesk brain remember` |

Inside a group: `ls` = `list`, `show` = `get`, `new` = `create`, `rm` = `delete`, `edit` = `update`. A bare group lists (`switchdesk todos`), a group plus an id gets one (`switchdesk notes <id>`), and `-` in place of text reads stdin (`switchdesk notes create -`). `switchdesk <command> --help` prints the options below.

## Local MCP server: switchdesk mcp {#mcp}

`switchdesk mcp` speaks MCP over stdio and forwards each message to `https://api.switchdesk.org/mcp` with the stored key, so no MCP config file holds it. Without a key, every request is answered with “run switchdesk login”.

```sh
# Claude Code
claude mcp add switchdesk -- switchdesk mcp
```

```json
{
  "mcpServers": {
    "switchdesk": {
      "command": "switchdesk",
      "args": ["mcp"]
    }
  }
}
```

Put the second block in `~/.cursor/mcp.json` (Cursor) or `~/Library/Application Support/Claude/claude_desktop_config.json` (Claude Desktop). If the app can’t find `switchdesk`, use the full path from `which switchdesk`.

## Commands {#commands}

| Command | Does |
|---|---|
| [`switchdesk login`](#login) | Save your SwitchDesk AI key in the macOS Keychain |
| [`switchdesk logout`](#logout) | Remove the key from your Keychain (revoke it in SwitchDesk to end it) |
| [`switchdesk whoami`](#whoami) | This connection: name, access, plan |
| [`switchdesk status`](#status) | Same as whoami |
| [`switchdesk todos list`](#todos-list) | List to-dos (open ones by default) |
| [`switchdesk todos get`](#todos-get) | One to-do with notes, sub-to-dos and Team Notes |
| [`switchdesk todos add`](#todos-add) | Add a to-do (Incoming unless you say where) |
| [`switchdesk todos update`](#todos-update) | Change only the fields you pass |
| [`switchdesk todos done`](#todos-done) | Check off to-dos |
| [`switchdesk todos undone`](#todos-undone) | Reopen to-dos |
| [`switchdesk todos start`](#todos-start) | Mark to-dos in progress |
| [`switchdesk todos delete`](#todos-delete) | Delete to-dos (you can Undo in SwitchDesk for 7 days) |
| [`switchdesk todo-notes add`](#todo-notes-add) | Post a Team Note on a to-do |
| [`switchdesk todo-notes delete`](#todo-notes-delete) | Delete one of your Team Notes |
| [`switchdesk categories list`](#categories-list) | Categories with their bios |
| [`switchdesk categories create`](#categories-create) | Create a category |
| [`switchdesk categories update`](#categories-update) | Change a category's bio or colour (never its name) |
| [`switchdesk meetings list`](#meetings-list) | Meetings you share with AI, newest first |
| [`switchdesk meetings search`](#meetings-search) | Full-text search over meetings (and transcripts when allowed) |
| [`switchdesk meetings get`](#meetings-get) | A meeting's summary, action items and your notes |
| [`switchdesk meetings transcript`](#meetings-transcript) | A meeting's transcript (one page, or --all) |
| [`switchdesk notes list`](#notes-list) | Notepad notes you share with AI, last changed first |
| [`switchdesk notes search`](#notes-search) | Full-text search over shared notes |
| [`switchdesk notes get`](#notes-get) | One note's whole body |
| [`switchdesk notes create`](#notes-create) | Create a note (queued for your Mac) |
| [`switchdesk notes append`](#notes-append) | Add text at the end of a note (queued) |
| [`switchdesk notes update`](#notes-update) | Retitle or retag a note (queued) |
| [`switchdesk notes delete`](#notes-delete) | Move a note to the Notes trash (queued) |
| [`switchdesk recap get`](#recap-get) | The newest day or week recap your Mac made |
| [`switchdesk brain search`](#brain-search) | Search your Brain (cited snippets + the names it knows) |
| [`switchdesk brain page`](#brain-page) | A Brain page: a person, company, project or topic, or a site's context page |
| [`switchdesk brain remember`](#brain-remember) | Tell your Brain to remember something (asks you first by default) |
| [`switchdesk approvals list`](#approvals-list) | This connection's approval cards |
| [`switchdesk approvals get`](#approvals-get) | One approval card's status, results and answer |
| [`switchdesk approvals ask`](#approvals-ask) | Ask the person a question in SwitchDesk |
| [`switchdesk approvals propose`](#approvals-propose) | Send several changes as ONE approval card |
| [`switchdesk activity`](#activity) | Where to see what this connection did |
| [`switchdesk undo`](#undo) | Where to undo a change |
| [`switchdesk mcp`](#mcp) | Run a stdio MCP server that proxies to SwitchDesk (for Claude Desktop, Claude Code, Cursor) |
| [`switchdesk tools`](#tools) | Every API tool and the command that calls it (--check: fail if one is missing) |
| [`switchdesk call`](#call) | Call any API tool with JSON arguments (advanced) |

### switchdesk login {#login}

Save your SwitchDesk AI key in the macOS Keychain.

```sh
switchdesk login [--stdin]
```

Options:

- `--stdin`: Read the key from stdin instead of a hidden prompt

Calls [`get_access`](/docs/ai/mcp#get_access). Add `--json` for the API’s JSON.

### switchdesk logout {#logout}

Remove the key from your Keychain (revoke it in SwitchDesk to end it).

```sh
switchdesk logout
```

### switchdesk whoami {#whoami}

This connection: name, access, plan.

```sh
switchdesk whoami
```

Calls [`get_access`](/docs/ai/mcp#get_access). Add `--json` for the API’s JSON.

### switchdesk status {#status}

Same as whoami.

```sh
switchdesk status
```

Calls [`get_access`](/docs/ai/mcp#get_access). Add `--json` for the API’s JSON.

### switchdesk todos list {#todos-list}

List to-dos (open ones by default).

```sh
switchdesk todos list [--incoming|--today|--week|--section S] [-c CATEGORY] [-q TEXT] [--done|--all]
```

Options:

- `--incoming`
- `--today`
- `--week`: This Week
- `--section S`: incoming|today|week|category|uncategorized|assigned|done
- `-c, --category NAME`
- `--category-id ID`
- `-q, --query TEXT`: Search titles and notes
- `--done`: Done to-dos only
- `--all`: Open and done
- `--backlog`
- `--due-before DATE`
- `--notes`: Include each to-do's notes
- `--limit N`
- `--cursor C`

Calls [`list_todos`](/docs/ai/mcp#list_todos). Add `--json` for the API’s JSON.

### switchdesk todos get {#todos-get}

One to-do with notes, sub-to-dos and Team Notes.

```sh
switchdesk todos get ID
```

Calls [`get_todo`](/docs/ai/mcp#get_todo). Add `--json` for the API’s JSON.

### switchdesk todos add {#todos-add}

Add a to-do (Incoming unless you say where).

```sh
switchdesk todos add TITLE [-c CATEGORY] [--today|--week [--day mon]] [--due DATE] [--repeat RULE] [--notes TEXT]
```

Options:

- `-c, --category NAME`
- `--category-id ID`
- `--incoming`
- `--today`
- `--week`: This Week
- `--day DAY`: With --week: 1-7 or mon…sun
- `--next-week`
- `--notes TEXT`
- `--tag CATEGORY`: For Incoming: the category it probably belongs to
- `--due DATE`
- `--repeat RULE`: An RRULE like FREQ=WEEKLY;BYDAY=MO
- `--tz ZONE`: IANA time zone, when SwitchDesk doesn't know yours
- `--parent ID`: Add it as a sub-to-do
- `--urgent`
- `--estimate MIN`

Calls [`add_todo`](/docs/ai/mcp#add_todo). Add `--json` for the API’s JSON.

### switchdesk todos update {#todos-update}

Change only the fields you pass.

```sh
switchdesk todos update ID [--title T] [--append-notes T] [-c CATEGORY|--today|--week] [--due DATE|--no-due] [--urgent] …
```

Options:

- `--title T`
- `--notes T`: Replace the notes
- `--append-notes T`
- `-c, --category NAME`
- `--category-id ID`
- `--today`
- `--week`
- `--uncategorized`
- `--day DAY`
- `--no-day`: The week's backlog
- `--next-week`
- `--no-next-week`
- `--due DATE`
- `--no-due`
- `--repeat RULE`
- `--no-repeat`: Stop repeating
- `--urgent`
- `--not-urgent`
- `--blocked`
- `--not-blocked`
- `--backlog`
- `--no-backlog`
- `--estimate MIN`
- `--priority 1-10`
- `--progress T`: Progress note
- `--parent ID`: Nest under a main to-do
- `--no-parent`: Make it a main to-do
- `--tz ZONE`

Calls [`update_todo`](/docs/ai/mcp#update_todo). Add `--json` for the API’s JSON.

### switchdesk todos done {#todos-done}

Check off to-dos.

```sh
switchdesk todos done ID [ID…]
```

Calls [`set_todo_state`](/docs/ai/mcp#set_todo_state). Add `--json` for the API’s JSON.

### switchdesk todos undone {#todos-undone}

Reopen to-dos.

```sh
switchdesk todos undone ID [ID…]
```

Calls [`set_todo_state`](/docs/ai/mcp#set_todo_state). Add `--json` for the API’s JSON.

### switchdesk todos start {#todos-start}

Mark to-dos in progress.

```sh
switchdesk todos start ID [ID…]
```

Calls [`set_todo_state`](/docs/ai/mcp#set_todo_state). Add `--json` for the API’s JSON.

### switchdesk todos delete {#todos-delete}

Delete to-dos (you can Undo in SwitchDesk for 7 days).

```sh
switchdesk todos delete ID [ID…] [--stop-series]
```

Options:

- `--stop-series`: Needed for a repeating to-do: ends the series

Calls [`delete_todos`](/docs/ai/mcp#delete_todos). Add `--json` for the API’s JSON.

### switchdesk todo-notes add {#todo-notes-add}

Post a Team Note on a to-do.

```sh
switchdesk todo-notes add TODO_ID TEXT…
```

Calls [`add_todo_note`](/docs/ai/mcp#add_todo_note). Add `--json` for the API’s JSON.

### switchdesk todo-notes delete {#todo-notes-delete}

Delete one of your Team Notes.

```sh
switchdesk todo-notes delete NOTE_ID
```

Calls [`delete_todo_note`](/docs/ai/mcp#delete_todo_note). Add `--json` for the API’s JSON.

### switchdesk categories list {#categories-list}

Categories with their bios.

```sh
switchdesk categories list
```

Calls [`list_categories`](/docs/ai/mcp#list_categories). Add `--json` for the API’s JSON.

### switchdesk categories create {#categories-create}

Create a category.

```sh
switchdesk categories create NAME [--bio TEXT] [--color #RRGGBB]
```

Options:

- `--bio TEXT`
- `--color #RRGGBB`

Calls [`create_category`](/docs/ai/mcp#create_category). Add `--json` for the API’s JSON.

### switchdesk categories update {#categories-update}

Change a category's bio or colour (never its name).

```sh
switchdesk categories update ID [--bio TEXT] [--color #RRGGBB]
```

Options:

- `--bio TEXT`
- `--color #RRGGBB`

Calls [`update_category`](/docs/ai/mcp#update_category). Add `--json` for the API’s JSON.

### switchdesk meetings list {#meetings-list}

Meetings you share with AI, newest first.

```sh
switchdesk meetings list [--since 7d|DATE] [--until DATE] [-c CATEGORY] [-q TEXT]
```

Options:

- `--since DATE|7d`
- `--until DATE`
- `-c, --category NAME`
- `-q, --query TEXT`
- `--limit N`
- `--cursor C`

Calls [`list_meetings`](/docs/ai/mcp#list_meetings). Add `--json` for the API’s JSON.

### switchdesk meetings search {#meetings-search}

Full-text search over meetings (and transcripts when allowed).

```sh
switchdesk meetings search QUERY… [--since DATE] [-c CATEGORY] [--limit N]
```

Options:

- `--since DATE|7d`
- `-c, --category NAME`
- `--limit N`

Calls [`search_meetings`](/docs/ai/mcp#search_meetings). Add `--json` for the API’s JSON.

### switchdesk meetings get {#meetings-get}

A meeting's summary, action items and your notes.

```sh
switchdesk meetings get ID [--include summary,action_items,my_notes,transcript]
```

Options:

- `--include LIST`
- `--transcript`: Also the transcript's first page

Calls [`get_meeting`](/docs/ai/mcp#get_meeting). Add `--json` for the API’s JSON.

### switchdesk meetings transcript {#meetings-transcript}

A meeting's transcript (one page, or --all).

```sh
switchdesk meetings transcript ID [--page N | --all]
```

Options:

- `--page N`
- `--all`: Every page

Calls [`get_meeting`](/docs/ai/mcp#get_meeting). Add `--json` for the API’s JSON.

### switchdesk notes list {#notes-list}

Notepad notes you share with AI, last changed first.

```sh
switchdesk notes list [-q TEXT] [--tag TAG]
```

Options:

- `-q, --query TEXT`
- `--tag TAG`
- `--limit N`
- `--cursor C`

Calls [`list_notes`](/docs/ai/mcp#list_notes). Add `--json` for the API’s JSON.

### switchdesk notes search {#notes-search}

Full-text search over shared notes.

```sh
switchdesk notes search QUERY… [--limit N]
```

Options:

- `--limit N`

Calls [`search_notes`](/docs/ai/mcp#search_notes). Add `--json` for the API’s JSON.

### switchdesk notes get {#notes-get}

One note's whole body.

```sh
switchdesk notes get ID
```

Calls [`get_note`](/docs/ai/mcp#get_note). Add `--json` for the API’s JSON.

### switchdesk notes create {#notes-create}

Create a note (queued for your Mac).

```sh
switchdesk notes create [--title T] [--tag TAG]… BODY…|-
```

Options:

- `--title T`
- `--tag TAG (repeatable)`

Calls [`create_note`](/docs/ai/mcp#create_note). Add `--json` for the API’s JSON.

### switchdesk notes append {#notes-append}

Add text at the end of a note (queued).

```sh
switchdesk notes append ID TEXT…|-
```

Calls [`append_to_note`](/docs/ai/mcp#append_to_note). Add `--json` for the API’s JSON.

### switchdesk notes update {#notes-update}

Retitle or retag a note (queued).

```sh
switchdesk notes update ID [--title T] [--tag TAG]… [--clear-tags]
```

Options:

- `--title T`
- `--tag TAG (repeatable)`: Replaces the whole tag list
- `--clear-tags`

Calls [`update_note`](/docs/ai/mcp#update_note). Add `--json` for the API’s JSON.

### switchdesk notes delete {#notes-delete}

Move a note to the Notes trash (queued).

```sh
switchdesk notes delete ID
```

Calls [`delete_note`](/docs/ai/mcp#delete_note). Add `--json` for the API’s JSON.

### switchdesk recap get {#recap-get}

The newest day or week recap your Mac made.

```sh
switchdesk recap get [day|week] [--date DATE]
```

Options:

- `--date DATE`

Calls [`get_recap`](/docs/ai/mcp#get_recap). Add `--json` for the API’s JSON.

### switchdesk brain search {#brain-search}

Search your Brain (cited snippets + the names it knows).

```sh
switchdesk brain search QUERY… [--space NAME] [--limit N]
```

Options:

- `-s, --space NAME`: One space (name or id)
- `--limit N`

Calls [`search_brain`](/docs/ai/mcp#search_brain). Add `--json` for the API’s JSON.

### switchdesk brain page {#brain-page}

A Brain page: a person, company, project or topic, or a site's context page.

```sh
switchdesk brain page ID [--kind entity|page]
```

Options:

- `--kind KIND`: entity or page

Calls [`get_brain_page`](/docs/ai/mcp#get_brain_page). Add `--json` for the API’s JSON.

### switchdesk brain remember {#brain-remember}

Tell your Brain to remember something (asks you first by default).

```sh
switchdesk brain remember TEXT…|- [--space NAME]   (or: switchdesk remember TEXT…)
```

Options:

- `-s, --space NAME`: File it in this space (name or id)

Calls [`remember`](/docs/ai/mcp#remember). Add `--json` for the API’s JSON.

### switchdesk approvals list {#approvals-list}

This connection's approval cards.

```sh
switchdesk approvals list [--status pending|approved|denied|answered|expired|withdrawn] [--since ISO]
```

Options:

- `--status S`
- `--since ISO`
- `--limit N`

Calls [`list_proposals`](/docs/ai/mcp#list_proposals). Add `--json` for the API’s JSON.

### switchdesk approvals get {#approvals-get}

One approval card's status, results and answer.

```sh
switchdesk approvals get ID
```

Calls [`get_proposal`](/docs/ai/mcp#get_proposal). Add `--json` for the API’s JSON.

### switchdesk approvals ask {#approvals-ask}

Ask the person a question in SwitchDesk.

```sh
switchdesk approvals ask QUESTION… [--option A]… [--todo ID]… [--wait] [--timeout SECONDS]
```

Options:

- `--option TEXT (repeatable)`: Up to 3 answers (default Yes / No)
- `--todo ID (repeatable)`
- `--wait`: Wait for the answer
- `--timeout SECONDS`: With --wait (default 600)

Calls [`ask_me`](/docs/ai/mcp#ask_me), [`get_proposal`](/docs/ai/mcp#get_proposal). Add `--json` for the API’s JSON.

### switchdesk approvals propose {#approvals-propose}

Send several changes as ONE approval card.

```sh
switchdesk approvals propose -f ops.json|- [--summary TEXT]
```

Options:

- `-f, --file FILE`
- `--summary TEXT`

Calls [`propose_changes`](/docs/ai/mcp#propose_changes). Add `--json` for the API’s JSON.

### switchdesk activity {#activity}

Where to see what this connection did.

```sh
switchdesk activity
```

### switchdesk undo {#undo}

Where to undo a change.

```sh
switchdesk undo
```

### switchdesk mcp {#mcp}

Run a stdio MCP server that proxies to SwitchDesk (for Claude Desktop, Claude Code, Cursor).

```sh
switchdesk mcp
```

### switchdesk tools {#tools}

Every API tool and the command that calls it (--check: fail if one is missing).

```sh
switchdesk tools [--check]
```

Options:

- `--check`

### switchdesk call {#call}

Call any API tool with JSON arguments (advanced).

```sh
switchdesk call TOOL [--args JSON | --args-file FILE|-]
```

Options:

- `--args JSON`
- `--args-file FILE`

## Safety {#safety}

Don’t allowlist every `switchdesk` command for a coding agent (`Bash(switchdesk:*)`): a web page or file it reads could talk it into deleting things. Allow the read commands you want and keep writes behind a prompt. A key stored on a shared machine (a Grok Bot computer, a CI runner) is readable by everything that runs there. For agent instructions see the [Claude Code skill](/docs/ai/claude-code-skill).
