Anthropic, OpenAI and GitHub Copilot use OAuth flows. Every other provider in the model database takes an API key.
kit auth login [provider] # Start OAuth flow (e.g., anthropic) or prompt for an API key
kit auth login groq # Prompt for a Groq API key (hidden input)
kit auth login openrouter --api-key sk-or-... # Store a key without prompting
kit auth login [provider] --set-default # Set provider's default model as system default
kit auth logout [provider] # Remove credentials for provider
kit auth status # Check authentication status
Stored keys live in $XDG_CONFIG_HOME/.kit/credentials.json (defaults to
~/.config/.kit/credentials.json, mode 0600) and take precedence over the
provider’s environment variable (for example GROQ_API_KEY). The
environment variable is still used when no key is stored.
Kit starts even when the configured model has no key. The TUI shows a notice
and refuses to send prompts until you add a key with /connect (or switch
to a model whose provider has one with /model). One-shot prompts
(kit "question") still fail fast with the same error.
Manage the local model database that maps provider names to API configurations.
kit models [provider] # List available models (optionally filter by provider)
kit models --all # Show all providers (not just LLM-compatible)
kit update-models [source] # Update model database
The update-models command accepts an optional source argument:
embedded — reset to the bundled databaseKit records the schema version of the on-disk cache. When Kit’s binary
understands catalog fields the cache was written without — reasoning options,
long-context pricing tiers, deprecation status — the older cache is ignored
in favour of the embedded snapshot, so a stale cache never masks metadata the
current binary can use. Run kit update-models once to rewrite the cache in
the current schema.
kit extensions list # List discovered extensions
kit extensions validate # Validate extension files
kit extensions init # Generate example extension template
kit install <git-url> # Install extensions from git repositories
kit install -l <git-url> # Install to project-local .kit/git/ directory
kit install -u <git-url> # Update an already-installed package
kit install --uninstall <pkg> # Remove an installed package
kit install --all # Install all extensions without prompting
Kit implements the Agent Skills format. A skill is a directory with a SKILL.md file (YAML frontmatter + Markdown instructions) and optional scripts/, references/, and assets/ subdirectories.
kit skill list # List discovered skills with scope, path and spec warnings
kit skill validate <path> # Validate a skill directory / SKILL.md against the spec
kit skill install # Install the Kit skills (kit-extensions, kit-sdk) via skills.sh
kit skill # Same as "kit skill install"
kit skill list honors --skill, --skills-dir, --no-skills and --bare, and never prompts for project trust (it is read-only). kit skill validate accepts a SKILL.md file, a skill directory, or a directory of skills; errors (missing name/description) make the exit code non-zero, while warnings (name format, length limits, name/directory mismatch, body over 500 lines) are informational.
Skills load in three tiers, following the spec’s progressive-disclosure model:
name, description and location in an <available_skills> block in the system prompt.SKILL.md body is loaded when a skill is activated, either by the model (the activate_skill tool, or a read of the listed location) or by you.<skill_resources> block and read on demand.To activate a skill yourself, type its name as a slash command, optionally followed by a request:
/pdf-processing extract the tables from report.pdf
The / autocomplete popup lists every loaded skill that is not shadowed by another slash command (see precedence below) with a [skill] badge next to it — hidden-from-model skills included, since hiding only affects the model-facing catalog (prompt templates show [prompt], extension commands [ext], MCP prompts [mcp]). Kit wraps the skill body in a <skill_content> block, appends your text, and sends it as the turn. Activated skill content is protected from /compact pruning.
Slash-name precedence is: built-in commands, extension commands, MCP prompts (/server:prompt), prompt templates, then skills. A skill whose name is already taken is left out of the popup and a warning is logged, so rename one side if that happens.
Control which skills are loaded at startup:
# Load a specific skill file
kit --skill path/to/skill.md "prompt"
# Load multiple skill files or directories (flag is repeatable)
kit --skill ./skill1.md --skill ./skill2.md "prompt"
# Scan a directory directly for skills (overrides auto-discovery)
kit --skills-dir /path/to/skills "prompt"
# Hide a skill from the model catalog by name (still usable via /<name>)
kit --skill-disable noisy-skill "prompt"
# Disable all skill loading (auto-discovery and explicit)
kit --no-skills "prompt"
Skills follow the agentskills.io convention. They are auto-discovered from four canonical scopes:
| Scope | Location |
|---|---|
| User-level (cross-client) | ~/.agents/skills/ |
| User-level (Kit) | ~/.config/kit/skills/ (honors $XDG_CONFIG_HOME) |
| Project-local (cross-client) | <project>/.agents/skills/ |
| Project-local (Kit) | <project>/.kit/skills/ |
Entries in these directories may be symlinks — for example, skill directories linked in by a dotfile manager such as home-manager or GNU Stow. Kit follows the link to a skill directory or a .md/.txt file, and silently skips a broken link.
When two skills share the same name, the project-level one takes precedence over the user-level one. Use --skills-dir to scan one directory directly instead (it is not treated as a parent of .agents/.kit — the directory itself is scanned). --skill loads files explicitly (which disables auto-discovery), and --no-skills suppresses all skill loading regardless of other flags.
Disabled skills (--skill-disable, the skill-disable config key, or disable-model-invocation: true in a skill’s frontmatter) are hidden from the model-facing <available_skills> catalog but remain available for explicit activation via the /<name> slash command.
A skill is a markdown file (SKILL.md in a directory, or a standalone .md/.txt file) with optional YAML frontmatter. Kit reads the full agentskills.io field set plus two Kit-specific extensions:
---
name: pdf-extractor # required; lowercase, digits, single hyphens; must match the directory
description: Use when extracting tables from PDFs # required (drives model discovery)
license: MIT # optional, SPDX identifier
compatibility: Requires python3 and pdftotext # optional, environment requirements (max 500 chars)
allowed-tools: Read Bash(pdftotext:*) # optional (experimental); parsed, not enforced by Kit
disable-model-invocation: false # optional; true hides from the catalog
metadata: # optional arbitrary string key/value pairs
author: you
tags: [pdf, data] # Kit extension
when: on-demand # Kit extension
---
name and description are required — a skill missing its description is skipped with a logged warning, since the description is the sole basis on which the model decides relevance. Other spec constraints (name is 1–64 chars of a-z0-9- with no leading/trailing/double hyphen and matches the parent directory; description ≤ 1024 chars; compatibility ≤ 500 chars; body under 500 lines) are checked leniently: the skill still loads, and the deviation is reported by kit skill list / kit skill validate. Descriptions are XML-escaped before they enter the catalog, so characters like <, >, and & are safe. A skill directory may bundle scripts/, references/, and assets/ subdirectories; when a skill is activated those files are enumerated in a <skill_resources> block so the model knows what it can read.
Because project-local skills are injected into the system prompt, entering a repository that ships .agents/skills/ or .kit/skills/ for the first time prompts you to trust it before any project skill loads — a safeguard against a freshly cloned, untrusted repo smuggling instructions into the agent:
This project provides 2 skills under .agents/skills or .kit/skills:
/path/to/repo
Load them into the agent? [t]rust always / [o]nce / [s]kip (default skip):
Choosing trust always persists the directory to ~/.config/kit/trusted-projects.json so you are not asked again. The prompt is skipped (skills load silently) in non-interactive runs — when a prompt is passed positionally, --quiet is set, or stdin is not a TTY.
Scaffold a GitHub Actions workflow that runs Kit as an automated collaborator/reviewer. The workflow triggers when someone comments /kit ... on an issue or pull request review, runs the agent non-interactively in the runner, and lets it respond.
kit github install # Scaffold .github/workflows/kit.yml
kit github install --model anthropic/claude-sonnet-4-5-20250929 # Skip the model prompt
kit github install --force # Overwrite an existing workflow file
kit github install --no-secret # Skip the offer to set the provider secret via the gh CLI
By default the command prompts for the model (pre-filled with a sensible default). If the gh CLI is detected on your PATH and the provider API key is present in your environment, you’ll be offered the option to store it as a repository secret automatically.
The generated workflow:
issue_comment and pull_request_review_comment (types: [created])./kit command token.author_association).permissions and persist-credentials: false.secrets.GITHUB_TOKEN and the provider via a repository secret (e.g. ANTHROPIC_API_KEY).CI trust: Trigger restrictions control who can start a run. They do not make all issue/PR content trusted or confine tool calls. Use an isolated, disposable runner, minimal token permissions, and only required credentials. Do not expose unrelated secrets or host access. See Tool execution and trust.
After committing the workflow and setting the provider secret, comment /kit <your request> on any issue or pull request to trigger Kit.
The generated workflow uses the bundled mark3labs/kit composite action, which installs the Kit binary and runs kit github run. That command reads the triggering event, enforces permissions, reacts with an emoji, runs the agent against the issue thread or PR, posts the response as a comment, and — if the agent changed files — pushes a kit-agent[bot] branch and opens a pull request.
| Flag | Description |
|---|---|
--model |
Provider/model to write into the workflow |
--force |
Overwrite an existing workflow file |
--no-secret |
Skip the offer to set the provider secret via the gh CLI |
These commands are available inside the Kit TUI during an interactive session:
| Command | Description |
|---|---|
/help |
Show available commands |
/tools |
List available MCP tools |
/servers |
Show connected MCP servers |
/model [name] |
Switch model or open model selector. The selector lists every model in the catalogue; models whose provider has no credentials are dimmed and cannot be selected — use /connect to add a key. Search ranks by match quality alone, so dimmed models stay findable (e.g. type openrouter/sonnet). |
/connect [provider] |
Add an API key for a provider. Opens a searchable provider list, then a masked key input. The key is saved to the credentials file and the active model is reconnected when it belongs to that provider. /connect groq skips the list. Alias: /login. |
/theme [name] |
Switch color theme. Running with no argument opens a modal picker showing every built-in and user theme. |
/thinking [level] |
Set thinking level. Running with no argument opens a modal picker showing only the levels the current model accepts; passing a model-specific effort switches directly, reporting any substitution. Catalog choices can include xhigh, max, and future names. off omits effort; none is literal. |
/compact [focus] |
Summarize older messages to free context |
/subagents |
Open the read-only subagent inspector on the newest retained run. Use Ctrl+Alt+A to pick a run. Replaces /subagent-sessions and /agents; extensions cannot override this command. |
/kill-subagent |
Open a picker of the running subagents and stop the selected one. The parent agent is told that the user killed it. Alias: /ks. |
/clear |
Clear conversation |
/clear-queue |
Clear queued messages |
/usage |
Show token usage |
/reset-usage |
Reset usage statistics |
/shortcuts |
List keyboard shortcuts registered by extensions |
/reload-ext |
Hot-reload all extensions from disk (alias: /re) |
/tree |
Navigate session tree |
/fork |
Fork to new session from an earlier message |
/new |
Start a new session (creates new session file) |
/name [name] |
Set or show session display name |
/resume |
Open session picker to switch sessions (alias: /r) |
/session |
Show session info |
/export [path] |
Export session as JSONL (default: auto-generated path) |
/import <path> |
Import a session from a JSONL file |
/share |
Upload session to GitHub Gist and get a shareable viewer URL |
/copy |
Copy the last message to the clipboard (alias: /cp) |
/quit |
Exit Kit |
Use ↑ and ↓ arrow keys to navigate through previously submitted prompts. Kit keeps the last 100 entries. Consecutive duplicates are skipped.
Drag with the mouse over the conversation to select text. Double-click selects a word, triple-click a line. Kit copies the selection when you release the button. The selection stays highlighted, and the status bar shows how many characters Kit copied. Both disappear at the next key, paste or click, or when the text under the selection changes, for example after a resize.
Kit writes the copy to the system clipboard, on Linux with wl-copy, xclip or xsel. It sends the same text to the terminal as an OSC 52 sequence. On Linux and the BSDs, Kit also sets the primary selection, so a middle click in another window pastes the text. If Kit cannot write the system clipboard, it tells you once, with the reason and the tool to install. The status bar also says so after a copy with the mouse or in message navigation. Without a display, for example over SSH, there is no system clipboard to write. The copy then depends on OSC 52, and Kit reports nothing.
In most terminals, holding Shift while you drag uses the terminal’s own selection instead. To copy a whole message, use /copy for the last one, or press Ctrl+X m, move to the message and press y.
Press ESC twice to cancel the current operation:
This ensures that tool_use and tool_result messages are always sent to the API as matched pairs, avoiding errors from orphaned tool calls.
Press Ctrl+X e to open your $VISUAL or $EDITOR in a temporary file pre-populated with the current input text. On save and quit, the edited content replaces the input textarea. On error exit (e.g., :cq in Vim), the original input is preserved.
Press Ctrl+X s during streaming to inject a system-level instruction mid-turn. This allows you to steer the conversation direction without waiting for the model to finish:
Example: While the model is writing code, press Ctrl+X s and type “Use async/await instead” to change the implementation approach.
Attach images to your next prompt straight from the clipboard:
When a terminal supports color, Kit renders a small low-resolution thumbnail preview of each pending image directly in the input, below the [N image(s) attached] indicator, so you can confirm the right image was attached before sending.
Kit probes the terminal at startup and draws the preview the best way it actually supports. A terminal that answers the Kitty graphics protocol gets a real image; anything else gets a thumbnail built from Unicode half-block characters and ordinary terminal colors, which renders correctly everywhere. Thumbnails are capped to a small cell box for a glanceable, low-res look.
Detection is a live query rather than a guess from $TERM, because a multiplexer can forward the query to the terminal behind it and appear to support graphics it cannot draw:
COLORTERM=truecolor); Kit degrades to 256-color where truecolor is unavailable.[N image(s) attached] text indicator is shown alone.Set KIT_IMAGE_PROTOCOL=kitty to force the graphics protocol, or KIT_IMAGE_PROTOCOL=halfblock to force half blocks, when the probe gets it wrong.
You can also attach image files by referencing them with @path/to/image.png — binary files are auto-detected by MIME type. See Quick Start for the @ attachment syntax.
In a remote session (kit remote --host <name>), Ctrl+V attaches an image from the local machine’s clipboard: it is streamed to the host over the tunnel and attached to the session with the same thumbnail preview. The clipboard tools only need to exist on the machine you are typing on. See Remote sessions.
Templates use YAML frontmatter for metadata and support argument placeholders:
---
description: Review code for issues
---
Review the following code for bugs and security issues.
Focus on $1 specifically.
Save to ~/.kit/prompts/review.md or .kit/prompts/review.md.
Templates appear as slash commands, tagged [prompt] in the autocomplete popup:
/review error handling
A template and a skill with the same name cannot both be reached: the template wins and the skill is left out of the popup with a logged warning.
| Placeholder | Description |
|---|---|
$1, $2, etc. |
Individual arguments by position |
$@, $ARGUMENTS |
All arguments joined with spaces (zero or more) |
$+ |
All arguments joined with spaces (one or more required) |
${@:N} |
Arguments from position N onwards |
${@:N:L} |
L arguments starting at position N |
Placeholders inside fenced code blocks ( `) and inline code spans are ignored, so documentation examples won’t be substituted.
# Load a specific template by name
kit --prompt-template review
# Disable template loading
kit --no-prompt-templates
Run Kit as an ACP (Agent Client Protocol) agent server. ACP-compatible clients communicate with Kit over JSON-RPC 2.0 on stdin/stdout.
kit acp # Start as ACP agent
kit acp --debug # With debug logging to stderr
kit acp -m anthropic/claude-sonnet-4-5 # Default model for new sessions
kit acp --approval auto_edit # Edit files without asking; ask before commands
Kit implements ACP protocol version 1. It supports session/new,
session/load (with history replay), session/resume, session/list,
session/close, and session/cancel. Each session uses the cwd that the
client sends as the base directory of the file and shell tools. MCP servers
that the client sends in mcpServers (stdio, HTTP, or SSE) are connected in
addition to the servers in your config. Clients can change the approval,
model and thinking_level config options with session/set_config_option.
Before a tool that can change something runs (edits, commands, subagents,
MCP and extension tools), Kit asks the client with
session/request_permission. The --approval flag sets the default mode:
ask (default), auto_edit (edit files without asking), or auto (never
ask). Read-only tools never ask.
When the client supports them, Kit reads and writes files through the
client (fs/*), so it sees unsaved editor buffers, and runs shell commands
in client terminals (terminal/*). Prompt templates and skills are sent to
the client as slash commands. The model can show its plan with the
update_plan tool.
Run Kit inside a session that survives closing your terminal, and switch between several of them like tmux or zellij. Sessions are hosted by a background daemon. See Remote sessions for the full picture.
When the daemon is running, plain kit is already detachable. There
is no separate command to learn: the session starts in the directory you
ran it from, with the arguments you gave it.
kit daemon service install # Start the daemon once (systemd user service)
cd ~/project && kit # A detachable session, right here
# Ctrl+] d # Detach; the agent keeps working
kit attach # Come back to it
Kit falls back to running in your terminal when no daemon is running, for
a one-shot prompt (kit "..."), for --quiet/--json, when stdin or
stdout is not a terminal, and for --no-daemon. See Detachable by
default for the exact
rule and the daemon-mode setting.
kit attach is the command for choosing which session — going back to
one, or starting one somewhere else. It starts a daemon automatically if
none is running.
kit attach # Pick a live session (local or paired host), or start one
kit attach 3 # Attach straight to session 3
kit attach --new # Skip the picker, start a new session
kit attach --host homelab # Attach on a paired remote host
kit attach --all # Pick across paired hosts without starting a local daemon
kit ls # List live sessions on this machine
kit ls --all # Include sessions on every paired host
kit --no-daemon # Run in this terminal, daemon or no daemon
The kit attach picker lists this machine’s sessions and those on
every paired host, grouped by host name, so it is the one command that
shows everything you can attach to. Querying those hosts costs up to eight
seconds when one is asleep (in parallel, so eight seconds total); --new
and kit attach <id> skip it, because neither opens a picker.
Where a new session starts depends on how you asked for it:
| How you started it | Working directory |
|---|---|
kit |
Where you ran it — no picker |
Ctrl+] c |
The same directory as the session you were in |
kit attach, kit attach --new |
The directory picker, opened where you ran it |
A remote client (kit remote --host) |
The directory picker, opened in the host’s home directory |
A remote client never sends a directory: it names nothing that exists on
the host. --new skips the session picker, not the directory one.
You can also run the directory picker outside a session with
kit --pick-dir; the daemon uses that same flag whenever a
session has no directory to start in.
Inside a session, Ctrl+] is the multiplexer prefix:
| Chord | Action |
|---|---|
Ctrl+] d |
Detach; the session keeps running |
Ctrl+] s |
Switch to another session |
Ctrl+] c |
Start a new session, in the same directory |
Ctrl+] n / Ctrl+] p |
Next / previous session |
Ctrl+] w |
Switch across paired hosts |
Ctrl+] Ctrl+] |
Send a literal Ctrl+] to the session |
The prefix is deliberately not Ctrl+X: that belongs to the session itself
(steering, external editor), so
the keymap is identical whether Kit runs locally or through a session.
Ctrl+X d still detaches too, kept for compatibility with earlier
releases.
Sessions survive a client disconnect, but not a restart of the hosting daemon — see Sessions and daemon restarts.
A session renders into your terminal but is spawned by the daemon, so the
client forwards its TERM, COLORTERM and background color when it
attaches — otherwise a session would inherit the daemon’s environment and
render a truecolor theme in the wrong palette. See Terminal and
colors.
A local client also forwards its working directory and an allowlist of
environment variables — PATH, HOME, SHELL, EDITOR, the locale,
proxy settings and the provider credentials — so a hosted session finds
the same tools and keys your shell has. Remote clients never do.
Run Kit as a daemon on one machine and attach to it from another over an end-to-end encrypted iroh connection. All work runs on the daemon host; see Remote sessions for the full picture.
# On the host
kit daemon # Host sessions for paired clients (Ctrl+C stops)
kit daemon pair # One-time pairing: show code, confirm on this terminal
kit daemon pair --list # List paired clients (fingerprints)
kit daemon pair --revoke <fp> # Revoke a client
kit daemon status # Endpoint, paired clients, active sessions
kit daemon service install # Install + start the systemd user service
kit daemon service remove # Stop and uninstall the service
# On the client (first time — the host terminal asks you to accept)
kit remote --pair A1B2C3D4 # Pair and save the host under a name
# On the client (any time after)
kit remote --host homelab # Attach to the paired host
kit attach --host homelab # Same, with session switching (Ctrl+] s)
kit remote --list # List paired hosts
kit remote --forget homelab # Forget a saved host
Pairing is one-time and human-approved: the code only works while the
kit daemon pair window is open, and the host must accept the request on
its terminal. After pairing, the client authenticates with its own signing
key — no code involved — and the host can revoke it at any time. Each
client picks a working directory and gets a private session; multiple
clients can hold sessions at the same time and /quit closes only that
client’s connection. Ctrl+] d detaches (Ctrl+X d still works, for
compatibility) — the session keeps running on the
host and can be reattached later (or shared by several clients at once, with
every attached terminal mirroring the same screen). Only one daemon may run
per user.