mirror of
https://github.com/mark3labs/kit.git
synced 2026-06-13 19:20:06 +00:00
7f366eab84
* cmd: add --no-skills, --skill, and --skills-dir CLI flags
The pkg/kit Options struct already had full backend support for skills
control (NoSkills, Skills []string, SkillsDir) wired into loadSkills()
in pkg/kit/kit.go, but there were no corresponding CLI flags to drive
them. This commit closes that gap.
Changes in cmd/root.go:
- Add three package-level flag variables alongside the existing
noExtensionsFlag/extensionPaths group:
noSkillsFlag bool
skillsPaths []string
skillsDir string
- Register three persistent cobra flags in init():
--no-skills disable skill loading (auto-discovery and explicit)
--skill <path> load a skill file or directory (repeatable)
--skills-dir <dir> override the project-local skills directory
used for auto-discovery
- Wire all three into the kitOpts struct literal in runNormalMode()
so they flow directly into kit.New() -> loadSkills().
No changes to pkg/kit or internal/skills -- the backend was already
complete. No viper binding is needed because kit.go reads these fields
directly from opts rather than from viper (unlike NoExtensions which
uses the viper fallback path).
Example usage:
kit --no-skills "prompt"
kit --skill ./my-skill.md --skill ./other-skill.md "prompt"
kit --skills-dir /path/to/skills "prompt"
Co-authored-by: Claude <claude@anthropic.com>
* docs: document --no-skills, --skill, and --skills-dir CLI flags
Add the three new skills CLI flags to all relevant documentation:
- README.md: add Skills section under Global Flags CLI reference
- www/pages/cli/flags.md: add Skills table (mirrors Extensions section pattern)
- www/pages/cli/commands.md: expand the Skills section with usage examples
and a description of auto-discovery vs explicit loading vs --no-skills
Co-authored-by: Claude <claude@anthropic.com>
* feat: add config file support for skills options
Skills could previously only be controlled via CLI flags or SDK Options
fields. This commit wires all three skills settings into viper so they
can also be set in .kit.yml / .kit.yaml / .kit.json and via KIT_*
environment variables — matching the pattern used by no-extensions,
no-core-tools, and prompt-template.
cmd/root.go:
- Bind --no-skills, --skill, and --skills-dir flags to viper keys
(no-skills, skill, skills-dir) so config file values flow through.
pkg/kit/kit.go:
- At skill-load time, merge opts fields with viper values:
- noSkills = opts.NoSkills || v.GetBool("no-skills")
- skillPaths: opts.Skills if non-empty, else v.GetStringSlice("skill")
- skillsDir: opts.SkillsDir if non-empty, else v.GetString("skills-dir")
- Build a shallow-copied mergedOpts so loadSkills() picks up the
resolved values without mutating the original Options struct.
docs:
- README.md: add skills keys to the Basic Configuration YAML example
- www/pages/configuration.md: add no-skills, skill, skills-dir rows to
the All configuration keys table
Config file example (.kit.yml):
no-skills: false
skill:
- /path/to/skill.md
skills-dir: /path/to/skills/
Co-authored-by: Claude <claude@anthropic.com>
* config: add skills keys to default .kit.yml template
Add no-skills, skill, and skills-dir as commented-out examples in the
default config file generated by EnsureConfigExists(), alongside the
existing application settings block.
Co-authored-by: Claude <claude@anthropic.com>
* test: add test coverage for skills CLI flags and config keys
Four test locations updated:
pkg/kit/export_test.go:
- Add ConfigStringSliceForTest() helper to expose v.GetStringSlice()
from the Kit's isolated viper store, needed to assert skill list values.
pkg/kit/kit_test.go (TestNewWithSkillsOptions):
- NoSkills=true: GetSkills() returns empty slice
- SkillsDir=<empty dir>: kit.New() succeeds with zero skills
- Skills=[file]: single explicit skill file is loaded and name parsed correctly
pkg/kit/viper_isolation_test.go:
- TestSkillsViperKeys: no-API-key struct-level checks for NoSkills, Skills,
and SkillsDir fields on Options
- TestSkillsConfigFileKeys: full kit.New() round-trips via a written .kit.yml
for each of the three config keys:
no-skills: true → GetSkills() returns empty
skill: [path] → named skill loaded from config file path
skills-dir: dir → custom discovery root accepted without error
internal/config/config_test.go (TestEnsureConfigExists):
- Assert generated ~/.kit.yml template contains '# Skills configuration',
'no-skills:', and 'skills-dir:' comment blocks.
Co-authored-by: Claude <claude@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
1079 lines
40 KiB
Markdown
1079 lines
40 KiB
Markdown
<p align="center">
|
|
<img src="logo.jpg" alt="KIT" width="400">
|
|
</p>
|
|
|
|
<p align="center">
|
|
<a href="https://github.com/mark3labs/kit/actions/workflows/ci.yml"><img src="https://github.com/mark3labs/kit/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
<a href="https://github.com/mark3labs/kit/releases/latest"><img src="https://img.shields.io/github/v/release/mark3labs/kit?style=flat&color=blue" alt="Release"></a>
|
|
<a href="https://www.npmjs.com/package/@mark3labs/kit"><img src="https://img.shields.io/npm/v/@mark3labs/kit?style=flat&color=cb3837" alt="npm"></a>
|
|
<a href="https://pkg.go.dev/github.com/mark3labs/kit"><img src="https://pkg.go.dev/badge/github.com/mark3labs/kit.svg" alt="Go Reference"></a>
|
|
<a href="https://github.com/mark3labs/kit/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mark3labs/kit?style=flat" alt="License"></a>
|
|
<a href="https://discord.gg/RqSS2NQVsY"><img src="https://img.shields.io/badge/Discord-community-5865F2?style=flat&logo=discord&logoColor=white" alt="Discord"></a>
|
|
</p>
|
|
|
|
# KIT (Knowledge Inference Tool)
|
|
|
|
A powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system.
|
|
|
|
## Features
|
|
|
|
- **Multi-Provider LLM Support**: Anthropic, OpenAI, Google Gemini, Ollama, Azure OpenAI, AWS Bedrock, OpenRouter, and more
|
|
- **Built-in Core Tools**: bash (with interactive sudo password prompt), read, write, edit, grep, find, ls, subagent - no MCP overhead
|
|
- **Smart @ Attachments**: Binary files auto-detected via MIME type, MCP resources via `@mcp:server:uri`
|
|
- **MCP Integration**: Connect external MCP servers for expanded capabilities
|
|
- **Extension System**: Write custom tools, commands, widgets, and UI modifications in Go
|
|
- **Theming**: 22 built-in color themes (KITT, Catppuccin, Dracula, Nord, etc.) with runtime switching, persistence, and custom theme files
|
|
- **Model Persistence**: Model and thinking level selections are automatically saved and restored across sessions
|
|
- **Prompt Templates**: Create reusable prompt templates with shell-style argument substitution
|
|
- **Interactive TUI**: Rich terminal interface powered by Bubble Tea with streaming, syntax highlighting, and custom rendering
|
|
- **Session Management**: Tree-based conversation history with branching support
|
|
- **Non-Interactive Mode**: Script-friendly positional args with JSON output
|
|
- **ACP Server**: Run Kit as an [Agent Client Protocol](https://agentclientprotocol.com) agent over stdio
|
|
- **Go SDK**: Embed Kit in your own applications with full agent lifecycle events (30+ event types) and behavior-modifying hooks
|
|
|
|
## Installation
|
|
|
|
### Using npm / bun / pnpm
|
|
|
|
```bash
|
|
npm install -g @mark3labs/kit
|
|
# or
|
|
bun install -g @mark3labs/kit
|
|
# or
|
|
pnpm install -g @mark3labs/kit
|
|
```
|
|
|
|
### Using Go
|
|
|
|
```bash
|
|
go install github.com/mark3labs/kit/cmd/kit@latest
|
|
```
|
|
|
|
### Building from source
|
|
|
|
```bash
|
|
git clone https://github.com/mark3labs/kit.git
|
|
cd kit
|
|
go build -o kit ./cmd/kit
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### Basic Usage
|
|
|
|
```bash
|
|
# Start interactive session
|
|
kit
|
|
|
|
# Run a one-off prompt
|
|
kit "List files in src/"
|
|
|
|
# Attach files as context
|
|
kit @main.go @test.go "Review these files"
|
|
|
|
# Continue the most recent session
|
|
kit --continue
|
|
|
|
# Model and thinking level selections are automatically persisted
|
|
# across sessions and restored on next launch
|
|
|
|
# Use specific model
|
|
kit --model anthropic/claude-sonnet-latest
|
|
```
|
|
|
|
### Non-Interactive Mode
|
|
|
|
```bash
|
|
# Get JSON output for scripting
|
|
kit "Explain main.go" --json
|
|
|
|
# Quiet mode (final response only)
|
|
kit "Run tests" --quiet
|
|
|
|
# Ephemeral mode (no session file)
|
|
kit "Quick question" --no-session
|
|
```
|
|
|
|
### ACP Server Mode
|
|
|
|
Kit can run as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server, enabling ACP-compatible clients (such as [OpenCode](https://github.com/sst/opencode)) to drive Kit as a remote coding agent over stdio.
|
|
|
|
```bash
|
|
# Start Kit as an ACP server (communicates via JSON-RPC 2.0 on stdin/stdout)
|
|
kit acp
|
|
|
|
# With debug logging to stderr
|
|
kit acp --debug
|
|
```
|
|
|
|
The ACP server exposes Kit's full capabilities — LLM execution, tool calls (bash, read, write, edit, grep, etc.), and session persistence — over the standard ACP protocol. Sessions are persisted to Kit's normal JSONL session files, so they can be resumed later.
|
|
|
|
## Configuration
|
|
|
|
Kit looks for configuration in the following locations (in order of priority):
|
|
|
|
1. CLI flags
|
|
2. Environment variables (with `KIT_` prefix)
|
|
3. `./.kit.yml` / `./.kit.yaml` / `./.kit.json` (project-local)
|
|
4. `~/.kit.yml` / `~/.kit.yaml` / `~/.kit.json` (global)
|
|
|
|
### Basic Configuration
|
|
|
|
Create `~/.kit.yml`:
|
|
|
|
```yaml
|
|
model: anthropic/claude-sonnet-latest
|
|
max-tokens: 4096
|
|
temperature: 0.7
|
|
stream: true
|
|
thinking-level: off # off, none, minimal, low, medium, high
|
|
no-core-tools: false # set to true to disable all built-in core tools
|
|
|
|
# Skills — all three keys are optional
|
|
no-skills: false # set to true to disable all skill loading
|
|
skill: # explicit skill files/dirs (disables auto-discovery)
|
|
- /path/to/skill.md
|
|
skills-dir: "" # override project-local directory for auto-discovery
|
|
```
|
|
|
|
All of the above keys can also be set programmatically via the SDK
|
|
(`kit.Options.MaxTokens`, `Options.Temperature`, `Options.ThinkingLevel`, etc.)
|
|
without touching config files — see [SDK options](#with-options).
|
|
|
|
### Environment Variables
|
|
|
|
```bash
|
|
export ANTHROPIC_API_KEY="sk-..."
|
|
export OPENAI_API_KEY="sk-..."
|
|
export KIT_MODEL="openai/gpt-4o"
|
|
```
|
|
|
|
### MCP Server Configuration
|
|
|
|
Add external MCP servers to `.kit.yml`:
|
|
|
|
```yaml
|
|
mcpServers:
|
|
filesystem:
|
|
type: local
|
|
command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"]
|
|
environment:
|
|
LOG_LEVEL: "info"
|
|
allowedTools: ["read_file", "write_file"]
|
|
|
|
search:
|
|
type: remote
|
|
url: "https://mcp.example.com/search"
|
|
|
|
pubmed:
|
|
type: remote
|
|
url: "https://pubmed.mcp.example.com"
|
|
noOAuth: true # skip OAuth for public servers that don't require auth
|
|
|
|
builds:
|
|
type: remote
|
|
url: "https://builds.mcp.example.com"
|
|
tasksMode: always # async task execution — see MCP Tasks below
|
|
```
|
|
|
|
## CLI Reference
|
|
|
|
### Global Flags
|
|
|
|
```bash
|
|
# Model and provider
|
|
--model, -m Model to use (provider/model format)
|
|
--provider-api-key API key for the provider
|
|
--provider-url Base URL for provider API
|
|
--tls-skip-verify Skip TLS certificate verification
|
|
|
|
# Session management
|
|
--session, -s Open specific JSONL session file
|
|
--continue, -c Resume most recent session for current directory
|
|
--resume, -r Interactive session picker
|
|
--no-session Ephemeral mode, no persistence
|
|
|
|
# Behavior (non-interactive: pass prompt as positional arg)
|
|
--quiet Suppress all output (non-interactive only)
|
|
--json Output response as JSON (non-interactive only)
|
|
--no-exit Enter interactive mode after prompt completes
|
|
--max-steps Maximum agent steps (0 for unlimited)
|
|
--stream Enable streaming output (default: true)
|
|
--compact Enable compact output mode
|
|
--auto-compact Auto-compact conversation near context limit
|
|
|
|
# Extensions and tools
|
|
--extension, -e Load additional extension file(s) (repeatable)
|
|
--no-extensions Disable all extensions
|
|
--no-core-tools Disable all built-in core tools (bash, read, write, edit, grep, find, ls, subagent)
|
|
--prompt-template Load a specific prompt template by name
|
|
--no-prompt-templates Disable prompt template loading
|
|
|
|
# Skills
|
|
--skill Load skill file or directory (repeatable)
|
|
--skills-dir Override the project-local skills directory for auto-discovery
|
|
--no-skills Disable skill loading (auto-discovery and explicit)
|
|
|
|
# Generation parameters
|
|
--max-tokens Maximum tokens in response (default: 8192, auto-raised up to 32768 for models with larger known output limits)
|
|
--temperature Randomness 0.0-1.0 (default: 0.7)
|
|
--top-p Nucleus sampling 0.0-1.0 (default: 0.95)
|
|
--top-k Limit top K tokens (default: 40)
|
|
--stop-sequences Custom stop sequences (comma-separated)
|
|
--frequency-penalty Penalize frequent tokens 0.0-2.0 (default: 0.0)
|
|
--presence-penalty Penalize present tokens 0.0-2.0 (default: 0.0)
|
|
--thinking-level Extended thinking level: off, none, minimal, low, medium, high (default: off)
|
|
|
|
# System
|
|
--config Config file path (default: ~/.kit.yml)
|
|
--system-prompt System prompt text or file path
|
|
--debug Enable debug logging
|
|
```
|
|
|
|
### Commands
|
|
|
|
```bash
|
|
# Authentication (for OAuth-enabled providers)
|
|
kit auth login [provider] # Start OAuth flow (e.g., anthropic)
|
|
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
|
|
|
|
# GitHub Copilot login (experimental; requires active Copilot subscription)
|
|
kit auth login copilot
|
|
kit --model copilot/gpt-5.5 "Hello"
|
|
|
|
# Model database
|
|
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 (from models.dev, URL, file, or 'embedded')
|
|
|
|
# Extension management
|
|
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
|
|
|
|
# Skills
|
|
kit skill # Install the Kit extensions skill via skills.sh
|
|
|
|
# ACP server
|
|
kit acp # Start as ACP agent (stdio JSON-RPC)
|
|
kit acp --debug # With debug logging to stderr
|
|
```
|
|
|
|
## Themes
|
|
|
|
Kit ships with 22 built-in color themes that control all UI elements. Switch at runtime:
|
|
|
|
```
|
|
/theme dracula
|
|
/theme catppuccin
|
|
/theme tokyonight
|
|
```
|
|
|
|
Theme selections are automatically saved and restored on next launch (stored in `~/.config/kit/preferences.yml`). This persistence also applies to **model** and **thinking level** selections — all are saved together and restored on startup.
|
|
|
|
### Custom themes
|
|
|
|
Drop a `.yml` file in `~/.config/kit/themes/` (user) or `.kit/themes/` (project):
|
|
|
|
```yaml
|
|
# ~/.config/kit/themes/my-theme.yml
|
|
primary:
|
|
light: "#8839ef"
|
|
dark: "#cba6f7"
|
|
success:
|
|
light: "#40a02b"
|
|
dark: "#a6e3a1"
|
|
```
|
|
|
|
Built-in themes: `kitt`, `catppuccin`, `dracula`, `tokyonight`, `nord`, `gruvbox`, `monokai`, `solarized`, `github`, `one-dark`, `rose-pine`, `ayu`, `material`, `everforest`, `kanagawa`, `amoled`, `synthwave`, `vesper`, `flexoki`, `matrix`, `vercel`, `zenburn`
|
|
|
|
## Extension System
|
|
|
|
Extensions are Go source files that run via Yaegi interpreter. They can add custom tools, slash commands, widgets, keyboard shortcuts, themes, and intercept lifecycle events.
|
|
|
|
### Minimal Extension
|
|
|
|
```go
|
|
//go:build ignore
|
|
|
|
package main
|
|
|
|
import "kit/ext"
|
|
|
|
func Init(api ext.API) {
|
|
api.OnSessionStart(func(_ ext.SessionStartEvent, ctx ext.Context) {
|
|
ctx.SetFooter(ext.HeaderFooterConfig{
|
|
Content: ext.WidgetContent{Text: "Custom Footer"},
|
|
})
|
|
})
|
|
}
|
|
```
|
|
|
|
**Usage:**
|
|
|
|
```bash
|
|
kit -e examples/extensions/minimal.go
|
|
```
|
|
|
|
### Extension Capabilities
|
|
|
|
**Lifecycle Events**: OnSessionStart, OnSessionShutdown, OnBeforeAgentStart, OnAgentStart, OnAgentEnd, OnLLMUsage, OnToolCall, OnToolCallInputStart, OnToolCallInputDelta, OnToolCallInputEnd, OnToolExecutionStart, OnToolOutput, OnToolExecutionEnd, OnToolResult, OnInput, OnMessageStart, OnMessageUpdate, OnMessageEnd, OnModelChange, OnContextPrepare, OnBeforeFork, OnBeforeSessionSwitch, OnBeforeCompact, OnCustomEvent, OnSubagentStart, OnSubagentChunk, OnSubagentEnd
|
|
|
|
`OnAgentEnd` carries per-turn aggregates (`ToolCallCount`, `ToolNames`, `LLMCallCount`, `InputTokensDelta`, `OutputTokensDelta`, `CostDelta`, `DurationMs`) so observers don't need to maintain parallel bookkeeping. `OnLLMUsage` fires after each LLM provider call with token + cost deltas attributed to that specific call/model — use it for accurate budget enforcement *between* calls instead of waiting for the turn to finish.
|
|
|
|
**Custom Components**:
|
|
- **Tools**: Add new tools the LLM can invoke
|
|
- **Commands**: Register slash commands (e.g., `/mycommand`)
|
|
- **Options**: Register configurable extension options
|
|
- **Session State**: Last-write-wins key-value store via `ctx.SetState` / `GetState` / `DeleteState` / `ListState`, persisted to a per-session sidecar file outside the conversation tree
|
|
- **Widgets**: Persistent status displays above/below input
|
|
- **Headers/Footers**: Persistent content above/below the conversation
|
|
- **Status Bar**: Custom status bar entries
|
|
- **Shortcuts**: Global keyboard shortcuts
|
|
- **Overlays**: Modal dialogs with markdown content
|
|
- **Tool Renderers**: Customize how tool calls display
|
|
- **Message Renderers**: Custom rendering for assistant messages
|
|
- **Editor Interceptors**: Handle key events and wrap rendering
|
|
- **Interactive Prompts**: Select, confirm, input, and multi-select dialogs
|
|
- **Subagents**: Spawn in-process child Kit instances
|
|
- **LLM Completion**: Direct model calls via `Complete()`
|
|
- **Themes**: Register and switch color themes via `RegisterTheme`, `SetTheme`, `ListThemes`
|
|
- **Custom Events**: Inter-extension communication via `EmitCustomEvent`
|
|
|
|
**Bridged SDK APIs** (NEW): Extensions can now access internal SDK capabilities:
|
|
- **Tree Navigation**: Navigate conversation history (`GetTreeNode`, `GetCurrentBranch`, `NavigateTo`), summarize branches (`SummarizeBranch`), and implement fresh context loops (`CollapseBranch`)
|
|
- **Skill Loading**: Dynamically load and inject skills at runtime (`LoadSkill`, `DiscoverSkills`, `InjectSkillAsContext`)
|
|
- **Template Parsing**: Parse and render templates with `{{variables}}` (`ParseTemplate`, `RenderTemplate`), parse CLI-style arguments (`ParseArguments`, `SimpleParseArguments`), and evaluate model conditionals (`EvaluateModelConditional`, `RenderWithModelConditionals`)
|
|
- **Model Resolution**: Resolve model fallback chains (`ResolveModelChain`), query model capabilities (`GetModelCapabilities`, `CheckModelAvailable`), and extract provider/model ID (`GetCurrentProvider`, `GetCurrentModelID`)
|
|
|
|
### Extension Examples
|
|
|
|
See the `examples/extensions/` directory:
|
|
|
|
- [`minimal.go`](examples/extensions/minimal.go) - Clean UI with custom footer
|
|
- [`auto-commit.go`](examples/extensions/auto-commit.go) - Auto-commit on shutdown
|
|
- [`bookmark.go`](examples/extensions/bookmark.go) - Bookmark conversations
|
|
- [`branded-output.go`](examples/extensions/branded-output.go) - Branded output rendering
|
|
- [`bridge-demo.go`](examples/extensions/bridge_demo.go) - Bridged SDK API demo (tree navigation, skills, templates, model resolution)
|
|
- [`compact-notify.go`](examples/extensions/compact-notify.go) - Notification on compaction
|
|
- [`confirm-destructive.go`](examples/extensions/confirm-destructive.go) - Confirm destructive operations
|
|
- [`context-inject.go`](examples/extensions/context-inject.go) - Inject context into conversations
|
|
- [`conversation-manager.go`](examples/extensions/conversation-manager.go) - **NEW** Tree navigation, branch summarization, and fresh context loops
|
|
- [`custom-editor-demo.go`](examples/extensions/custom-editor-demo.go) - Vim-like modal editor
|
|
- [`dev-reload.go`](examples/extensions/dev-reload.go) - Development live-reload
|
|
- [`header-footer-demo.go`](examples/extensions/header-footer-demo.go) - Custom headers and footers
|
|
- [`inline-bash.go`](examples/extensions/inline-bash.go) - Inline bash execution
|
|
- [`interactive-shell.go`](examples/extensions/interactive-shell.go) - Interactive shell integration
|
|
- [`kit-kit.go`](examples/extensions/kit-kit.go) - Kit-in-Kit (sub-agent spawning)
|
|
- [`lsp-diagnostics.go`](examples/extensions/lsp-diagnostics.go) - LSP diagnostic integration
|
|
- [`notify.go`](examples/extensions/notify.go) - Desktop notifications
|
|
- [`overlay-demo.go`](examples/extensions/overlay-demo.go) - Modal dialogs
|
|
- [`permission-gate.go`](examples/extensions/permission-gate.go) - Permission gating for tools
|
|
- [`pirate.go`](examples/extensions/pirate.go) - Pirate-themed personality
|
|
- [`plan-mode.go`](examples/extensions/plan-mode.go) - Read-only planning mode
|
|
- [`project-rules.go`](examples/extensions/project-rules.go) - Project-specific rules
|
|
- [`prompt-demo.go`](examples/extensions/prompt-demo.go) - Interactive prompts (select/confirm/input)
|
|
- [`prompt-templates.go`](examples/extensions/prompt-templates.go) - **NEW** Frontmatter-driven templates with model switching and skill injection
|
|
- [`protected-paths.go`](examples/extensions/protected-paths.go) - Path protection for sensitive files
|
|
- [`subagent-widget.go`](examples/extensions/subagent-widget.go) - Multi-agent orchestration with status widget
|
|
- [`subagent-test.go`](examples/extensions/subagent-test.go) - Subagent testing utilities
|
|
- [`summarize.go`](examples/extensions/summarize.go) - Conversation summarization
|
|
- [`tool-logger.go`](examples/extensions/tool-logger.go) - Log all tool calls
|
|
- [`neon-theme.go`](examples/extensions/neon-theme.go) - Custom theme registration and switching
|
|
- [`tool-renderer-demo.go`](examples/extensions/tool-renderer-demo.go) - Custom tool call rendering
|
|
- [`usage-budget.go`](examples/extensions/usage-budget.go) - Per-call usage callback (`OnLLMUsage`), session state, and enriched `OnAgentEnd` per-turn report
|
|
- [`widget-status.go`](examples/extensions/widget-status.go) - Persistent status widgets
|
|
|
|
Also see [`.kit/extensions/go-edit-lint.go`](.kit/extensions/go-edit-lint.go) (in this repo) for a project-local extension example that runs gopls and golangci-lint on Go file edits.
|
|
|
|
### Loading Extensions
|
|
|
|
**Auto-discovery** (loads automatically):
|
|
- `~/.config/kit/extensions/*.go` (global single files)
|
|
- `~/.config/kit/extensions/*/main.go` (global subdirectory extensions)
|
|
- `.kit/extensions/*.go` (project-local single files)
|
|
- `.kit/extensions/*/main.go` (project-local subdirectory extensions)
|
|
- `~/.local/share/kit/git/` (global git-installed packages)
|
|
- `.kit/git/` (project-local git-installed packages)
|
|
|
|
**Explicit loading**:
|
|
```bash
|
|
kit -e path/to/extension.go
|
|
kit -e ext1.go -e ext2.go # Multiple extensions
|
|
```
|
|
|
|
**Disable auto-load**:
|
|
```bash
|
|
kit --no-extensions
|
|
```
|
|
|
|
### Testing Extensions
|
|
|
|
Kit provides a testing package to help you write unit tests for your extensions:
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"testing"
|
|
"github.com/mark3labs/kit/pkg/extensions/test"
|
|
"github.com/mark3labs/kit/internal/extensions"
|
|
)
|
|
|
|
func TestMyExtension(t *testing.T) {
|
|
harness := test.New(t)
|
|
harness.LoadFile("my-ext.go")
|
|
|
|
// Emit events and verify behavior
|
|
_, err := harness.Emit(extensions.SessionStartEvent{SessionID: "test"})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// Verify the extension printed something
|
|
test.AssertPrinted(t, harness, "session started")
|
|
}
|
|
```
|
|
|
|
**Available assertions:**
|
|
- `AssertBlocked()`, `AssertNotBlocked()` — Verify tool blocking
|
|
- `AssertWidgetSet()`, `AssertWidgetText()` — Verify widget content
|
|
- `AssertPrinted()`, `AssertPrintedContains()` — Verify output
|
|
- `AssertToolRegistered()`, `AssertCommandRegistered()` — Verify registration
|
|
|
|
See [`examples/extensions/tool-logger_test.go`](examples/extensions/tool-logger_test.go) for a complete example with 14 test cases covering tool calls, input handling, and session lifecycle.
|
|
|
|
### Prompt Templates
|
|
|
|
Create reusable prompt templates with shell-style argument substitution. Templates are loaded from `~/.kit/prompts/*.md` and `.kit/prompts/*.md`.
|
|
|
|
**Example template** (`~/.kit/prompts/review.md`):
|
|
```markdown
|
|
---
|
|
description: Review code for issues
|
|
---
|
|
Review the following code for bugs and security issues.
|
|
Focus on $1 specifically.
|
|
```
|
|
|
|
**Usage:**
|
|
```
|
|
/review error handling
|
|
```
|
|
|
|
**Argument placeholders:**
|
|
- `$1`, `$2`, etc. — Individual arguments
|
|
- `$@` or `$ARGUMENTS` — All arguments (zero or more)
|
|
- `$+` — All arguments (one or more required; error if none given)
|
|
- `${@:2}` — Arguments from position 2 onwards
|
|
- `${@:1:3}` — 3 arguments starting at position 1
|
|
|
|
Placeholders inside fenced code blocks (```) and inline code spans are ignored.
|
|
|
|
Disable templates with `--no-prompt-templates` or load a specific template with `--prompt-template <name>`.
|
|
|
|
## Session Management
|
|
|
|
Kit uses a tree-based session model that supports branching and forking conversations.
|
|
|
|
### Session Locations
|
|
|
|
- Default: `~/.kit/sessions/<cwd-path>/<timestamp>_<id>.jsonl`
|
|
- Path separators in the working directory are replaced with `--` (e.g., `/home/user/project` becomes `home--user--project`)
|
|
- Each line is a session entry (messages, tool calls, extension data)
|
|
- Supports branching from any message to explore alternate paths
|
|
|
|
### Session Commands
|
|
|
|
```bash
|
|
# Resume most recent session for current directory
|
|
kit --continue
|
|
kit -c
|
|
|
|
# Interactive session picker
|
|
kit --resume
|
|
kit -r
|
|
|
|
# Open specific session file
|
|
kit --session path/to/session.jsonl
|
|
kit -s path/to/session.jsonl
|
|
|
|
# Ephemeral mode (no file persistence)
|
|
kit --no-session
|
|
```
|
|
|
|
### Interactive Session Commands
|
|
|
|
During an interactive session, use these slash commands:
|
|
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `/name [name]` | Set or display the session's display name |
|
|
| `/session` | Show session info (path, ID, message count) |
|
|
| `/resume` | Open the session picker to switch sessions |
|
|
| `/export [path]` | Export session as JSONL (auto-generates path if omitted) |
|
|
| `/import <path>` | Import and switch to a session from a JSONL file |
|
|
| `/share` | Upload session to GitHub Gist and get a shareable viewer URL |
|
|
| `/tree` | Navigate the session tree |
|
|
| `/fork` | Fork to new session from an earlier message |
|
|
| `/new` | Start a fresh session |
|
|
|
|
### Keyboard Shortcuts
|
|
|
|
| Shortcut | Description |
|
|
|----------|-------------|
|
|
| `Ctrl+V` | Paste an image from the clipboard — shows an inline low-res thumbnail preview (tmux/zellij-safe) |
|
|
| `Ctrl+U` | Clear all pending image attachments |
|
|
| `Ctrl+X e` | Open `$VISUAL`/`$EDITOR` to compose or edit your prompt |
|
|
| `Ctrl+X s` | Steer — inject a system-level instruction mid-turn |
|
|
| `ESC ESC` | Cancel the current operation (tool call or streaming) |
|
|
| `↑` / `↓` | Navigate prompt history |
|
|
|
|
## Go SDK
|
|
|
|
Embed Kit in your Go applications:
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
kit "github.com/mark3labs/kit/pkg/kit"
|
|
)
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
|
|
// Create Kit instance with default configuration
|
|
host, err := kit.New(ctx, nil)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer func() { _ = host.Close() }()
|
|
|
|
// Send a prompt
|
|
response, err := host.Prompt(ctx, "What is 2+2?")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
println(response)
|
|
}
|
|
```
|
|
|
|
### With Options
|
|
|
|
```go
|
|
host, err := kit.New(ctx, &kit.Options{
|
|
Model: "ollama/llama3",
|
|
SystemPrompt: "You are a helpful bot",
|
|
ConfigFile: "/path/to/config.yml",
|
|
MaxSteps: 10,
|
|
Streaming: ptr(true), // *bool: nil = unset (default true), &false = off
|
|
Quiet: true,
|
|
|
|
// Generation parameters (override env/config/per-model defaults)
|
|
MaxTokens: 16384, // 0 = auto-resolve (env → config → per-model → 8192 floor)
|
|
ThinkingLevel: "medium", // "off", "none", "minimal", "low", "medium", "high"
|
|
Temperature: ptr(float32(0.2)), // pointer so 0.0 != unset; nil = provider default
|
|
TopP: nil, // nil = leave provider/per-model default
|
|
TopK: nil,
|
|
FrequencyPenalty: nil,
|
|
PresencePenalty: nil,
|
|
|
|
// Provider configuration (override env/config without reaching into viper)
|
|
ProviderAPIKey: "sk-...", // "" = use config / provider env var
|
|
ProviderURL: "https://proxy.internal/v1", // "" = provider default
|
|
TLSSkipVerify: false, // only takes effect when true
|
|
|
|
// Session options
|
|
SessionPath: "./session.jsonl", // Open specific session
|
|
Continue: true, // Resume most recent session
|
|
NoSession: true, // Ephemeral mode
|
|
|
|
// Tool options
|
|
Tools: []kit.Tool{...}, // Replace default tool set entirely
|
|
ExtraTools: []kit.Tool{...}, // Add tools alongside defaults
|
|
DisableCoreTools: true, // Disable all built-in core tools; also controllable via
|
|
// --no-core-tools flag, KIT_NO_CORE_TOOLS env var,
|
|
// or no-core-tools: true in .kit.yml
|
|
|
|
// Configuration
|
|
SkipConfig: true, // Skip .kit.yml files (viper defaults + env vars still apply)
|
|
|
|
// Compaction
|
|
AutoCompact: true, // Auto-compact near context limit
|
|
|
|
Debug: true, // Debug logging
|
|
})
|
|
```
|
|
|
|
**Generation & provider fields** (added in v0.55+) let SDK consumers configure
|
|
Kit entirely in-code without `viper.Set()` workarounds or shipping a `.kit.yml`.
|
|
Precedence is `Options` > `KIT_*` env vars > `.kit.yml` > per-model defaults
|
|
(`modelSettings` / `customModels`) > provider-level defaults. Sampling params
|
|
are pointer types so explicit `0.0` is distinguishable from "leave alone"; a
|
|
non-zero `MaxTokens` suppresses automatic right-sizing the same way `--max-tokens`
|
|
does on the CLI.
|
|
|
|
### Functional options (`NewAgent`)
|
|
|
|
For simple programmatic setups, `kit.NewAgent` offers an ergonomic
|
|
functional-options front door over `kit.New`. Streaming is **enabled by
|
|
default**; pass `kit.WithStreaming(false)` to opt out.
|
|
|
|
```go
|
|
host, err := kit.NewAgent(ctx,
|
|
kit.WithModel("anthropic/claude-sonnet-4-5-20250929"),
|
|
kit.WithSystemPrompt("You are a helpful assistant."),
|
|
kit.WithMaxTokens(8192),
|
|
kit.WithThinkingLevel("medium"),
|
|
kit.Ephemeral(), // in-memory session, no persistence
|
|
)
|
|
```
|
|
|
|
Available options: `WithModel`, `WithSystemPrompt`, `WithStreaming`,
|
|
`WithMaxTokens`, `WithThinkingLevel`, `WithTools`, `WithExtraTools`,
|
|
`WithProviderAPIKey`, `WithProviderURL`, `WithConfigFile`, `WithDebug`, and
|
|
`Ephemeral`. For advanced configuration not covered by the helpers (custom MCP
|
|
config, in-process MCP servers, session backends, MCP task tuning) construct an
|
|
`Options` value explicitly and call `kit.New`.
|
|
|
|
### Per-instance config isolation
|
|
|
|
Each `kit.New` / `kit.NewAgent` call owns an **isolated configuration store**,
|
|
so constructing multiple Kit instances in the same process is safe: setting the
|
|
model, thinking level, or generation parameters on one never affects another,
|
|
and runtime mutators (`SetModel`, `SetThinkingLevel`) only touch the owning
|
|
instance. This makes subagent spawning and multi-Kit embedding race-free with
|
|
no external synchronization required.
|
|
|
|
### MCP OAuth (remote MCP servers)
|
|
|
|
When a remote MCP server returns 401, Kit runs the full OAuth flow (dynamic
|
|
client registration → PKCE → token exchange → persistence) but delegates the
|
|
user-facing step — showing the authorization URL and receiving the callback —
|
|
to an `MCPAuthHandler` that you pass explicitly via `Options.MCPAuthHandler`.
|
|
If nil, OAuth is disabled and the authorization-required error surfaces to the
|
|
caller; the SDK never auto-opens a browser or binds a localhost port.
|
|
|
|
```go
|
|
// CLI/TUI apps: opens the system browser + prints status to stderr.
|
|
authHandler, _ := kit.NewCLIMCPAuthHandler()
|
|
defer authHandler.Close()
|
|
|
|
host, _ := kit.New(ctx, &kit.Options{
|
|
MCPAuthHandler: authHandler,
|
|
})
|
|
|
|
// Custom UX: reuse the SDK's port + callback server, supply your own
|
|
// presentation via OnAuthURL (TUI modal, QR code, web redirect, etc.).
|
|
// h, _ := kit.NewDefaultMCPAuthHandler()
|
|
// h.OnAuthURL = func(server, authURL string) { myUI.Show(server, authURL) }
|
|
//
|
|
// Full control (web apps, daemons): implement kit.MCPAuthHandler yourself —
|
|
// no localhost binding, no side effects.
|
|
```
|
|
|
|
Tokens are persisted to `$XDG_CONFIG_HOME/.kit/mcp_tokens.json` by default; swap
|
|
in a custom `MCPTokenStoreFactory` for encrypted, DB-backed, or in-memory
|
|
storage. See the [SDK options docs](/sdk/options#mcp-oauth-authorization) for
|
|
the full matrix.
|
|
|
|
### MCP Tasks (long-running tools)
|
|
|
|
Kit advertises [MCP task support](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks)
|
|
during `initialize`, so cooperating MCP servers can respond to `tools/call`
|
|
with a `taskId` instead of blocking the connection. Kit then polls
|
|
`tasks/get` / `tasks/result` until the task reaches a terminal state, and
|
|
best-effort `tasks/cancel`s on context cancellation.
|
|
|
|
Defaults are safe — a server that doesn't advertise task capability runs
|
|
synchronously, exactly as before. Opt in per server via `tasksMode` in
|
|
`.kit.yml` (`auto` | `never` | `always`) or programmatically through the SDK:
|
|
|
|
```go
|
|
host, _ := kit.New(ctx, &kit.Options{
|
|
MCPTaskMode: map[string]kit.MCPTaskMode{
|
|
"build-server": kit.MCPTaskModeAlways,
|
|
},
|
|
MCPTaskTimeout: 15 * time.Minute,
|
|
MCPTaskProgress: func(p kit.MCPTaskProgress) {
|
|
log.Printf("%s: %s", p.TaskID, p.Status)
|
|
},
|
|
})
|
|
|
|
tasks, _ := host.ListMCPTasks(ctx, "build-server")
|
|
_, _ = host.CancelMCPTask(ctx, "build-server", tasks[0].TaskID)
|
|
```
|
|
|
|
See the [configuration docs](/configuration#mcp-tasks-long-running-tools) and
|
|
[SDK options → MCP Tasks](/sdk/options#mcp-tasks) for the full surface.
|
|
|
|
### Custom Tools
|
|
|
|
Create custom tools with automatic schema generation — no external dependencies needed:
|
|
|
|
```go
|
|
type SearchInput struct {
|
|
Query string `json:"query" description:"Search query"`
|
|
}
|
|
|
|
searchTool := kit.NewTool("search", "Search the codebase",
|
|
func(ctx context.Context, input SearchInput) (kit.ToolOutput, error) {
|
|
return kit.TextResult("Found: ..."), nil
|
|
},
|
|
)
|
|
|
|
host, _ := kit.New(ctx, &kit.Options{
|
|
ExtraTools: []kit.Tool{searchTool}, // adds alongside built-in tools
|
|
})
|
|
```
|
|
|
|
Use `kit.NewParallelTool` for tools safe to run concurrently. Binary data (images, audio, etc.) in `ToolOutput.Data` is automatically forwarded to the LLM when `MediaType` is set. See the [SDK docs](/sdk/overview) for full details on struct tags, `ToolOutput` fields, and `ToolCallIDFromContext`.
|
|
|
|
#### Return Helpers
|
|
|
|
| Helper | Description |
|
|
| --- | --- |
|
|
| `kit.TextResult(content)` | Successful text result |
|
|
| `kit.ErrorResult(content)` | Error result (LLM sees it as a tool error) |
|
|
| `kit.ImageResult(content, data, mediaType)` | Image result with binary data (e.g. `"image/png"`) |
|
|
| `kit.MediaResult(content, data, mediaType)` | Non-image media result (e.g. `"audio/mpeg"`) |
|
|
|
|
#### ToolOutput Fields
|
|
|
|
```go
|
|
kit.ToolOutput{
|
|
Content: "result text", // text returned to the LLM
|
|
IsError: false, // true = LLM sees this as an error
|
|
Data: pngBytes, // optional binary data (images, audio)
|
|
MediaType: "image/png", // MIME type for binary Data
|
|
Metadata: map[string]any{}, // opaque metadata for hooks/UI (not sent to LLM)
|
|
}
|
|
```
|
|
|
|
### With Callbacks
|
|
|
|
```go
|
|
unsub := host.OnToolCall(func(e kit.ToolCallEvent) {
|
|
println("Calling tool:", e.ToolName)
|
|
})
|
|
defer unsub()
|
|
|
|
unsub2 := host.OnToolResult(func(e kit.ToolResultEvent) {
|
|
if e.IsError {
|
|
println("Tool failed:", e.ToolName)
|
|
}
|
|
})
|
|
defer unsub2()
|
|
|
|
unsub3 := host.OnMessageUpdate(func(e kit.MessageUpdateEvent) {
|
|
print(e.Chunk)
|
|
})
|
|
defer unsub3()
|
|
|
|
response, err := host.Prompt(
|
|
ctx,
|
|
"List files in current directory",
|
|
)
|
|
```
|
|
|
|
### Session Management
|
|
|
|
```go
|
|
// Multi-turn conversations retain context automatically
|
|
host.Prompt(ctx, "My name is Alice")
|
|
response, _ := host.Prompt(ctx, "What's my name?")
|
|
|
|
// Sessions are persisted automatically to JSONL files.
|
|
// Access session info:
|
|
path := host.GetSessionPath()
|
|
id := host.GetSessionID()
|
|
|
|
// Clear conversation history
|
|
host.ClearSession()
|
|
```
|
|
|
|
Session persistence is configured via `Options`:
|
|
|
|
```go
|
|
host, _ := kit.New(ctx, &kit.Options{
|
|
SessionPath: "./my-session.jsonl", // Open specific session
|
|
Continue: true, // Resume most recent session
|
|
NoSession: true, // Ephemeral mode
|
|
})
|
|
```
|
|
|
|
### Runtime Skills & Context Files
|
|
|
|
For multi-tenant hosts (chatbots, per-user agents, web services), the SDK
|
|
lets you swap skills and `AGENTS.md`-style context files **after** Kit
|
|
construction. Every mutation recomposes the system prompt and applies it to
|
|
the agent so the next turn picks up the new instructions — no restart needed.
|
|
|
|
```go
|
|
// Programmatic skill (no file on disk required).
|
|
host.AddSkill(&kit.Skill{
|
|
Name: "polite-french",
|
|
Description: "Respond in French and always greet the user.",
|
|
Content: "Always reply in French. Open every response with 'Bonjour'.",
|
|
})
|
|
|
|
// Or load one from disk.
|
|
host.LoadAndAddSkill("/var/skills/refund-policy.md")
|
|
|
|
// Per-user AGENTS.md content pulled from a database.
|
|
host.AddContextFileContent(
|
|
fmt.Sprintf("session://%s/AGENTS.md", userID),
|
|
rulesFromDB,
|
|
)
|
|
|
|
// Tear down session-specific state on logout.
|
|
host.RemoveSkill("polite-french")
|
|
host.RemoveContextFile(fmt.Sprintf("session://%s/AGENTS.md", userID))
|
|
|
|
// Or replace the whole set atomically.
|
|
host.SetSkills(activeSkillsForUser)
|
|
host.SetContextFiles(activeContextForUser)
|
|
```
|
|
|
|
Skills dedupe by `Name`, context files dedupe by `Path` (which can be any
|
|
opaque identifier — it doesn't have to be a real filesystem path). All
|
|
mutators and readers (`GetSkills`, `GetContextFiles`) are safe to call
|
|
concurrently from multiple goroutines. See the [SDK overview docs](/sdk/overview#runtime-skills-and-context-files)
|
|
for the full reference.
|
|
|
|
## Advanced Usage
|
|
|
|
### Subagent Pattern
|
|
|
|
Spawn Kit as a subprocess for multi-agent orchestration:
|
|
|
|
```bash
|
|
kit "Analyze codebase" \
|
|
--json \
|
|
--no-session \
|
|
--no-extensions \
|
|
--quiet \
|
|
--model anthropic/claude-haiku-3-5-20241022
|
|
```
|
|
|
|
Parse the JSON output:
|
|
|
|
```json
|
|
{
|
|
"response": "Final assistant response text",
|
|
"model": "anthropic/claude-haiku-3-5-20241022",
|
|
"stop_reason": "end_turn",
|
|
"session_id": "a1b2c3d4e5f6",
|
|
"usage": {
|
|
"input_tokens": 1024,
|
|
"output_tokens": 512,
|
|
"total_tokens": 1536,
|
|
"cache_read_tokens": 0,
|
|
"cache_creation_tokens": 0
|
|
},
|
|
"messages": [
|
|
{
|
|
"role": "assistant",
|
|
"parts": [
|
|
{"type": "text", "data": "..."},
|
|
{"type": "tool_call", "data": {"name": "...", "args": "..."}},
|
|
{"type": "tool_result", "data": {"name": "...", "result": "..."}}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Testing with tmux
|
|
|
|
Test the TUI non-interactively:
|
|
|
|
```bash
|
|
# Start Kit in detached tmux session
|
|
tmux new-session -d -s kittest -x 120 -y 40 \
|
|
"kit -e ext.go --no-session 2>kit.log"
|
|
|
|
# Wait for startup
|
|
sleep 3
|
|
|
|
# Capture screen
|
|
tmux capture-pane -t kittest -p
|
|
|
|
# Send input
|
|
tmux send-keys -t kittest '/command' Enter
|
|
|
|
# Cleanup
|
|
tmux kill-session -t kittest
|
|
```
|
|
|
|
## Development
|
|
|
|
### Build and Test
|
|
|
|
```bash
|
|
# Build
|
|
go build -o output/kit ./cmd/kit
|
|
|
|
# Run tests
|
|
go test -race ./...
|
|
|
|
# Run specific test
|
|
go test -race ./cmd -run TestScriptExecution
|
|
|
|
# Lint
|
|
go vet ./...
|
|
|
|
# Format
|
|
go fmt ./...
|
|
```
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
cmd/kit/ - CLI entry point (main.go)
|
|
cmd/ - CLI command implementations (root, auth, models, etc.)
|
|
pkg/kit/ - Go SDK for embedding Kit
|
|
internal/app/ - Application orchestrator (agent loop, message store, queue)
|
|
internal/agent/ - Agent execution and tool dispatch
|
|
internal/auth/ - OAuth authentication and credential storage
|
|
internal/acpserver/ - ACP (Agent Client Protocol) server
|
|
internal/clipboard/ - Cross-platform clipboard operations
|
|
internal/compaction/ - Conversation compaction and summarization
|
|
internal/config/ - Configuration management
|
|
internal/core/ - Built-in tools (bash, read, write, edit, grep, find, ls)
|
|
internal/extensions/ - Yaegi extension system
|
|
internal/kitsetup/ - Initial setup wizard
|
|
internal/message/ - Message content types and structured content blocks
|
|
internal/models/ - Provider and model management
|
|
internal/session/ - Session persistence (tree-based JSONL)
|
|
internal/skills/ - Skill loading and system prompt composition
|
|
internal/tools/ - MCP tool integration
|
|
internal/ui/ - Bubble Tea TUI components
|
|
examples/extensions/ - Example extension files
|
|
npm/ - NPM package wrapper for distribution
|
|
```
|
|
|
|
## Supported Providers
|
|
|
|
- **Anthropic** - Claude models (native, prompt caching, OAuth)
|
|
- **OpenAI** - GPT models
|
|
- **Copilot** - GitHub Copilot models (`copilot`, requires active Copilot subscription)
|
|
- **Google** - Gemini models
|
|
- **Ollama** - Local models
|
|
- **Azure OpenAI** - Azure-hosted OpenAI
|
|
- **AWS Bedrock** - Bedrock models
|
|
- **Google Vertex** - Claude on Vertex AI
|
|
- **OpenRouter** - Multi-provider router
|
|
- **Vercel AI** - Vercel AI SDK models
|
|
- **Custom** - Any OpenAI-compatible endpoint via `--provider-url`
|
|
- **Auto-routed** - Any provider from models.dev database
|
|
|
|
### Custom Provider
|
|
|
|
Use `custom/custom` when pointing Kit at any OpenAI-compatible endpoint with `--provider-url`:
|
|
|
|
```bash
|
|
kit --provider-url "http://localhost:8080/v1" "Hello"
|
|
```
|
|
|
|
This automatically defaults to `custom/custom` without needing to specify a model. The custom provider routes through the `openaicompat` provider and supports:
|
|
|
|
- Zero cost tracking (input/output = 0)
|
|
- 262K context window, 65K output limit
|
|
- Reasoning and temperature support
|
|
- Optional `CUSTOM_API_KEY` environment variable or `--provider-api-key` flag
|
|
|
|
### Auto-routed Providers
|
|
|
|
Any provider in the [models.dev](https://models.dev) database can be used as
|
|
`provider/model` without a dedicated native integration. Kit auto-routes the
|
|
request through the matching **wire protocol** based on the provider's npm package
|
|
(or per-model override), using its `api` URL as the base:
|
|
|
|
| npm package | Wire protocol |
|
|
|-------------|---------------|
|
|
| `@ai-sdk/openai` | OpenAI (Responses API) |
|
|
| `@ai-sdk/openai-compatible` | OpenAI (chat completions) |
|
|
| `@ai-sdk/anthropic` | Anthropic |
|
|
| `@ai-sdk/google` | Google Gemini |
|
|
|
|
Providers with an `api` URL but an unrecognized npm package fall back to the
|
|
OpenAI-compatible wire. Because routing follows the wire protocol, aggregator/proxy
|
|
providers work across all of their models — including Claude, GPT, *and* Gemini
|
|
routes:
|
|
|
|
```bash
|
|
kit --model opencode/claude-haiku-4-5 "Hello" # → Anthropic wire
|
|
kit --model opencode/gpt-5 "Hello" # → OpenAI wire
|
|
kit --model opencode/gemini-3.5-flash "Hello" # → Google wire
|
|
```
|
|
|
|
### Model String Format
|
|
|
|
```bash
|
|
provider/model # Standard format
|
|
anthropic/claude-sonnet-latest
|
|
openai/gpt-4o
|
|
ollama/llama3
|
|
google/gemini-2.0-flash-exp
|
|
```
|
|
|
|
### Model Aliases
|
|
|
|
```bash
|
|
# Anthropic Claude
|
|
claude-opus-latest → claude-opus-4-6
|
|
claude-sonnet-latest → claude-sonnet-4-6
|
|
claude-haiku-latest → claude-haiku-4-5
|
|
claude-4-opus-latest → claude-opus-4-6
|
|
claude-4-sonnet-latest → claude-sonnet-4-6
|
|
claude-4-haiku-latest → claude-haiku-4-5
|
|
claude-3-7-sonnet-latest → claude-3-7-sonnet-20250219
|
|
claude-3-5-sonnet-latest → claude-3-5-sonnet-20241022
|
|
claude-3-5-haiku-latest → claude-3-5-haiku-20241022
|
|
claude-3-opus-latest → claude-3-opus-20240229
|
|
|
|
# OpenAI GPT
|
|
o1-latest → o1
|
|
o3-latest → o3
|
|
o4-latest → o4-mini
|
|
gpt-5-latest → gpt-5.4
|
|
gpt-5-chat-latest → gpt-5.4
|
|
gpt-4-latest → gpt-4o
|
|
gpt-4 → gpt-4o
|
|
gpt-3.5-latest → gpt-3.5-turbo
|
|
gpt-3.5 → gpt-3.5-turbo
|
|
codex-latest → codex-mini-latest
|
|
|
|
# Google Gemini
|
|
gemini-pro-latest → gemini-2.5-pro
|
|
gemini-flash-latest → gemini-2.5-flash
|
|
gemini-flash → gemini-2.5-flash
|
|
gemini-pro → gemini-2.5-pro
|
|
```
|
|
|
|
## Contributing
|
|
|
|
Contributions are welcome! Please see the [contribution guide](contribute/contribute.md) for guidelines.
|
|
|
|
## License
|
|
|
|
[MIT](LICENSE)
|
|
|
|
## Community
|
|
|
|
- [Discord](https://discord.gg/RqSS2NQVsY)
|
|
- [GitHub Issues](https://github.com/mark3labs/kit/issues)
|
|
- [Documentation](https://github.com/mark3labs/kit/wiki)
|