# Slash commands

> Slash commands are client-side actions you trigger from the composer by typing /. They run locally in the UI — they are not model turns — and cover everything from switching modes to resuming a session.

Slash commands are client-side actions you trigger from the composer by typing
`/`. They run locally in the UI — they are not model turns — and cover
everything from switching modes to resuming a session.

<!-- SOURCE: src/kin/harness/commands.py, src/kin/harness/github_connection.py, src/kin/harness/defaults/commands/beam.md, src/kin/harness/defaults/commands/shelf.md, src/kin/tui/commands/, src/kin/tui/commands_mixin.py, src/kin/tui/composer_assist.py, src/kin/tui/diff.py, src/kin/tui/widgets/, src/kin/tui/modals/, src/kin/tui/artifact_editor.py, src/kin/harness/artifact_edit.py, src/kin/tui/banner.py, src/kin/tui/turn_lifecycle.py, src/kin/tui/modal_workers.py, src/kin/tui/mcp_lifecycle.py, src/kin/tui/git_tree.py, src/kin/tui/bg_agents_bar.py, src/kin/tui/external_editor.py -->

## Using the menu

Type `/` in the composer and a filtered menu appears above the input. Keep
typing to narrow it — the menu shows every command whose name starts with what
you have typed. The menu stays open only while the text is a bare `/token`
(no space, no newline); as soon as you type a space the menu hides so you can
add arguments.

| Key | Action |
|-----|--------|
| ++up++ / ++down++ | Move the highlight |
| ++tab++ | Fill the highlighted command into the composer (with a trailing space) so you can add arguments |
| ++enter++ | Run the highlighted command |
| click | Run the clicked command |

The composer keeps focus the whole time, so you filter by typing and the menu
tracks your input. To run a command directly, type its full name and press
++enter++ — the menu does not have to be open.

> **Tip**
>
> ++tab++ fills, ++enter++ runs. Use ++tab++ when a command takes an
> argument (for example `/mode strict` or `/model <id>`) and ++enter++ when it
> does not.

## Built-in commands

