> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wolffi.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Terminal CLI

> The whole app in a terminal — a wolffish command that attaches to the running agent, chats, browses settings, and works over SSH

# The Whole App, in a Terminal

Since **v1.0.239** there is a `wolffish` command, and it is not a smaller second Wolffish. Every command it has is a call into **the same code the desktop windows call** — the same settings with the same labels and descriptions, in your own language, Arabic included; the same conversations; the same agent. The desktop app remains the primary way to live with Wolffish. The terminal is the same app for the places a window can't go: an SSH session, a script, a [server with no screen](/getting-started/server-deployment).

```bash theme={null}
wolffish "what changed in the workspace today?"
```

One-shot: ask, print, exit. Or just `wolffish` for an interactive session.

## A View, Not the App

The important part is what the terminal *is*: **a view**. Wolffish runs as a background process and the command attaches to it — if the desktop app is open, the terminal attaches to *that*, and turns you run from the shell stream into the window too. If nothing is running, the first command **starts the agent itself**, headless, and attaches.

That has consequences worth internalizing:

* **Leaving stops nothing.** Close the terminal or drop the SSH connection and the turn keeps working. Come back, run `wolffish`, and it reattaches to whatever is still running.
* **Detaching is not cancelling.** Stopping a run is its own deliberate act: `Ctrl-C` during a turn, or `wolffish cancel` from anywhere — which stops a running turn on *any* channel, including a runaway automation on a headless box.
* **Approvals park.** A tool call waiting on your yes/no when the terminal goes away doesn't fail — it parks, and is redrawn when you reattach (`/pending`), or answered from [your phone](/integrations/mobile-app).

<Note>
  Three commands never start the agent: `wolffish status`, `wolffish service`, and `wolffish path`. They report on the machine's state, so they must be able to say "not running" rather than quietly starting a daemon to answer the question. Everything else brings the agent up on demand.
</Note>

## Chat

```bash theme={null}
wolffish                          # open a session
wolffish "<prompt>"               # ask once, print, exit
wolffish -p "<prompt>" -f a.pdf   # attach files by path
wolffish -p "…" --project <id>    # ask inside a project
cat log.txt | wolffish -p "why?"  # pipe context in
wolffish resume [id]              # continue a past conversation
```

Replies arrive as **rendered markdown** — headings, bold, lists, tables, quotes, and code in a bordered block labelled with its language, drawn as the model streams. The model sends the same markdown to every surface, deliberately; the terminal simply got the renderer the window and the phone already had.

Files are **paths in both directions**, because the terminal and the agent share one filesystem: nothing is uploaded, nothing is encoded, and a delivered file prints the path you can already open.

Inside a session, `/help` lists the whole slash vocabulary — the highlights:

|                                                                            |                                                                                      |
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `/new` · `/resume [id]` · `/switch <n\|id>`                                | Move between conversations without leaving the session                               |
| `/show [tools\|clean] [n]`                                                 | Read the conversation back, paged, with or without tool calls                        |
| `/attach <path…>` · `/files` · `/open <n>` · `/save <n> <dest>`            | Stage files for the next message; collect what the agent delivered                   |
| `/pending`                                                                 | Answer approvals parked by an earlier session                                        |
| `/rate <0-10>`                                                             | Score the last answer — the same signal [reflection](/memory/reflection) learns from |
| `/cancel` · `/info` · `/status` · `/usage` · `/logs` · `/diagnose`         | The running turn, the conversation, the machine                                      |
| `/projects` · `/procedures` · `/automations` · `/customizations`           | The [workspace](#the-app-in-the-terminal), browsable in place                        |
| `/settings [name]` · `/set <id> <value>` · `/model` · `/mode` · `/verbose` | Settings, from a browser to a one-liner                                              |

`Ctrl-C` follows one rule — it stops the nearest thing: a running turn first, then a nested prompt, then (pressed twice) the session itself, always saying which. `Ctrl-D` leaves immediately. **The agent keeps running without you** either way.

## The App, in the Terminal

The top level is the app's own navigation and nothing more — `conversations`, `projects`, `procedures`, `automations`, `customizations`, `settings` — because a second taxonomy to memorize would be a second app:

```bash theme={null}
wolffish conversations            # list · show · resume · diagnose · rate · rm
wolffish projects                 # browse · new · show · edit · rename · rm
wolffish procedures               # browse · new · run · edit · mode · project · rm
wolffish automations              # browse · show <label> · run <label> · edit
wolffish customizations           # soul · user · agents — view, or edit <name>
```

Projects, procedures and automations all carry [attached files and working folders](/configuration/projects), editable here exactly as in the app:

```bash theme={null}
wolffish procedures files <id> add report.pdf   # copied into the workspace
wolffish automations dirs "Daily digest" add ~/notes
```

And the workspace itself is walkable — `wolffish files` to browse it, `wolffish view <path>` to read one file (credentials masked unless you pass `--raw`), `wolffish edit <path>` to change one.

### Settings, three ways

`wolffish settings` *is* the settings screen, walked the way the app walks it — **page → card → setting** — with a blank line always meaning "up one level", so there is one key to learn rather than a different escape at every depth. Jump straight to a card (`wolffish settings channels telegram`), name a destination (`wolffish settings notion`), or type any word and get everything matching it, wherever it lives.

The things that were never a single value sit on their cards too: entering a provider key, choosing the brain, connecting Notion or GitHub or Google, adding an MCP server, pairing a phone, linking WhatsApp or Telegram, running a reflection now, resetting the workspace. Keys are **typed hidden** — they land in neither your terminal nor your shell history — and tested before they're saved.

For scripts, skip the browsing:

```bash theme={null}
wolffish settings list            # read them all, tokens redacted
wolffish settings set channels.telegram.verbose true
wolffish brain deepseek deepseek-v4-flash
```

### An editor that always resolves

Editing a prompt or a document opens, in order of preference: your own `$EDITOR` (or `$VISUAL`, or `$WOLFFISH_EDITOR` ahead of both); otherwise an editor that is **actually installed** — nano, micro, vim, notepad — saying which one it opened; and failing both, a **built-in line editor with no dependencies at all**, which works inside an SSH session on a box with nothing on it: type to append, `:s <n> <text>` to replace a line, `:d <n>` to delete, `:show` to reprint, `:save` or `:cancel` to leave. Half the menu used to dead-end at `no $EDITOR set` — the default state of a fresh server login. Nothing dead-ends now.

## Approvals and Safety

When the agent wants to do something the [amygdala](/architecture/brain-modules) flags, the terminal draws the approval card: `approve? [y]es / [n]o / [a]lways this tool` — where `a` lasts for this session only. Two properties matter more than the keystrokes:

* **Non-interactive runs fail closed.** If there is no terminal to ask — a cron job, a pipe — the approval is denied, not assumed. Re-run interactively, or pass `--yes` deliberately.
* **`--yes` puts back what it found.** It flips the app-wide bypass for the run and restores the *previous* value on exit — including on `Ctrl-C` and a dropped connection — so one scripted run can't leave every surface running with approvals off.

A handful of window-only actions — file pickers, reveal-in-folder — are refused by name with the terminal's own way to do the same thing (`pass file paths instead: wolffish -f <path>`). On a box with no display, `/open` prints where the file is rather than pretending to open it.

## The Terminal Is a Channel

A conversation started from the terminal is a real conversation on a real channel — id `cli`, label **Terminal**. It wears its own **origin badge** in the desktop's History and rail and on [your phone's lists](/integrations/mobile-app), a score cast here is recorded as coming from here, and the agent's own channel roster names the terminal as a route to you, exactly like Telegram, WhatsApp, and the phone. **Settings → Channels → CLI** holds its two knobs: verbose task results, and [autostart](/getting-started/server-deployment#make-it-survive-a-reboot) — with `--tools` / `--clean` overriding verbosity for a single command.

