Skip to content

Slash Commands

Daniel Ellison edited this page Sep 3, 2026 · 1 revision

Slash Commands

Every Kai feature is accessible through a Telegram slash command. This page is the authoritative reference for all commands, their subcommands, arguments, and behavior.

How commands work

Commands are handled by Kai's bot process, not by the agent. When you send /new, Kai restarts the subprocess directly - the agent never sees the message. Only regular text messages (and file/photo/voice attachments) are passed through to the agent.

Authorization: All commands except /start require you to be in users.yaml. Unauthorized users get no response. When TOTP is configured, every command except /start and /help additionally sits behind the authentication gate; an expired session prompts for a code first.

Persistence: Settings written via commands are canonical: Telegram and the Workshop browser client mutate the same stored state, so a model change here shows up there and vice versa. The precedence chain for any setting is: runtime settings > users.yaml > install defaults.

Aliases: /ws is a full alias for /workspace. Every subcommand works identically.


Session commands

/start

Sends the initial greeting. This is the only command that does not require authorization - it responds to anyone so new users know the bot is alive.

/start
→ Kai is ready. Send me a message.

/new

Kills the current agent subprocess and starts a fresh session, clearing the session record from the database.

Use this when the conversation context has grown unwieldy, when the agent is stuck in a bad state, or when you want a clean slate without changing any other settings.

/new
→ Session cleared. Starting fresh.

/stop

Aborts the current response mid-stream. Sets the per-chat stop event (checked by the streaming loop) and immediately kills the Claude subprocess. The in-progress Telegram message gets "(stopped)" appended.

/stop
→ Stopping...

Note: the bot uses concurrent_updates=True, which is what makes /stop reachable while Claude is streaming. Without it, the stop message would queue behind the current response.


Model commands

/model <name>

Switches the active model immediately. The choice persists to the database and survives restarts. Also restarts the subprocess and clears the session (model is a CLI flag baked in at process start).

Valid model names depend on your configured provider:

  • Anthropic (Claude backend): haiku, sonnet, opus
  • OpenAI (Goose backend): gpt-5.4, gpt-5.4-mini, gpt-5.4-nano
  • Google (Goose backend): gemini-3.1-pro, gemini-3-flash, gemini-3-deep-think
  • openrouter / ollama: any model ID your provider supports
/model sonnet
→ Model set to ⚡ Sonnet. Session restarted.

/model badname
→ Choose: opus, sonnet, or haiku

/models

Shows an inline keyboard for model selection. The current model is highlighted with a green circle. Tapping a different model is equivalent to /model <name>. Tapping the current model dismisses the keyboard with "No change."

For open-ended providers (openrouter, ollama), no keyboard is shown. Instead, the current model ID is displayed with a prompt to use /model <id> to switch to any model your provider supports.


Backend commands

/backend [backend:provider]

Shows your current backend, or switches it. Switching is bounded by the runtime options the operator granted on your runtime profile; a backend outside your grants is rejected. Multi-provider backends take the backend:provider form.

/backend
→ Backend: claude (anthropic)
/backend codex
→ Backend set to codex. Session restarted.

/backends

Inline keyboard listing your granted backend and provider options; tap to switch.


Personalization commands

/preferences [show|set <text>|history|restore <n>]

Your personal PREFERENCES.md: the standing guidance injected into every session. show prints it, set replaces it (revisioned; concurrent edits are detected), history lists prior revisions, and restore <n> brings one back without losing the current text. The same document is editable in Workshop Settings.

/notifications

Your notification delivery controls: adapters lists per-adapter toggles (adapter <n> on|off flips one), channels shows per-channel levels, muted-mentions toggles the direct-mention override, dnd manages the do-not-disturb window, and /notifications <github|generic> [number|reset] picks the destination channel per integration class. See GitHub Notification Routing.

/project [register [name]|unregister <name>]

Manages the memory project registry: which project the current workspace's memories belong to. register adds the current workspace (or a named entry), unregister removes one. /workspace new registers its directory automatically. See Memory.


Settings commands

Global per-user settings. These are your defaults across all workspaces. Workspace-specific overrides are set separately with /workspace config.