These ship with kin and are always available. A user-defined command with the
same name replaces the built-in (see [Custom commands](#custom-commands)).

| Command | Argument | Description |
|---------|----------|-------------|
| `/help` | | Keybindings and commands overlay (also ++f1++) |
| `/clear` | | Reset the transcript and model history (asks to confirm) |
| `/mode` | `<name>` | Set the permission mode (`auto` / `strict`); bare `/mode` toggles `auto ↔ strict` (same as ++shift+tab++) |
| `/plan` | `[task]` | Enter the read-only planning freeze and run `[task]`; bare `/plan` toggles the freeze (the human escape hatch). See [Planning](/docs/kin/guide/modes-and-permissions/#planning) |
| `/model` | `<id>` | Swap the model. Bare `/model` opens a cross-provider picker (favorites first, `f` toggles a favorite, the active endpoint's live models included) showing a `✓ key` badge per provider that's ready to swap, or a `needs key` hint otherwise. `/model <id>` swaps silently when a key resolves from `provider_keys[id]` / the matching vendor or generic env / the shared `api_key`; if nothing resolves a one-field key prompt opens at the point of need — enter saves & swaps, esc cancels |
| `/models` | `[jobs\|connections\|routes]` | Open the staged human model-configuration hub (Jobs by default). Save & apply validates the complete configuration, writes once, and applies one prepared snapshot; Escape discards all staged edits. |
| `/routes` | | Deep-link to `/models routes`: add/edit/duplicate/remove routes and inspect preset/model identity, credential readiness, manual/observed vision, assignments, and this-run usage. Stored secret values are never shown. |
| `/compact` | `[focus]` | Summarize history to free context |
| `/theme` | `[name]` | Switch and persist the TUI theme. Bare cycles `kin` (terminal ground) ↔ `kin-graphite` (opaque fallback); an explicit registered Textual theme name such as `nord` remains available. A standing `KIN_THEME` env or project override is named with a warning |
| `/spinner` | `[name]` | Pick the busy-spinner vibe (`rain` · `braille` · `arc` · `toggle` · `line` — the [style table](/docs/kin/concepts/identity/#spinner-vibes)). Bare opens a picker with a live preview; `/spinner <name>` applies directly. Applies live and **persists** (`spinner` in `~/.kin/settings.toml`; a standing `KIN_SPINNER` env or project override is named with a warning). HUMAN-ONLY cosmetic — not model-writable |
| `/sessions` | | Open the cross-workspace session switcher (also ++ctrl+l++): identify every live instance, switch to one, resume saved work, or choose **New session here** for an independent process |
| `/resume` | `[id]` | Switch to a saved conversation; bare opens a picker. If another managed instance already owns it, switch to that process instead of opening a second journal writer; a plain unwrapped client refuses that case |
| `/detach` | | Leave a [persistent session](/docs/kin/guide/sessions/#background-sessions-detach-reattach) running in the background and return only this terminal to the shell — a running turn and any mirrored terminal keep going. If Kin cannot identify the issuing/current client, it warns and detaches nobody. In a plain launch this explains how to enable the feature; inside your own tmux it points at your multiplexer's detach |
| `/skills` | | List the skills discoverable from the workspace |
| `/mcp` | | Manage MCP servers — enable/disable, add, edit, remove, reconnect live |
| `/reload` | | Re-read `settings.toml` + the mcp.json scopes and apply model routes/wire, appearance (theme + spinner), and MCP changes live (no restart). A route catalog is fully validated before the root/future dispatches switch; running children keep their frozen snapshot. |
| `/tokens` | | Show context usage by component |
| `/export` | `[path]` | Dump the current session's saved transcript to a markdown file — bare writes `kin-export-<session-id>.md` into the workdir; an explicit path wins (overwrite allowed, no confirm) |
| `/fork` | | Branch this session — copies the on-disk journal to a new session id and switches you onto the copy; the source is left untouched, resumable later with `/resume <old-id>` |
| `/editor` | | Compose the current draft in `$VISUAL`/`$EDITOR` (falls back to `vi`) — suspends kin, opens the editor on a temp file seeded with the composer's text, and replaces the composer text on a clean exit. Never submits; you still review and hit enter |
| `/rewind` | `[n] [conversation\|files\|both]` | Roll back the last `n` completed turns — conversation (default), on-disk files, or both. `n>1`, or any `files`/`both` target, asks to confirm. Double-tap ++escape++ on an empty, idle composer for a picker instead of typing this by hand — see [Rewind & retry](/docs/kin/guide/sessions/#rewind-retry) |
| `/retry` | | Re-send the last user message |
| `/grants` | `[revoke <n>]` | View or revoke session approvals and persistent trust grants |
| `/github` | `[status\|connect\|repair] [hostname]` | Check or establish `gh` CLI authentication for structured PR operations |
| `/tree` | | Toggle the file-tree sidebar (also ++ctrl+g++) |
| `/view` | `<path>` | Peek a file in a syntax-highlighted read-only viewer (alias of `v` on the tree) |
| `/providers` | `[name]` | Deep-link to `/models connections`, optionally preselecting a built-in or custom connection. Credentials, default model/tier, custom fields, metadata-only connection checks, and model-catalogue import remain staged until Save & apply. |
| `/brave-key` | | Save your Brave Search API key — opens the search-key picker on its Brave Search row, key field focused; saving enables `web_search` + `web_context` **live** (no restart). Search keys are separate from model credentials, which live in `/models`. See [Web tools](/docs/kin/guide/web-tools/) |
| `/search-key` | | Alias of `/brave-key` |
| `/workflow` | `<goal>` | Run a goal as a fan-out workflow (nudges the model to author an `async def main()` and call the `workflow` tool) |
| `/workflow-save` | `<name>` | Save the most recent successful workflow run's script as a reusable `kind: workflow` command (`/<name>`) |
| `/workflows` | | Open the read-only panel of this session's workflow runs |
| `/nudges` | | Open the session-nudge multi-select. Apply replaces the complete set; Escape cancels. `workflow-first` prefers workflows for substantial staged, parallel, or iterative work without changing tools, effort, or permissions |
| `/effort` | `[level]` | Set reasoning effort — bare opens a per-serve picker; with a level, validates against the picker vocabulary and prompts to confirm. **Changes invalidate the prompt cache**, so inline picks show a confirmation. The TopBar chip (`effort:high` etc.) reflects the active level; resume restores it from the journal. HUMAN-ONLY — the model has no setter and reaches this only via `propose_settings effort=...`, which still requires your approval. See [Models & providers](/docs/kin/guide/models-and-providers/#effort-picker) for the per-serve vocabulary table |
| `/settings` | `[on\|off]` | Let Kin help tune your settings; bare toggles. When on, a settings guide is injected each turn so the model can use the `read_settings` / `propose_settings` [tools](/docs/kin/guide/tools/#settings) — it can only ever change sampling/model knobs, never containment or secrets, and you approve every diff |
| `/cost` | `[on\|off]` | Show/toggle the running inference-cost display; bare reports the current state (+ running total, when on). **Opt-in, default off** (kin's primary endpoint is local vLLM — no cost — and the subscription providers make per-token cost noise). Unlike `/nudges`/`/settings` this **persists globally** — `/cost on\|off` writes `pricing_enabled` to `~/.kin/settings.toml` and flips the live session immediately. HUMAN-ONLY. See [Cost display](/docs/kin/guide/models-and-providers/#cost-display) |
| `/config` | | Open the config picker (including human-only Model configuration, plus AGENTS.md, settings, skills, agents, commands, and `.kin/mcp.json`) — see [Editing config artifacts](#editing-config-artifacts) |
| `/edit-agents` | `[instruction]` | Edit `AGENTS.md` project guidance |
| `/edit-settings` | `[instruction]` | Edit the global `~/.kin/settings.toml` |
| `/edit-mcp` | `[instruction]` | Edit the project `.kin/mcp.json` server config |
| `/new-skill` | `<name> [instruction]` | Draft a new skill |
| `/edit-skill` | `<name> [instruction]` | Edit an existing skill |
| `/new-agent` | `<name> [instruction]` | Draft a new subagent profile |
| `/edit-agent` | `<name> [instruction]` | Edit a subagent profile |
| `/new-command` | `<name> [instruction]` | Draft a new `kind: prompt` slash command |
| `/stop` | | Interrupt the running turn |
| `/exit` | | Quit kin |
| `/quit` | | Quit kin (alias of `/exit`) |
| `/beam` | `[focus hint] \| back [job-id]` | Hand work to Outpost or return a settled job; see [Beam work to Outpost](/docs/kin/guide/beam/) |
| `/handoff` | `[focus hint] \| back [job-id]` | Exact alias of `/beam` |
| `/shelf` | `[park <idea> \| board \| pickup <slug> \| submit <slug> \| recover <slug>]` | Curate durable workspace jobs; see [The shelf](/docs/kin/guide/shelf/) |

A few of these have dedicated pages: `/mode` and `/plan` in
[Modes & permissions](/docs/kin/guide/modes-and-permissions/), `/resume`, `/rewind`,
`/retry`, `/compact`, `/tokens`, `/export`, and `/fork` in
[Sessions, resume & compaction](/docs/kin/guide/sessions/#export), `/skills` in
[Skills](/docs/kin/guide/skills/), `/mcp` in [MCP servers](/docs/kin/guide/mcp/), `/github` below and in
[Git and GitHub tools](/docs/kin/guide/tools/#git-and-github), `/providers` in
[Provider presets](/docs/kin/guide/providers/), `/workflow` / `/workflows` /
`/nudges` in [Workflows](/docs/kin/guide/workflows/), and `/effort` in
[Models & providers](/docs/kin/guide/models-and-providers/#effort-picker)
(the picker is curated per-serve and human-only — invalidate-cache
prompts on inline picks). The full key reference lives in
[Keybindings & cursor mode](/docs/kin/guide/keybindings/).

<a id="github"></a>
### `/github`

`/github` is the proactive human-owned authentication surface for the
structured [`git` and `github` tools](/docs/kin/guide/tools/#git-and-github). A missing login
during either tool now raises the same connection flow in place and resumes
that operation automatically, so you do not normally need to leave the task
and run this command first. Bare `/github` and
`/github status [hostname]` run `gh auth status` and report whether the CLI is
ready without exposing a token. `/github connect [hostname]` suspends the TUI
and runs a fixed `gh auth login --web` flow so `gh` can show its device code and
browser instructions in the real terminal. If a stored account exists but is
unhealthy, Connect uses the fixed `gh auth refresh` flow instead of creating a
duplicate login. Kin selects HTTPS for its own Git calls without rewriting your
saved remote.

`/github repair` first checks the active account. When it is present, repair
performs a real read-only `ls-remote` through the same sandboxed, gh-backed
HTTPS route the structured Git tool uses. If login is absent, repair runs the
login flow. If the account exists but its data-plane probe fails, repair runs
`gh auth refresh` for that active host and probes again. This distinguishes
“the account exists” from “Git transport actually works.”

Kin never stores a GitHub token. `gh` owns its credential broker, and its status
projection removes token fields before output reaches Kin. Both the status
check and model-facing adapter strip inherited `GH_*` / `GITHUB_*` environment
tokens so a repository or launched process cannot silently choose a different
identity. Only the human can accept the connection modal; child and headless
runs report a needs-human requirement instead.

### `/effort`

<a id="effort"></a>

`/effort` flips a per-serve reasoning-depth knob live. The vocabulary is
curated per active backend — `low` / `medium` / `high` / `xhigh` / `max`
for the Anthropic wire (real Anthropic, vLLM Anthropic serve),
`adaptive` / `enabled` / `disabled` for the MiniMax preset (its real
knob is `thinking.type`, not `output_config.effort`), `max` / `high` for
the Z.ai preset (a top-level `reasoning_effort` field — the only two
values z.ai's wire operates on), `low` / `medium` / `high` for the
OpenAI wire against real OpenAI / OpenRouter, the 8-value Z.ai
OpenAI-compat vocab for GLM-5.2+, and `auto` / `on` / `off` for Qwen
vLLM OpenAI-compat (where `auto` leaves
`chat_template_kwargs.enable_thinking` unset — the server's default).
A custom Anthropic provider with `reasoning_profile="poolside"` exposes
`max` / `off` through that same chat-template boolean while retaining signed
thinking blocks.
A named OpenAI Chat or Responses route with
`reasoning_profile="qwen-llamacpp"` instead exposes `default`, `off`, and the
budget-labelled `thinking-128` / `thinking-512` / `thinking-1024` /
`thinking-2048` choices. Those labels map to an exact token budget and are not
OpenAI semantic effort aliases.
See the [effort picker vocabulary table](/docs/kin/guide/models-and-providers/#effort-picker)
for the per-serve dispatch.

Bare `/effort` opens the picker; `/effort <level>` validates against the
active vocabulary and pops a cache-invalidation confirmation modal
because changing the knob invalidates the prompt cache. The set level is
journaled (resume restores it) and the TopBar chip paints the active
value (`effort:high` etc.).

The setter is **HUMAN-ONLY** — the model has no `set_effort` tool. The
model reaches the knob only via `propose_settings effort=…`, which still
requires your diff approval before anything changes (and `reasoning_effort`
is intentionally refused there so the picker stays the single
cross-wire source of truth).

## Editing config artifacts

The `/config` and `/edit-*` / `/new-*` commands let you edit kin's own
configuration files **with kin's help** instead of opening an editor. They drive
a scoped, read-only sub-conversation that drafts the complete new file, then show
you a diff to approve before anything is written.

`/config` opens a picker over the six editable artifacts:

| Artifact | File | Reload on apply |
|----------|------|-----------------|
| AGENTS.md | `<workdir>/AGENTS.md` | system prompt re-composed live |
| settings | `~/.kin/settings.toml` (global) | cache dropped; applies to **new** sessions |
| skill | `<workdir>/.kin/skills/<name>/SKILL.md` | skills catalog re-composed live |
| agent profile | `<workdir>/.kin/agents/<name>.md` | profile cache dropped |
| slash command | `<workdir>/.kin/commands/<name>.md` | command cache rebuilt |
| `.kin/mcp.json` | `<workdir>/.kin/mcp.json` | live MCP reconnect |

Singletons (AGENTS.md, settings, `.kin/mcp.json`) edit in place; the named kinds
(skill, agent, command) open a sub-picker of existing instances plus a **＋ new…**
row. You can also jump straight to a target: `/edit-agents fix the test command`,
`/new-skill triage triage failing CI jobs`, `/edit-settings raise temperature to 1`.
If you give no instruction, kin asks what to change.

How it works, and why it's safe:

- The editor runs as an **isolated subagent** with a hard read-only tool
  allow-list (`read_file` / `ls` / `grep` / `glob`) — it can read the repo to
  match local style but **never writes disk**. Its file-spelunking is hidden
  from the transcript; you just see a *drafting…* note.
- It returns the complete new file through a single `propose_edit` channel,
  which **validates the draft with the real loader's parser** — a draft that
  fails to parse is rejected before you ever see it, so an approved write can't
  produce a file kin then can't load.
- **You approve a diff.** That approval is the only thing that writes the file;
  reject and nothing changes. The settings editor works in JSON and refuses to
  draft any **hand-edit-only** key — containment (`mode`, `sandbox`,
  `shell_allowlist`), egress (`ssh_hosts`), secrets/endpoints (`api_key`,
  `base_url`, `brave_api_key`), and the preset machinery — because the draft is
  model-authored even though *you* invoked `/edit-settings`, and a prompt-injected
  draft must not slip a containment change past a skimmed approval; set those by
  hand. The `.kin/mcp.json` editor sees a redacted copy of the current config.

After you apply, kin fires the matching reload so the change is live without a
restart (settings are the exception — they feed **new** sessions; `/mode` and
`/model` change the live one).

## Custom commands

You can add your own commands as markdown files with frontmatter. kin discovers
them from five roots, highest priority first; a project command always wins,
and the bundled defaults are the last-resort fallback:

1. `<workdir>/.kin/commands/`
2. `<workdir>/.claude/commands/`
3. `~/.kin/commands/`
4. `~/.claude/commands/`
5. the bundled defaults shipped with kin

The file stem is the command name — `review-pr.md` becomes `/review-pr`. The
name must match `^[a-z][a-z0-9-]*$`. The cache is refreshed when the UI mounts
and after `/clear`, so dropping in a new file mid-session takes effect on the
next restart (or after `/clear`).

### Frontmatter schema

```markdown
---
name: review-pr              # advisory; the filename stem is canonical
description: Review a PR.     # required; capped at 160 chars (the menu width)
argument-hint: "<branch>"    # optional; shown in /help
kind: prompt                 # required
---
Review the changes on branch $1 and summarize the risks.
```

| Field | Required | Notes |
|-------|----------|-------|
| `name` | no | Advisory only; the filename stem is canonical. A mismatch warns and the stem wins |
| `description` | yes | Shown in the menu and `/help`; truncated to 160 characters |
| `argument-hint` | no | A short usage hint shown next to the command in `/help` |
| `kind` | yes | `prompt` for a custom command (the body is sent as a turn), or `workflow` for a saved workflow script (the body is an `async def main()` — see below). The built-in handler kinds — `clear`, `help`, `mode`, `plan`, `model`, `theme`, `compact`, `resume`, `detach`, `list-skills`, `list-mcp`, `reload`, `tokens`, `export`, `fork`, `editor`, `rewind`, `retry`, `grants`, `github`, `tree`, `view`, `providers`, `routes`, `workflows`, `nudges`, `effort`, `spinner`, `settings`, `cost`, `workflow-save`, `interrupt`, `exit` — are also valid and re-bind that built-in |

A file missing a `description`, or with an unknown `kind`, is skipped with a
warning rather than crashing the menu.

### `kind: prompt` and `$ARGUMENTS`

A `kind: prompt` command renders its markdown body and sends it as a user turn —
exactly as if you had typed the body yourself. Before sending, the body is
expanded:

- `$ARGUMENTS` is replaced with everything you typed after the command name.
- `$1`, `$2`, … are replaced with the individual whitespace-separated arguments.

So `/review-pr feature-x` runs the example above with `$1` set to `feature-x`.

> **Warning**
>
> A discovered command file is trusted like the rest of the project's code.
> Its `kind: prompt` body is sent to the model verbatim, with no provenance
> framing — a command dropped into a cloned repo's `.kin/commands/` can inject
> instructions. Invocation is always explicit, and any tool calls the model
> makes still pass through the permission gate, but treat custom commands from
> untrusted repos with the same care as any code you run.

### `kind: workflow` — saved workflow scripts

A `kind: workflow` command's body is a Python `async def main()` orchestration
script (the same script the [`workflow` tool](/docs/kin/guide/workflows/) runs). You don't
hand-write these — run a `/workflow`, then `/workflow-save <name>` writes the most
recent successful run's script to `<workdir>/.kin/commands/<name>.md` for you.
kin ships nine bundled, ready-to-run examples: `/critique <target>`
(a correctness/perf/maintainability review), `/security-review <target>`
(an attack-path-disclosing security audit),
[`/deep-research <question>`](/docs/kin/guide/deep-research/) (a multi-lane **web**
research loop with a citation-liveness gate), `/research <question>`
(its **local** sibling — a codebase/repo fan-out that scales 1–5
read-only explorer lanes to the question's complexity and synthesizes
from [artifact handles](/docs/kin/guide/workflows/#the-artifact-store-publish-ref-handles)),
`/revise <task>` (a rubric-graded draft → grade → revise loop, bounded
rounds, graders read each published draft by ref) — all five
`kind: workflow` — and four `kind: prompt` commands, including the identical
`/beam` and `/handoff` handoff pair:
`/init [focus-hint]` (AGENTS.md scaffolding that fans out parallel
`explorer` subagents for multi-subsystem repos) and
`/memory [init]` (curate [persistent memory](/docs/kin/guide/memory/#memory-capture-at-session-end) —
reflect on the conversation, or bootstrap an initial memory set from the
repo's docs with `init`). The
`kind: workflow` commands run fixed scripts through the normal workflow
path (the ASK gate + AST filter apply on every invocation) — see
[Workflows](/docs/kin/guide/workflows/#save-a-run-as-a-reusable-command) for what they
do.

```markdown
---
description: review every changed file, one finding per line
kind: workflow
---
async def main():
    files = args.split() or ["README.md"]
    findings = await parallel([lambda f=f: agent(f"Review {f}; one finding per line") for f in files])
    return "\n".join(x for x in findings if x)
```

Invoking `/<name> <text>` **re-runs the saved script** through the real `workflow`
tool path — so the script you (and the menu) see is approved at the **ASK gate on
every invocation**, and the same AST filter applies. Re-running a saved workflow is
no more privileged than the original run.

- **No `$ARGUMENTS` substitution.** Unlike `kind: prompt`, the body is the script
  *verbatim* — the text after `/<name>` is exposed to the script as a plain `str`
  **global named `args`** (read it like a variable, e.g. `args.split()`). It is
  passed as data, never spliced into the script source — splicing user text into
  code would be an injection hole the structural AST filter couldn't catch. `args`
  defaults to `""` when you invoke the command with no text.
- The distilled result appears in the transcript's workflow card; like any
  `workflow`, only `main()`'s returned string is the deliverable.