The panel also answers whether the `wolffish` command is on your PATH — from **your shell's PATH, not the app's** — installs it if it isn't, takes it back off when you want it gone, and warns when something else named `wolffish` comes first. From the terminal side, the same answers live under `wolffish path status` and `wolffish path install`. On Linux the `.deb` and `.rpm` **ship the command** at `/usr/bin/wolffish`, there the moment the install finishes; on Windows the installer puts it on your user PATH; on macOS, one `wolffish path install` prints the line to add.

## Pairing From a Terminal

The three channels that need a handshake all pair from here — built for the machine where no window will ever open:

```bash theme={null}
wolffish pair phone        # QR drawn in the terminal — black-on-white, scanner-friendly
wolffish pair phone --code # typed code instead: K7M9-2QXR, for a small window
wolffish pair whatsapp --number +15551234567
wolffish pair telegram     # BotFather token, typed hidden
```

The QR is measured before it is drawn: a pairing code needs 27 rows against an SSH window's usual 24, and when it can't fit, the command says so with the exact numbers and **switches to the typed code by itself** — same for WhatsApp, whose QR can never fit and which links by phone number instead. See [Mobile App](/integrations/mobile-app#pairing) for what pairing means and [Server Deployment](/getting-started/server-deployment) for why a paired phone is the best interface a server can have.

## Reference

| Flag                             | Meaning                                                            |
| -------------------------------- | ------------------------------------------------------------------ |
| `--json`                         | Machine-readable output where it applies                           |
| `--yes` / `-y`                   | Approve tool calls for this run, restoring the prior setting after |
| `--tools` / `--clean`            | Show or hide tool calls, overriding the saved verbosity once       |
| `--last <n>` · `--limit <n>`     | Trim `show` and lists                                              |
| `-p` / `-f` / `-c` / `--project` | Prompt, files, conversation, project                               |
| `--raw`                          | Print credentials instead of masking them                          |
| `--no-color`                     | Plain text                                                         |

Exit codes are honest: `0` it worked, `1` the thing failed or isn't in the state you asked about, `2` you used the command wrong — and a single mistyped word gets *did you mean*, rather than being sent to the model as a question and spending a real turn to be told it wasn't understood. Anything not recognized as a command is treated as a prompt.

| Environment           | Effect                                      |
| --------------------- | ------------------------------------------- |
| `WOLFFISH_EDITOR`     | Editor, ahead of `$VISUAL` / `$EDITOR`      |
| `WOLFFISH_SOCKET`     | Override the control socket path            |
| `WOLFFISH_HEADLESS=1` | Start the daemon with no window and no tray |
| `WOLFFISH_UNICODE=0`  | Force plain glyphs for boxes and QR codes   |

<Card title="Deploy on a server" icon="server" href="/getting-started/server-deployment">
  The terminal exists for the machine with no screen — a VPS install verified end to end on Ubuntu 24.04, running as a background service, with your phone as the daily interface.
</Card>