/settings

Shows your current settings with source attribution for each field - whether the value comes from your database override, users.yaml, or the global default.

/settings
→ Your settings:
    Model: sonnet (user override)
    Provider: anthropic
    Timeout: 120s (global default)

The "Provider" line shows your effective LLM provider (derived from backend and provider in your config). This is always displayed so you know which backend you are on.

/settings model <name>

Sets your default model. Same effect as /model - persists, restarts the subprocess, clears the session. On canonical runtimes the name validates against the model catalogue for your backend, so what the picker offers tracks what the backend actually serves.

/settings model opus
→ Default model set to 🧠 Opus. Session restarted.

/settings timeout <seconds>

Sets how long Kai waits for the agent to respond before giving up. Must be a positive integer. The upper bound comes from your protected runtime profile; the legacy 600-second cap applies only on compatibility paths without one.

/settings timeout 300
→ Default timeout set to 300s.

Takes effect immediately on any running subprocess.

/settings reset [field]

Clears your database override for the specified field, reverting it to the users.yaml value or global default. Omitting the field name resets everything.

Valid field names: model, timeout

/settings reset timeout
→ timeout reset to default.

/settings reset
→ All settings reset to defaults.

Always restarts the subprocess, even for fields (timeout) that could take effect without one. This simplicity is intentional.


Workspace commands

Workspaces are directories where Claude operates. Switching workspaces changes Claude's working directory and restarts the subprocess. Each workspace can have its own model, timeout, env vars, and system prompt (set via /workspace config).

/ws is a full alias for /workspace.

/workspace

Shows your current workspace - the short name and the full absolute path.

/workspace
→ Workspace: kai
   /Users/kai/Projects/kai

/workspace <name>

Switches to a workspace by short name. Resolution order:

  1. workspace_base/<name> - if a base directory is configured and the subdirectory exists
  2. The allowed workspace list - matched by directory name

Absolute paths and ~ are rejected. If the name is ambiguous (exists in both base and allowed list), the base directory wins.

/workspace my-app
→ Switched to my-app. Session cleared.

/workspace home

Switches to your home workspace (the home_workspace in users.yaml, or CLAUDE_WORKSPACE globally). Always allowed regardless of access restrictions.

/workspace home
→ Switched to Home. Session cleared.

/workspace new <name>

Creates a new directory under workspace_base, runs git init inside it, and switches to it. Requires workspace_base to be configured (in users.yaml or WORKSPACE_BASE env var).

The name must not contain path separators.

/workspace new my-project
→ Created my-project. Session cleared.

/workspace allow <path>

Adds an absolute path to your personal allowed workspace list, stored in the database. The path must exist and be a directory. Paths already covered by workspace_base are silently rejected (they're already accessible).

/workspace allow /home/alice/client-work
→ Added: /home/alice/client-work

/workspace allow /Users/kai/Projects
→ Already covered by your workspace base:
   /Users/kai/Projects

/workspace deny <path>

Removes a path from your personal allowed workspace list. Only paths you added via /workspace allow can be removed; globally-configured paths (from ALLOWED_WORKSPACES or admin config) cannot be removed via Telegram.

/workspace deny /home/alice/client-work
→ Removed: /home/alice/client-work

/workspace allowed

Lists all workspaces you can access, with source attribution for each entry.

/workspace allowed
→ Workspace base: /Users/kai/Projects

   Allowed workspaces:
     /Users/kai/extra-repo  (you)
     /opt/shared-docs       (global)

If neither a base nor any allowed paths are configured, all directories are accessible (permissive mode).

/workspaces

Shows an inline keyboard of your recent workspaces. The top button is always Home; the rest are drawn from your workspace history. Tapping your current workspace dismisses the keyboard with "No change." Stale entries (directories that no longer exist or are no longer allowed) are removed automatically when you tap them.

/workspace config

Shows the effective configuration for your current workspace, with source attribution for each field.

/workspace config
→ Config for kai:
    Model: opus (workspace override)
    Timeout: 120s (global default)
    Env vars: GITHUB_TOKEN, DEBUG
    Prompt: You are working on the Kai project... (workspace override)

Source labels follow the full precedence chain: workspace override (set via /workspace config) > workspaces.yaml > user setting (set via /settings) > users.yaml > global default.

Env var keys are shown but values are never displayed (they may contain secrets).

/workspace config model <name>

Sets the model for the current workspace only. Overrides your global /settings model when in this workspace.

/workspace config model haiku
→ Model set to haiku.

/workspace config timeout <seconds>

Sets the response timeout for the current workspace.

/workspace config timeout 60
→ Timeout set to 60s.

/workspace config env KEY=VALUE

Sets an environment variable that is injected into Claude's subprocess when working in this workspace. Useful for workspace-specific API keys or flags.

/workspace config env GITHUB_TOKEN=ghp_xxxx
→ Set GITHUB_TOKEN.

Remove a variable: Prefix the key with -

/workspace config env -GITHUB_TOKEN
→ Removed GITHUB_TOKEN.

List variables: Omit the value

/workspace config env
→ Workspace env vars:
    GITHUB_TOKEN
    DEBUG

/workspace config prompt [text]

Sets a system prompt appended to Claude's instructions when working in this workspace. Useful for project-specific context (coding standards, architecture notes, personas).

/workspace config prompt You are working on the Kai project. All code must be thoroughly commented.
→ Prompt set.

Clear the prompt:

/workspace config prompt clear
→ Prompt cleared.

You can also send a text file as an attachment with the command in the caption - useful for long prompts that would be awkward to type in Telegram.

/workspace config reset [field]

Clears the workspace config override for a specific field, reverting to workspaces.yaml or the global default. Omitting the field name clears everything.

Valid field names: model, timeout, env, prompt

/workspace config reset model
→ model reset to default.

/workspace config reset
→ All workspace config cleared. Using global defaults.

GitHub commands

Commands for managing GitHub webhook subscriptions, notification routing, and agent feature toggles. The full settings surface is displayed by /github with no arguments.

/github

Shows your current GitHub configuration: notification destination, subscribed repos (with source attribution), feature toggle states, and token status.

/github
→ GitHub settings:
   Notifications: this chat
   PR reviews: on (global default)
   Issue triage: off (users.yaml)

   Subscribed repos:
     dcellison/kai  (users.yaml)
     dcellison/other-repo  (added via /github add)

   GitHub token: stored

/github add <owner/repo>

Subscribes you to webhook events from owner/repo. If a GitHub token is stored, Kai registers the webhook on the repository automatically. If not, it prints the webhook URL and a manual cURL command for you to run.

/github add dcellison/new-project
→ Subscribed to dcellison/new-project. Webhook registered.

/github add dcellison/new-project  (no token stored)
→ Subscribed to dcellison/new-project.
   Register the webhook manually:
   URL: https://<your-kai-host>/webhook/github
   ...

If you previously removed the repo via /github remove, adding it again un-removes it (clears the remove entry) rather than creating a duplicate add entry.

/github remove <owner/repo>

Unsubscribes you from owner/repo. If no other users are subscribed to that repo and a token is stored, Kai removes the webhook from GitHub automatically.

/github remove dcellison/old-project
→ Unsubscribed from dcellison/old-project. Webhook removed.

For repos in your users.yaml baseline, the removal is stored as a delta override in the database. The users.yaml file is not modified. If the admin later removes the repo from users.yaml, the delta is redundant but harmless.

/github token <value>

Stores a GitHub personal access token for automatic webhook registration and removal. The token is saved in the database and never echoed back or written to logs.

Required token scope: admin:repo_hook (or write:repo_hook if you don't need deletion). For organization repos, the token owner must have admin access to the repo.

/github token ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
→ GitHub token stored.

/github token clear

Removes your stored GitHub token. Does not affect existing webhooks.

/github token clear
→ GitHub token removed.

/github notify [number]

Chooses which canonical destination channel receives your GitHub notifications. With no argument it lists your available destinations as a numbered list; pick one by number. Raw chat IDs are rejected; destinations are channels, not chats.

/github notify
→ 1. GitHub feed (current)
  2. Direct channel
/github notify 2
→ GitHub notifications will go to Direct channel.

/github notify reset

Restores your GitHub destination to the operator's protected policy.

/github reviews on|off

Enables or disables the PR review agent for your account (the users.yaml pr_review field is the admin baseline; there is no global env toggle). The same switch lives in Workshop Settings.

/github reviews off
→ PR reviews disabled.

/github triage on|off

Enables or disables the issue triage agent for your account, same model as reviews.

/github triage off
→ Issue triage disabled.

/review <pr-number> / /review <owner/repo> <pr-number>

Runs a PR review on demand (repository inferred from your subscriptions when omitted). The result comes back to you as a document attachment; no GitHub comment is posted. See PR Review Agent.


Voice commands

Voice output requires TTS_ENABLED=true in your environment. All voice commands return an error message if TTS is not enabled.

Three voice modes exist:

Mode Behavior
off Text only (default)
on Text message + voice note (both sent)
only Voice note only (no text)

/voice

Bare toggle: switches between off and only. Does not cycle through on - use /voice on explicitly if you want both text and audio.

/voice  (currently off)
→ Voice mode: ONLY (voice only) (voice: Nova)

/voice  (currently only)
→ Voice mode: OFF (voice: Nova)

/voice on

Enables text + voice mode. Both a text message and a voice note are sent for each response.

/voice off

Disables voice. Text only.

/voice only

Enables voice-only mode. No text is sent, only the audio file.

/voice <name>

Sets the TTS voice by name. If voice mode was off, it is automatically set to only. If mode was already on or only, it stays as-is.

/voice nova
→ Voice set to Nova. Voice mode: ONLY (voice only)

Run /voice with an invalid name to see the list of available voice names.

/voices

Shows an inline keyboard of all available TTS voices. Tapping a voice sets it and auto-enables voice mode to only if it was previously off. Same behavior as /voice <name> via the keyboard.


Memory commands

Kai's semantic memory layer (Mem0 + Qdrant) extracts facts from conversations and stores them with tags, confidence scores, and embeddings. The /memory command surface lets you browse, search, and prune these facts directly from Telegram. Memories are scoped per user by Telegram chat ID, so each user only sees and manages their own facts.

For the broader memory architecture, see System Architecture - Memory system.

/memory

Opens the memory dashboard: a one-line summary of how many extracted facts and episodes you have, plus a single utility row of inline buttons for browsing them. The row holds Facts (N) (when you have any extracted or migration rows), Episodes (N) (when you have any episode rows), and Stats (always). The Facts and Episodes buttons drill into a paginated list; tapping a row opens a detail view with full text, source, and confidence, plus per-record actions: Forget, a scope-change flow (move between global and project scope), and a source view showing the originating conversation.

/memory
→ Memory: 24 facts, 6 episodes.

  Tap Facts or Episodes to browse. Tap Stats for details.

  [Facts (24)] [Episodes (6)] [Stats]

There is no Search button on the dashboard - Telegram inline keyboards cannot accept free text. Use /memory search <query> for search. There is no tag-browse axis; tags are visible on individual rows but are not a primary browse surface.

/memory search <query>

Runs a semantic search across all your facts and returns the top matches. Search is vector-based, not keyword - phrasing the query as a question or rough description works as well as an exact phrase. Each result is tappable for the same detail view as the dashboard drill-down.

/memory search what coffee do I like
→ Top matches:
  • Prefers light-roast pour-over from Counter Culture (preferences, 0.87)
  • Drinks decaf after 2pm (preferences, 0.71)

/memory stats

Shows the total count of remembered facts plus the distribution of confidence scores (how certain Kai is about each fact). Useful for spot-checking whether the memory layer is accumulating noise or producing high-confidence extractions.

/memory stats
→ 24 facts
  Confidence: high (0.8+) 14 | medium (0.5-0.8) 7 | low (<0.5) 3

/memory help

Compact subcommand reference. Same content shown when an unrecognized /memory subcommand is typed.


Info and status commands

/stats

Shows your current session details: session ID (truncated), model in use, when the session started, when it was last used, and whether the Claude subprocess is alive.

/stats
→ Session: a3f91b2c...
   Model: sonnet
   Started: 2026-04-05 14:23:11
   Last used: 2026-04-05 17:44:02
   Process alive: True

If no session exists yet (no messages sent since last restart), reports "No active session."

/job

Unified command for managing scheduled jobs. Without arguments (or with list), shows all active jobs. Subcommands handle inspection and cancellation.

Aliases: /jobs works as a shortcut for /job list.

/job or /job list

Lists all your active scheduled jobs. Each job shows its ID, name, and schedule in human-readable form. Job type is indicated by an emoji: bell (reminder) or robot (Claude job).

/job
→ Active jobs:
   🔔 #3 Laundry reminder (once at 2026-04-06T19:00:00+00:00)
   🤖 #7 Daily weather (daily at 08:00 UTC)
   🤖 #12 Package tracker (every 1h)

/job info <id>

Shows full details for a specific job: type, schedule, auto-remove status, and the prompt text. You can only inspect your own jobs.

/job info 7
→ Job #7 - Daily weather
   Type: claude
   Schedule: daily at 08:00 UTC
   Auto-remove: no

   Prompt:
   Check the weather forecast for today and send me a summary.

/job cancel <id>

Permanently cancels a scheduled job. Removes it from the database and from APScheduler's in-memory queue. You can only cancel your own jobs.

/job cancel 7
→ Job #7 cancelled.

/job cancel 99
→ Job #99 not found.

Unknown subcommand

If you pass an unrecognized subcommand, Kai shows usage help:

/job blah
→ Usage:
  /job - List all jobs
  /job info <id> - Show job details
  /job cancel <id> - Cancel a job

/help

Prints a compact command reference. This page is the full reference; /help is the quick-lookup version for when you forget a specific syntax.

/webhooks

Shows the webhook server's status, port, and advertised endpoints, plus GitHub webhook setup instructions when configured. (The generic /webhook endpoint still exists when GENERIC_WEBHOOK_SECRET is set; this listing just no longer advertises it.)

/webhooks
→ Webhook server: running
   Port: 8080

   Endpoints:
     GET  /health
     POST /api/schedule
     POST /api/services/*
     POST /webhook/github

   GitHub setup:
   1. Set Payload URL to https://your-host/webhook/github
   ...

Quick reference

Command What it does
/start Initial greeting (no auth required)
/new Start a fresh session
/stop Abort the current response
/model <name> Switch model
/models Model picker keyboard
/backend [b:p] Show or switch backend within your grants
/backends Backend picker keyboard
/preferences ... Show, set, or restore your PREFERENCES.md
/notifications ... Adapters, levels, DND, destinations
/project ... Memory project registry
/review [repo] <pr> On-demand PR review, delivered as a document
/settings Show your settings
/settings <field> <value> Set model/timeout
/settings reset [field] Reset to default
/workspace Show current workspace
/workspace <name> Switch by name
/workspace home Go to home workspace
/workspace new <name> Create and switch
/workspace allow <path> Add to allowed list
/workspace deny <path> Remove from allowed list
/workspace allowed List all allowed workspaces
/workspace config Show workspace-specific settings
/workspace config <field> <value> Set per-workspace model/timeout/env/prompt
/workspace config reset [field] Reset workspace overrides
/workspaces Workspace picker keyboard
/ws Alias for /workspace
/github Show GitHub settings
/github add <owner/repo> Subscribe to repo
/github remove <owner/repo> Unsubscribe from repo
/github token <value> Store GitHub token
/github token clear Remove token
/github notify <chat_id> Route notifications to a group
/github notify reset Restore notifications to DM
/github reviews on|off Toggle PR review agent
/github triage on|off Toggle issue triage agent
/voice Toggle voice off/only
/voice on|off|only Set voice mode
/voice <name> Set voice (enables voice if off)
/voices Voice picker keyboard
/memory Browse facts and episodes (inline buttons)
/memory search <query> Semantic search over remembered facts
/memory stats Counts and confidence distribution
/memory help /memory subcommand reference
/stats Session cost and status
/job List scheduled jobs
/job info <id> Show job details
/job cancel <id> Cancel a job
/jobs Alias for /job list
/help Compact command reference
/webhooks Webhook server status

Clone this wiki locally