mirror of
https://github.com/mark3labs/kit.git
synced 2026-06-14 11:40:13 +00:00
Compare commits
297 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f5a696cfd | |||
| 10d05df015 | |||
| b0103e3cbf | |||
| c0827868b3 | |||
| e1badea340 | |||
| c2b70ea4b9 | |||
| 02b652fe59 | |||
| 91c37897e9 | |||
| 1b946b1815 | |||
| a391221424 | |||
| 62940d96d5 | |||
| 09088878e2 | |||
| 4798ea314e | |||
| 97c8d174fd | |||
| 2d1ecc5cba | |||
| 5eae413b91 | |||
| a75764fcdc | |||
| fd1a4d6910 | |||
| a77f1c1d6f | |||
| 245863b9f5 | |||
| 505e54318d | |||
| 097f2beeb7 | |||
| d1ba46b969 | |||
| c16f1938a2 | |||
| 9a57895c36 | |||
| f728f185a6 | |||
| bdbb3f7499 | |||
| 06db3f2ef9 | |||
| b9f1d1e90b | |||
| e9e5400546 | |||
| 82194f36bd | |||
| 9ed9b70b48 | |||
| fdc0e924bd | |||
| 1e9a87f3f7 | |||
| 9d4cefa521 | |||
| 358cbe8b03 | |||
| 240c3f9c63 | |||
| a241d1a6cd | |||
| c95a1c723f | |||
| ae36b8abd1 | |||
| 9ed9713985 | |||
| dccd43e049 | |||
| f40e424698 | |||
| 66e3308b4c | |||
| 5e3ac82c20 | |||
| b861501219 | |||
| 16c3924175 | |||
| eef2eef7de | |||
| f60b497fcd | |||
| b180b923ea | |||
| 4c8abad1e7 | |||
| ece392ee04 | |||
| 131d4d2c04 | |||
| c6cda4e679 | |||
| 1834da8186 | |||
| 4b9f95aa24 | |||
| 5a71f424d6 | |||
| 855805c461 | |||
| b418565a00 | |||
| b232c32a17 | |||
| 920e8fa208 | |||
| 0028e58a9b | |||
| 44c4527f84 | |||
| b3eef6f8e6 | |||
| 9e4813586e | |||
| b650f95c75 | |||
| a464dd984e | |||
| 637884b6be | |||
| e8a9f94679 | |||
| 979aa8969a | |||
| 9736164c02 | |||
| 2f52a270b6 | |||
| 1043a04b48 | |||
| 1f4ff9ccb5 | |||
| e3f1258870 | |||
| d381d970c1 | |||
| 401c4c621b | |||
| 1173c80a8f | |||
| a70dec6efa | |||
| d5826315dc | |||
| 0dc2cab65e | |||
| 7c0361245f | |||
| 0a8577f572 | |||
| 7dd23a57c2 | |||
| 3fdfed8df0 | |||
| a18bd5d828 | |||
| f9b1a6715e | |||
| 24a2dffe08 | |||
| 9de96a7d50 | |||
| ff3c30d651 | |||
| 9d6ce4eefb | |||
| e514713cbe | |||
| ccf0a1dda9 | |||
| bbf349952d | |||
| 08ecef02c5 | |||
| efdc81e42f | |||
| eef0467763 | |||
| 8d277bd550 | |||
| 0f373cd7c5 | |||
| 524ba2d971 | |||
| 0bc33fdf64 | |||
| 8dfbe49b98 | |||
| 7f7b3c527b | |||
| e21567ecf5 | |||
| 7295ef0e90 | |||
| 3115882e5e | |||
| 77e90d335a | |||
| 752d2797fa | |||
| f85a86a4a6 | |||
| e29c62333f | |||
| 9756682bcb | |||
| ec2c146dd2 | |||
| 5b6c1367c8 | |||
| 8b0a83b7d5 | |||
| e3d413ceef | |||
| 880b9dff37 | |||
| 687c092987 | |||
| 9ef8959b8b | |||
| 145be66dab | |||
| 8e9484ceb1 | |||
| 702c230090 | |||
| 8e6390d1c0 | |||
| 1e707653ff | |||
| 6e2fb58951 | |||
| f73dc7c338 | |||
| bbb651d12d | |||
| bdf2ed7fa0 | |||
| e0f6f3d762 | |||
| 8e068b14cd | |||
| cffda6b80c | |||
| 2f3970efd8 | |||
| 2369793637 | |||
| 9a84fee5d7 | |||
| 3c08f14a2f | |||
| e6f98776f3 | |||
| f85085a12e | |||
| adf9cfff76 | |||
| 32d4fc558f | |||
| 93fbcc40d5 | |||
| 76fe2851d1 | |||
| 7816d63a0e | |||
| 6d0109ce74 | |||
| 764e32c4fd | |||
| 7837be9d1f | |||
| fc64612282 | |||
| 649e67e344 | |||
| fbaedfb71d | |||
| 016929df2e | |||
| dbead16e4e | |||
| dfec8ef6ca | |||
| b3145e0f2f | |||
| a4f2aaa91a | |||
| 3257994ff8 | |||
| d161c930cd | |||
| 0c6b1c8307 | |||
| 2cae02c9ba | |||
| d56c2627ff | |||
| aa20be72a4 | |||
| ecb3b446f9 | |||
| 9e166ad6db | |||
| c2fbf21192 | |||
| 1ee23a7bf6 | |||
| 73dc7e5e20 | |||
| 1629e74b7d | |||
| 93def3b103 | |||
| 1ba4811536 | |||
| db695f9e38 | |||
| 76d57f3978 | |||
| edc406611e | |||
| 19ca9c60da | |||
| e5413157fc | |||
| 144f2e953c | |||
| a9d85c7bc2 | |||
| e2f85c469c | |||
| ee47fe7b0b | |||
| 144c873ce5 | |||
| 6e349633d8 | |||
| 1e1105045f | |||
| 042fd08a86 | |||
| b7269b8c7e | |||
| 7d9689bc3a | |||
| d6e9a0bb37 | |||
| 3d25fefb18 | |||
| 72a3d94066 | |||
| 0b25f0224e | |||
| c251b3b1d3 | |||
| e08002c6d7 | |||
| 868c836ae8 | |||
| a5045ddbfd | |||
| 0ee6a640ff | |||
| d728e4397c | |||
| 11b396c3aa | |||
| d82de1d63a | |||
| 70243c6136 | |||
| 1c46ad6e43 | |||
| 001975a0bc | |||
| 9e926998b8 | |||
| 78a3cf7a12 | |||
| 0a7d23104e | |||
| 44cb0fbc37 | |||
| e6dc292a60 | |||
| e6e949a559 | |||
| 5809583e36 | |||
| 94206cfb3d | |||
| 75708f46c1 | |||
| 707adc5088 | |||
| 2fb2983c1d | |||
| e1e1fdf271 | |||
| bd3ce2d3b0 | |||
| 498ff88a4b | |||
| 4d53a6a8bf | |||
| aa79357217 | |||
| e1f7e585bd | |||
| 55ff94eb3c | |||
| e389b492ae | |||
| f1ebf2cc05 | |||
| 0fa8d44217 | |||
| d583fd72d4 | |||
| 3a9493871d | |||
| f1d3b6cd8d | |||
| 83e0f8b9e3 | |||
| 0096c12253 | |||
| 8b6662263d | |||
| f2fb3bc41d | |||
| b53d1919e2 | |||
| 877d60034a | |||
| de84440d03 | |||
| 678d6a3925 | |||
| a090f088c0 | |||
| f04c6fe4ca | |||
| d3a441faa9 | |||
| aefdaaf465 | |||
| e9243b6eb3 | |||
| f7bd352266 | |||
| 3a7e53f938 | |||
| 69881eff50 | |||
| 2afe4489a4 | |||
| 43cf2100dd | |||
| 254896e02d | |||
| 13ec5721f5 | |||
| 6e26fb7764 | |||
| a6c4e70ac4 | |||
| b4af7e892b | |||
| e3b08effe5 | |||
| 35dc729860 | |||
| 76dcc2ba7f | |||
| 475fc3a1c0 | |||
| c2f45393bf | |||
| 8760c178c5 | |||
| f6cf5db412 | |||
| 67beb5446f | |||
| 11791d98c7 | |||
| 0774e8cfba | |||
| 713c3ed7d1 | |||
| ed9155a0a8 | |||
| 61c6c8e67b | |||
| 97f1bdf755 | |||
| 3105437279 | |||
| 9b610cb1cd | |||
| 119d7a58fd | |||
| bce4e90f80 | |||
| 0b7ec37fd4 | |||
| ab6f7f7751 | |||
| 350027abe7 | |||
| d98bba4746 | |||
| 4859b50eb0 | |||
| 082756c086 | |||
| 7df4089d01 | |||
| 6e1abeb3bd | |||
| 840954a598 | |||
| 5819801c96 | |||
| 4adede09cc | |||
| de6835b63b | |||
| 7d5118de1d | |||
| 18ddedd928 | |||
| 70bcdc1243 | |||
| f83d54144c | |||
| 019eee1104 | |||
| e9a963b8ae | |||
| 4fc24bf73d | |||
| 235f65582c | |||
| b811934d7e | |||
| 28d9a2fbb1 | |||
| c0c9787987 | |||
| 473c9b634b | |||
| 3e02930514 | |||
| a1038d8071 | |||
| d687d9ca7a | |||
| c254663081 | |||
| 12d19656d8 | |||
| b6da6aed75 | |||
| ce86806b0e | |||
| c54b5b78ae | |||
| 8c81b53c76 | |||
| 91ee4d7ffa | |||
| f752e3d1be | |||
| db274af1c6 |
@@ -1,79 +0,0 @@
|
||||
name: Bug Report
|
||||
description: Report a bug or issue with Kit
|
||||
title: "fix: "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Bug Description
|
||||
description: What happened? What did you expect to happen?
|
||||
placeholder: |
|
||||
The BorderColor field in ToolRenderConfig is documented but never applied
|
||||
during tool rendering. I expected the tool block to render with my custom
|
||||
color, but it uses the default styling instead.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Provide clear steps to reproduce the issue
|
||||
placeholder: |
|
||||
1. Create an extension with `api.RegisterToolRenderer(ext.ToolRenderConfig{...})`
|
||||
2. Set `BorderColor: "#89b4fa"` in the config
|
||||
3. Run a tool that uses this renderer
|
||||
4. Observe the border color is not applied
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: code
|
||||
attributes:
|
||||
label: Relevant Code / Configuration
|
||||
description: Paste any code, configuration, or error messages
|
||||
placeholder: |
|
||||
```go
|
||||
api.RegisterToolRenderer(ext.ToolRenderConfig{
|
||||
ToolName: "bash",
|
||||
DisplayName: "Shell",
|
||||
BorderColor: "#a6e3a1", // This is ignored!
|
||||
Background: "#1e1e2e", // This is ignored!
|
||||
})
|
||||
```
|
||||
render: go
|
||||
|
||||
- type: input
|
||||
id: component
|
||||
attributes:
|
||||
label: Affected Component
|
||||
description: Which part of Kit is affected?
|
||||
placeholder: e.g., extensions, ui, tool rendering, session management
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Kit Version
|
||||
description: What version of Kit are you running?
|
||||
placeholder: e.g., v0.1.0, commit hash, or "main"
|
||||
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other context, proposed fixes, or related issues
|
||||
placeholder: |
|
||||
The issue appears to be in `internal/ui/messages.go:RenderToolMessage()`
|
||||
which ignores the BorderColor and Background fields from ToolRendererData.
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Checklist
|
||||
options:
|
||||
- label: I've searched existing issues and this hasn't been reported yet
|
||||
required: true
|
||||
- label: I've tested with the latest version of Kit
|
||||
required: false
|
||||
@@ -1,11 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Kit Documentation
|
||||
url: https://github.com/mark3labs/kit/tree/main/www/pages
|
||||
about: Check the documentation before filing an issue
|
||||
- name: Extension Examples
|
||||
url: https://github.com/mark3labs/kit/tree/main/examples/extensions
|
||||
about: See working extension examples for reference
|
||||
- name: Discussions
|
||||
url: https://github.com/mark3labs/kit/discussions
|
||||
about: For questions, ideas, or general discussion
|
||||
@@ -1,40 +0,0 @@
|
||||
name: Documentation Issue
|
||||
description: Report missing, incorrect, or unclear documentation
|
||||
title: "docs: "
|
||||
labels: ["documentation"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Documentation Issue
|
||||
description: What's wrong or missing in the documentation?
|
||||
placeholder: |
|
||||
The ToolRenderConfig documentation mentions BorderColor and Background fields,
|
||||
but the code doesn't actually use them. The docs should either be updated
|
||||
to reflect reality, or the bug should be fixed.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: location
|
||||
attributes:
|
||||
label: Documentation Location
|
||||
description: Where is the affected documentation?
|
||||
placeholder: e.g., README.md, examples/extensions/tool-renderer-demo.go, pkg/kit docs
|
||||
|
||||
- type: textarea
|
||||
id: suggestion
|
||||
attributes:
|
||||
label: Suggested Improvement
|
||||
description: How should the documentation be improved?
|
||||
placeholder: |
|
||||
Add a note that BorderColor and Background are not yet implemented,
|
||||
or fix the bug and document the correct behavior.
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Checklist
|
||||
options:
|
||||
- label: I've checked that this documentation issue still exists in the latest version
|
||||
required: true
|
||||
@@ -1,64 +0,0 @@
|
||||
name: Feature Request
|
||||
description: Suggest a new feature or enhancement for Kit
|
||||
title: "feat: "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Feature Description
|
||||
description: What would you like to see added or changed?
|
||||
placeholder: |
|
||||
I'd like to be able to customize the border color of tool result blocks
|
||||
dynamically based on the tool type or result status.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: motivation
|
||||
attributes:
|
||||
label: Motivation / Use Case
|
||||
description: Why is this feature needed? What problem does it solve?
|
||||
placeholder: |
|
||||
When running multiple tools in sequence, it's hard to visually distinguish
|
||||
between file reads (blue), shell commands (green), and errors (red)
|
||||
without custom border colors.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: proposed
|
||||
attributes:
|
||||
label: Proposed Implementation
|
||||
description: How do you think this should work? (optional)
|
||||
placeholder: |
|
||||
Extend `ToolRenderConfig` to accept a function that receives the tool
|
||||
result and returns a color based on the content:
|
||||
|
||||
```go
|
||||
BorderColorFunc: func(result string, isError bool) string {
|
||||
if isError {
|
||||
return "#f38ba8"
|
||||
}
|
||||
return "#89b4fa"
|
||||
}
|
||||
```
|
||||
render: go
|
||||
|
||||
- type: checkboxes
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
options:
|
||||
- label: I've considered workarounds or alternative approaches
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Checklist
|
||||
options:
|
||||
- label: I've searched existing issues and this hasn't been requested yet
|
||||
required: true
|
||||
- label: This feature aligns with Kit's design philosophy (TUI-first, extension-based)
|
||||
required: false
|
||||
@@ -1,32 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.26"
|
||||
|
||||
- uses: golangci/golangci-lint-action@v7
|
||||
with:
|
||||
version: v2.10.1
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.26"
|
||||
|
||||
- run: go test -race ./...
|
||||
@@ -1,32 +0,0 @@
|
||||
name: Build and Deploy Docs to GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Install Dependencies
|
||||
working-directory: ./www
|
||||
run: bun install
|
||||
|
||||
- name: Build
|
||||
working-directory: ./www
|
||||
run: bun run build
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: JamesIves/github-pages-deploy-action@v4
|
||||
with:
|
||||
folder: www/out
|
||||
branch: gh-pages
|
||||
@@ -1,105 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Tag to use for npm publish'
|
||||
required: true
|
||||
skip_goreleaser:
|
||||
description: 'Skip goreleaser job (npm-only release)'
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write # Required for npm trusted publishing (OIDC)
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'push' || !inputs.skip_goreleaser }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.26"
|
||||
|
||||
- uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: "~> v2"
|
||||
args: release --clean
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
npm-publish:
|
||||
runs-on: ubuntu-latest
|
||||
needs: goreleaser
|
||||
if: ${{ always() && (needs.goreleaser.result == 'success' || needs.goreleaser.result == 'skipped') }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
- name: Set version from tag
|
||||
working-directory: npm
|
||||
run: |
|
||||
TAG=${{ inputs.tag || github.ref_name }}
|
||||
VERSION=${TAG#v}
|
||||
echo "Setting npm version to $VERSION"
|
||||
npm version $VERSION --no-git-tag-version
|
||||
|
||||
- name: Publish to npm
|
||||
working-directory: npm
|
||||
run: npm publish --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [goreleaser, npm-publish]
|
||||
if: ${{ always() && (needs.goreleaser.result == 'success' || needs.goreleaser.result == 'skipped') && (needs.npm-publish.result == 'success') }}
|
||||
steps:
|
||||
- name: Send Discord Notification
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.RELEASES_WEBHOOK }}
|
||||
TAG_NAME: ${{ inputs.tag || github.ref_name }}
|
||||
RELEASE_URL: https://github.com/${{ github.repository }}/releases/tag/${{ inputs.tag || github.ref_name }}
|
||||
run: |
|
||||
curl -H "Content-Type: application/json" \
|
||||
-X POST \
|
||||
-d "{
|
||||
\"embeds\": [{
|
||||
\"title\": \"New Release: $TAG_NAME\",
|
||||
\"description\": \"A new version of kit has been released!\",
|
||||
\"color\": 5814783,
|
||||
\"fields\": [
|
||||
{
|
||||
\"name\": \"Version\",
|
||||
\"value\": \"$TAG_NAME\",
|
||||
\"inline\": true
|
||||
},
|
||||
{
|
||||
\"name\": \"Repository\",
|
||||
\"value\": \"[kit](https://github.com/${{ github.repository }})\",
|
||||
\"inline\": true
|
||||
}
|
||||
],
|
||||
\"footer\": {
|
||||
\"text\": \"Released via GitHub Actions\"
|
||||
},
|
||||
\"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)\",
|
||||
\"url\": \"$RELEASE_URL\"
|
||||
}]
|
||||
}" \
|
||||
$DISCORD_WEBHOOK
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
.aider*
|
||||
.task/
|
||||
.env
|
||||
.kit/*
|
||||
!.kit/extensions/
|
||||
!.kit/prompts/
|
||||
aidocs/
|
||||
*.log
|
||||
/kit
|
||||
.idea
|
||||
build/
|
||||
dist/
|
||||
contribute/output/
|
||||
CONTEXT.md
|
||||
output/
|
||||
.agents/
|
||||
skills-lock.json
|
||||
@@ -1,9 +0,0 @@
|
||||
version: "2"
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- modernize
|
||||
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
@@ -1,70 +0,0 @@
|
||||
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
|
||||
version: 2
|
||||
|
||||
builds:
|
||||
- main: ./cmd/kit
|
||||
binary: kit
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- darwin
|
||||
- linux
|
||||
- windows
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
ldflags:
|
||||
- -s -w
|
||||
- -X main.version={{.Version}}
|
||||
- -X main.commit={{.Commit}}
|
||||
- -X main.date={{.Date}}
|
||||
|
||||
archives:
|
||||
- formats: [tar.gz]
|
||||
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
formats: [zip]
|
||||
|
||||
checksum:
|
||||
name_template: checksums.txt
|
||||
|
||||
release:
|
||||
header: |
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Bun / npm
|
||||
bun add -g @mark3labs/kit
|
||||
# or: npm install -g @mark3labs/kit
|
||||
|
||||
# Go install (requires Go 1.26+)
|
||||
go install github.com/mark3labs/kit/cmd/kit@latest
|
||||
|
||||
# Or download from assets below
|
||||
```
|
||||
|
||||
changelog:
|
||||
sort: asc
|
||||
use: github
|
||||
filters:
|
||||
exclude:
|
||||
- "^Merge"
|
||||
- "^merge"
|
||||
- "^wip"
|
||||
- "^WIP"
|
||||
groups:
|
||||
- title: "Features"
|
||||
regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
|
||||
order: 0
|
||||
- title: "Bug Fixes"
|
||||
regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$'
|
||||
order: 1
|
||||
- title: "Documentation"
|
||||
regexp: '^.*?docs(\([[:word:]]+\))??!?:.+$'
|
||||
order: 2
|
||||
- title: "Maintenance"
|
||||
regexp: '^.*?(chore|refactor|style|ci|build)(\([[:word:]]+\))??!?:.+$'
|
||||
order: 3
|
||||
- title: "Other Changes"
|
||||
order: 999
|
||||
@@ -1 +0,0 @@
|
||||
{"Created":"2026-02-25T21:53:09.725157606Z","name":"iteratr_events","subjects":["iteratr.\u003e"],"retention":"limits","max_consumers":-1,"max_msgs":-1,"max_bytes":-1,"max_age":2592000000000000,"max_msgs_per_subject":-1,"max_msg_size":-1,"discard":"old","storage":"file","num_replicas":1,"duplicate_window":120000000000,"compression":"none","allow_direct":false,"mirror_direct":false,"sealed":false,"deny_delete":false,"deny_purge":false,"allow_rollup_hdrs":false,"consumer_limits":{}}
|
||||
@@ -1 +0,0 @@
|
||||
0d94ed0d599988d1
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"Created":"0001-01-01T00:00:00Z","Name":"","name":"7UfQJgqo","deliver_policy":"all","ack_policy":"explicit","ack_wait":30000000000,"max_deliver":-1,"filter_subject":"iteratr.unified-bubbletea-architecture.\u003e","replay_policy":"instant","max_waiting":512,"max_ack_pending":1000,"inactive_threshold":5000000000,"num_replicas":0}
|
||||
@@ -1 +0,0 @@
|
||||
0a75862a3a998ab5
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"Created":"0001-01-01T00:00:00Z","Name":"","name":"EnXXTfbX","deliver_policy":"all","ack_policy":"explicit","ack_wait":30000000000,"max_deliver":-1,"filter_subject":"iteratr.unified-bubbletea-architecture.\u003e","replay_policy":"instant","max_waiting":512,"max_ack_pending":1000,"inactive_threshold":5000000000,"num_replicas":0}
|
||||
@@ -1 +0,0 @@
|
||||
3288f873d6615ff9
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
39825
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
description: Run ACP smoke test against opencode/kimi-k2.5 to verify JSON-RPC stdio works
|
||||
---
|
||||
|
||||
Run the ACP smoke test to verify the Kit ACP server works correctly over JSON-RPC stdio with streaming responses.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Build the kit binary:
|
||||
```bash
|
||||
go build -o output/kit ./cmd/kit
|
||||
```
|
||||
|
||||
2. Run the smoke test Python script against opencode/kimi-k2.5:
|
||||
```bash
|
||||
python3 scripts/acp_smoke_test.py
|
||||
```
|
||||
|
||||
3. Verify the output shows:
|
||||
- `session/new` returns a valid `sessionId`
|
||||
- `session/prompt` streams `agent_thought_chunk` notifications (reasoning)
|
||||
- `session/prompt` streams `agent_message_chunk` notifications (response)
|
||||
- Final result has `stopReason: "end_turn"`
|
||||
- `✓ SMOKE TEST PASSED` at the end
|
||||
|
||||
4. If the test fails, check:
|
||||
- `output/kit` binary exists and is executable
|
||||
- `OPENCODE_API_KEY` or `OPENCODE_ZEN_API_KEY` environment variable is set
|
||||
- `scripts/acp_smoke_test.py` exists
|
||||
- The model `opencode/kimi-k2.5` is available (`kit models opencode | grep kimi-k2.5`)
|
||||
|
||||
5. For testing with a different model, edit the script or set the `MODEL` variable:
|
||||
```bash
|
||||
MODEL=anthropic/claude-sonnet-4-5 python3 scripts/acp_smoke_test.py
|
||||
```
|
||||
|
||||
The smoke test exercises the full ACP protocol: session lifecycle, streaming notifications, and tool-free prompt completion.
|
||||
@@ -1,146 +0,0 @@
|
||||
---
|
||||
description: Read-only audit for dead code, duplication, boundary violations, and refactor opportunities
|
||||
---
|
||||
|
||||
Perform a comprehensive **read-only** audit of this repository and report
|
||||
findings. **Do not edit, rename, or delete any files.** Optional focus / scope
|
||||
hints from the user: $@
|
||||
|
||||
## Scope
|
||||
|
||||
If the user supplied focus hints above (a package path, a subsystem name, a
|
||||
concern like "TUI" or "extensions"), scope the audit accordingly. Otherwise
|
||||
audit the whole repo, prioritising the highest-traffic packages first
|
||||
(`cmd/`, `internal/`, `pkg/kit/` for this repo).
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Map the repo first**:
|
||||
- `ls` / `find` the top-level layout and list every Go package
|
||||
- Read `AGENTS.md`, `README.md`, and any `pkg/*/doc.go` to understand the
|
||||
intended architectural boundaries (SDK vs internal vs TUI vs cmd vs
|
||||
extension surface)
|
||||
- Note the public SDK surface (`pkg/kit/`) and any documented invariants
|
||||
(e.g. "no dependency name leakage", "UI never imports extensions
|
||||
directly") — these define what counts as a violation
|
||||
|
||||
2. **Hunt for dead code**:
|
||||
- Run `go vet ./...` and capture warnings
|
||||
- Use `grep` to find exported symbols (`^func [A-Z]`, `^type [A-Z]`,
|
||||
`^var [A-Z]`, `^const [A-Z]`) and cross-reference call sites. Symbols
|
||||
with zero non-test references inside the module are suspects
|
||||
- Check for unreferenced files, `// TODO: remove` markers, commented-out
|
||||
blocks, and `_ = x` discard patterns
|
||||
- If `staticcheck`, `deadcode`, or `unused` are available on PATH, run
|
||||
them and include their output verbatim
|
||||
- **Do not delete anything** — list candidates with file:line and a
|
||||
confidence level (high / medium / low)
|
||||
|
||||
3. **Find unnecessary duplication**:
|
||||
- Look for near-identical function bodies, struct shapes, or switch
|
||||
statements across packages — `grep` for repeated function signatures
|
||||
and copy-pasted string literals / error messages is a fast first pass
|
||||
- Distinguish *coincidental* duplication (two things that happen to look
|
||||
alike but evolve independently) from *unnecessary* duplication (same
|
||||
intent, drifting in lockstep) — only flag the latter
|
||||
- For each cluster, propose where the extracted helper should live
|
||||
(which package, which file) and whether it crosses a boundary
|
||||
|
||||
4. **Check concerns / boundary violations**:
|
||||
- **SDK leakage**: grep `pkg/kit/` for imports of `internal/...` types
|
||||
in exported signatures, and for dependency-name leakage in exported
|
||||
names / godoc (e.g. library jargon appearing in `LLM*` types)
|
||||
- **UI ↔ extensions**: grep `internal/ui/` for any import of
|
||||
`internal/extensions/` — per AGENTS.md the UI must not import
|
||||
extensions directly; converters in `cmd/root.go` should bridge them
|
||||
- **cmd vs internal**: business logic living in `cmd/` that should be
|
||||
in `internal/` (and vice versa)
|
||||
- **Cyclic risk**: packages that import each other transitively or that
|
||||
reach across sibling boundaries unexpectedly
|
||||
- For each violation, cite the offending import / signature with
|
||||
file:line
|
||||
|
||||
5. **Spot refactor opportunities**:
|
||||
- Long functions (>80 lines) doing multiple unrelated things
|
||||
- Deeply nested conditionals that flatten well with early returns
|
||||
- Repeated `if err != nil { return fmt.Errorf("...: %w", err) }` chains
|
||||
that could become helpers — but only where the wrapping context is
|
||||
genuinely uniform
|
||||
- Structs with too many fields that hint at split responsibilities
|
||||
- Exported APIs that would be cleaner with options structs / functional
|
||||
options
|
||||
- Tests that share setup boilerplate ripe for a helper
|
||||
- Flag each with: location, current shape (1-2 lines), proposed shape
|
||||
(1-2 lines), and estimated risk (low / medium / high)
|
||||
|
||||
6. **Cross-check against project rules**:
|
||||
- Re-read `AGENTS.md` "Key Patterns" section and verify nothing in your
|
||||
findings contradicts the documented gotchas (Yaegi interface ban,
|
||||
`prog.Send()` from `Update()`, function-field bug, etc.) — if a
|
||||
"refactor" would reintroduce a known pitfall, drop it from the report
|
||||
and note why
|
||||
|
||||
7. **Write the report** as your final message (do not write it to disk)
|
||||
structured as:
|
||||
|
||||
```
|
||||
# Code Audit Report
|
||||
|
||||
## Summary
|
||||
- N dead-code candidates
|
||||
- N duplication clusters
|
||||
- N boundary violations
|
||||
- N refactor opportunities
|
||||
|
||||
## Dead Code
|
||||
### High confidence
|
||||
- path/to/file.go:LINE — symbol — reason
|
||||
|
||||
### Medium confidence
|
||||
...
|
||||
|
||||
## Duplication
|
||||
### Cluster: <short name>
|
||||
- Sites: file:line, file:line, …
|
||||
- Suggested home: package/path
|
||||
- Notes: …
|
||||
|
||||
## Boundary Violations
|
||||
- Rule: <which rule from AGENTS.md / project convention>
|
||||
- Offender: file:line
|
||||
- Fix sketch: …
|
||||
|
||||
## Refactor Opportunities
|
||||
- Location: file:line
|
||||
- Current: …
|
||||
- Proposed: …
|
||||
- Risk: low/medium/high
|
||||
- Why it's worth it: …
|
||||
|
||||
## Suggested Next Steps
|
||||
1. …
|
||||
2. …
|
||||
```
|
||||
|
||||
8. **End the report with an explicit reminder** that no files were modified,
|
||||
and recommend the user pick the highest-leverage items to act on
|
||||
manually (or via a follow-up `/fix-issue` style prompt) rather than
|
||||
running a sweeping refactor.
|
||||
|
||||
## Guidelines
|
||||
|
||||
- **Read-only, always**: no `edit`, no `write`, no `git commit`, no `go mod
|
||||
tidy`. Use only `read`, `grep`, `find`, `ls`, and read-only `bash`
|
||||
commands (`go vet`, `go build -o /tmp/...`, `staticcheck`, etc.)
|
||||
- **Cite every finding** with `path/to/file.go:LINE` so the user can jump
|
||||
straight to it
|
||||
- **Be honest about confidence**: false positives in a code audit are
|
||||
expensive — prefer "medium confidence, worth a look" over confidently
|
||||
wrong claims
|
||||
- **Quantity isn't quality**: 10 sharp findings beat 100 nitpicks. Cut
|
||||
anything that's purely stylistic unless it directly causes one of the
|
||||
four issue categories above
|
||||
- **Skip generated code** (`*.pb.go`, `*_gen.go`, anything under
|
||||
`vendor/`) and obvious third-party copies
|
||||
- **Don't propose architectural rewrites** — stay within the existing
|
||||
shape of the repo and recommend incremental, reviewable changes
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
description: Stage, commit, and push changes with an auto-generated conventional commit message
|
||||
---
|
||||
|
||||
Review the current git status and diff, then stage all changes, write a concise conventional commit message, commit, and push to the current branch.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Check status**: `git status` — understand what has changed
|
||||
2. **Review the diff**: `git diff` (and `git diff --cached` if anything is already staged) — read the actual changes
|
||||
3. **Stage everything**: `git add -A`
|
||||
4. **Craft the commit message** following Conventional Commits:
|
||||
- Format: `<type>(<scope>): <short summary>`
|
||||
- Types: `feat`, `fix`, `refactor`, `chore`, `docs`, `test`, `perf`, `build`
|
||||
- Scope: optional, the subsystem affected (e.g. `ui`, `cmd`, `config`)
|
||||
- Summary: imperative mood, lowercase, no trailing period, ≤72 chars
|
||||
- Body: add a blank line then bullet points for non-trivial changes
|
||||
- Do **not** include "Generated by" or similar noise
|
||||
5. **Commit**: `git commit -m "<message>"`
|
||||
6. **Push**: `git push`
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Read the actual diff — do not guess from filenames alone
|
||||
- Prefer one well-scoped commit; do not split unless the changes are clearly unrelated
|
||||
- Keep the subject line under 72 characters
|
||||
- Use the body to explain *what* and *why*, not *how*
|
||||
- If there is nothing to commit, say so and stop
|
||||
|
||||
$@
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
description: Open a GitHub PR for the current branch using the repo's PR template
|
||||
---
|
||||
|
||||
Open a GitHub pull request for the current branch, filling out the repository's PR template with a description grounded in the actual commits and diff.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Verify the branch is pushed**:
|
||||
- `git status -sb` and `git log @{u}..HEAD --oneline 2>/dev/null` — if there is no upstream or unpushed commits, run `git push -u origin "$(git branch --show-current)"` first
|
||||
- If the working tree is dirty, stop and tell the user to commit first (suggest `/commit-push`)
|
||||
2. **Gather context**:
|
||||
- `git log origin/main..HEAD --oneline` — list of commits going into the PR
|
||||
- `git diff origin/main...HEAD --stat` then `git diff origin/main...HEAD` — read the actual changes
|
||||
- Identify the linked issue (from commit messages, branch name, or extra user input: $@) — capture as `Fixes #N` if applicable
|
||||
3. **Locate the PR template**:
|
||||
- Check `.github/pull_request_template.md`, `.github/PULL_REQUEST_TEMPLATE.md`, or `docs/pull_request_template.md`
|
||||
- If none exists, use a minimal `## Description` / `## Type of Change` / `## Checklist` structure
|
||||
4. **Draft the PR body** by filling out the template:
|
||||
- **Description**: 1–3 short paragraphs explaining *what* changed and *why*, grounded in the diff. Include a brief before/after example for new APIs when useful.
|
||||
- **Fixes #N**: only if there is a real linked issue
|
||||
- **Type of Change**: tick the single most accurate box with `[x]` (leave others as `[ ]`)
|
||||
- **Checklist**: tick items that are genuinely true (style, self-review, tests added, docs updated)
|
||||
- **Additional Information**: bullet list of added / modified files and any backward-compatibility notes
|
||||
- Remove template sections explicitly marked "remove if not applicable" (e.g. MCP Spec Compliance) when they don't apply
|
||||
5. **Write the body to a temp file**: `/tmp/pr-body-<branch-or-issue>.md` — never inline a long body via `--body`, always use `--body-file`
|
||||
6. **Choose the title**: prefer the subject of the primary commit if it already follows Conventional Commits; otherwise craft one in the same style (`<type>(<scope>): <imperative summary>`, ≤72 chars)
|
||||
7. **Create the PR**:
|
||||
```
|
||||
gh pr create \
|
||||
--title "<title>" \
|
||||
--body-file /tmp/pr-body-<...>.md \
|
||||
--base main \
|
||||
--head "$(git branch --show-current)"
|
||||
```
|
||||
Use the repo's actual default branch if it isn't `main` (`gh repo view --json defaultBranchRef -q .defaultBranchRef.name`)
|
||||
8. **Report the PR URL** returned by `gh` and stop
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Read the diff and commit messages — do **not** invent features that aren't in the code
|
||||
- One PR per logical change; if the branch contains unrelated commits, surface that and ask before continuing
|
||||
- Keep the description focused on reviewer-relevant information (what / why), not a replay of the diff
|
||||
- Only check checklist boxes that are actually satisfied; leave the rest unchecked rather than lying
|
||||
- If `gh` is not authenticated (`gh auth status` fails), stop and tell the user
|
||||
|
||||
$@
|
||||
@@ -1,86 +0,0 @@
|
||||
---
|
||||
description: Create a feature request using the GitHub template
|
||||
---
|
||||
|
||||
Create a feature request for the Kit repository. The user wants to request: $@
|
||||
|
||||
## Feature Request Template
|
||||
|
||||
This prompt uses the `feature_request` GitHub template which requires:
|
||||
|
||||
| Field | Required | Purpose |
|
||||
|-------|----------|---------|
|
||||
| **Feature Description** | Yes | What should be added or changed |
|
||||
| **Motivation / Use Case** | Yes | Why is this needed? What problem does it solve? |
|
||||
| **Proposed Implementation** | No | How do you think this should work? |
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Understand the request** from the user input: $@
|
||||
- What capability is missing?
|
||||
- What would the ideal behavior look like?
|
||||
|
||||
2. **Ask clarifying questions** if needed:
|
||||
- "What problem does this solve for you?"
|
||||
- "How would you expect this to work?"
|
||||
- "Are there similar features in other tools you use?"
|
||||
|
||||
3. **Craft the title** using conventional format:
|
||||
- `feat: <short description>`
|
||||
- Lowercase, imperative mood, ≤72 chars
|
||||
- Good examples:
|
||||
- `feat: add keyboard shortcut for clearing input`
|
||||
- `feat: support custom themes per extension`
|
||||
- `feat: add fuzzy matching to model selector`
|
||||
- Bad examples:
|
||||
- `Feature request: can we have...` (too vague)
|
||||
- `It would be nice if...` (not imperative)
|
||||
|
||||
4. **Build the body** with the template fields:
|
||||
|
||||
**Feature Description:**
|
||||
- Clear statement of what to add/change
|
||||
- Be specific about the behavior
|
||||
- Include UI/UX details if relevant
|
||||
|
||||
**Motivation / Use Case:**
|
||||
- What problem does this solve?
|
||||
- Current workaround (if any) and why it's insufficient
|
||||
- Who benefits from this feature?
|
||||
|
||||
**Proposed Implementation** (optional but helpful):
|
||||
- High-level approach
|
||||
- API changes if applicable
|
||||
- Example usage code
|
||||
|
||||
5. **Create the issue**:
|
||||
```bash
|
||||
gh issue create --template feature_request --title "feat: ..." --body "..."
|
||||
```
|
||||
|
||||
6. **Confirm success**:
|
||||
- Show the issue URL and number
|
||||
- Mention it was created with the feature_request template
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Focus on the *problem* first, then the solution
|
||||
- Include concrete examples of how the feature would be used
|
||||
- Consider edge cases and mention them
|
||||
- If proposing API changes, show before/after code
|
||||
- Check if similar features exist in related tools (mention them for reference)
|
||||
- Align with Kit's philosophy: TUI-first, extension-based, keyboard-driven
|
||||
|
||||
## Example
|
||||
|
||||
User: `/feature-request I want to be able to customize tool border colors dynamically`
|
||||
|
||||
You:
|
||||
1. Title: `feat: dynamic border colors for tool results based on status`
|
||||
2. Body:
|
||||
- **Feature Description**: Allow `ToolRenderConfig` to accept a function that determines border color based on tool result content or status, enabling dynamic visual feedback.
|
||||
- **Motivation**: When running multiple tools, it's hard to distinguish file reads (blue), shell commands (green), and errors (red) without custom colors per result.
|
||||
- **Proposed Implementation**: Add `BorderColorFunc` callback that receives `(result string, isError bool)` and returns a color string.
|
||||
|
||||
3. Execute: `gh issue create --template feature_request --title "feat: ..." --body "..."`
|
||||
4. Confirm: Created issue #43 using feature_request template
|
||||
@@ -1,100 +0,0 @@
|
||||
---
|
||||
description: File a GitHub issue using the appropriate template
|
||||
---
|
||||
|
||||
File a GitHub issue for the Kit repository. The user wants to create an issue about: $@
|
||||
|
||||
## Issue Templates Available
|
||||
|
||||
This repository has structured issue templates. You MUST use the appropriate template:
|
||||
|
||||
| Type | Template | Use For |
|
||||
|------|----------|---------|
|
||||
| `bug` | `bug_report` | Something is broken, not working as expected |
|
||||
| `feat` | `feature_request` | New feature, enhancement, improvement |
|
||||
| `docs` | `documentation` | Missing, incorrect, or unclear documentation |
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Determine the issue type** from the user input: $@
|
||||
- Bug → use `--template bug_report`
|
||||
- Feature → use `--template feature_request`
|
||||
- Documentation → use `--template documentation`
|
||||
|
||||
2. **Ask clarifying questions** if critical info is missing:
|
||||
- For bugs: "What were you doing when this happened?" (reproduction steps)
|
||||
- For features: "What problem does this solve?" (motivation)
|
||||
- For docs: "Where did you look for this information?" (location)
|
||||
|
||||
3. **Craft the title** using conventional format:
|
||||
- `<type>: <short description>`
|
||||
- Lowercase, imperative mood, ≤72 chars
|
||||
- Examples:
|
||||
- `fix: ToolRenderConfig BorderColor ignored during rendering`
|
||||
- `feat: add keyboard shortcut for clearing input`
|
||||
- `docs: clarify extension widget lifecycle`
|
||||
|
||||
4. **File the issue** using the template:
|
||||
```bash
|
||||
# For bugs
|
||||
gh issue create --template bug_report --title "fix: ..." --body "..."
|
||||
|
||||
# For features
|
||||
gh issue create --template feature_request --title "feat: ..." --body "..."
|
||||
|
||||
# For documentation
|
||||
gh issue create --template documentation --title "docs: ..." --body "..."
|
||||
```
|
||||
|
||||
The template will guide the user through the required fields. You need to provide:
|
||||
- **Bug reports**: Description, reproduction steps, expected vs actual behavior
|
||||
- **Feature requests**: Description, motivation/use case, optional proposed implementation
|
||||
- **Documentation**: Description, location of docs, suggested improvement
|
||||
|
||||
5. **Confirm success** by showing:
|
||||
- The issue URL
|
||||
- The issue number
|
||||
- Which template was used
|
||||
|
||||
## Template Field Guide
|
||||
|
||||
### Bug Report (`bug_report`)
|
||||
Required fields in the body:
|
||||
- **Bug Description** - what happened vs expected
|
||||
- **Steps to Reproduce** - numbered list to recreate the bug
|
||||
- **Relevant Code** - code snippets, configuration, error messages
|
||||
- **Component** - which part of Kit (ui, extensions, session, etc.)
|
||||
- **Version** - Kit version or commit hash
|
||||
|
||||
### Feature Request (`feature_request`)
|
||||
Required fields in the body:
|
||||
- **Feature Description** - what to add/change
|
||||
- **Motivation / Use Case** - why this is needed
|
||||
- **Proposed Implementation** - how it could work (optional)
|
||||
|
||||
### Documentation (`documentation`)
|
||||
Required fields in the body:
|
||||
- **Documentation Issue** - what's wrong or missing
|
||||
- **Documentation Location** - file or URL where docs exist
|
||||
- **Suggested Improvement** - how to fix the docs
|
||||
|
||||
## Guidelines
|
||||
|
||||
- ALWAYS use `--template <name>` instead of bare `gh issue create`
|
||||
- Include file paths and line numbers when you know them
|
||||
- Use triple backticks for code blocks
|
||||
- Keep the body factual - avoid speculation unless in "Proposed Fix" section
|
||||
- If you're unsure about technical details, say so in the issue
|
||||
- For UI bugs, describe what you see vs what you expect
|
||||
- For API bugs, include the relevant struct/function names
|
||||
|
||||
## Example Usage
|
||||
|
||||
User: `/file-issue The ToolRenderConfig BorderColor field is documented but never used in rendering`
|
||||
|
||||
You:
|
||||
1. Determine this is a **bug** (documented field doesn't work)
|
||||
2. Use `--template bug_report`
|
||||
3. Gather: reproduction steps (register renderer with BorderColor), expected (custom color), actual (default color)
|
||||
4. Create issue with title `fix: ToolRenderConfig BorderColor and Background fields are ignored`
|
||||
5. Confirm: Created issue #42 using bug_report template
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
description: Implement the fix/feature/docs change requested by a GitHub issue
|
||||
---
|
||||
|
||||
Resolve GitHub issue #$1 by reading it, classifying it, and producing the appropriate code or doc change. **Stop once the working tree contains the change** — committing, pushing, and opening a PR are handled by `/commit-push` and `/create-pr`.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Fetch the issue**:
|
||||
- Run: gh issue view $1 --json number,title,body,labels,state,author,comments
|
||||
- If the issue is closed, stop and ask the user whether to proceed
|
||||
- Read the **entire** thread including comments — the latest comment often refines the ask
|
||||
|
||||
2. **Classify the issue** from labels, title prefix, and body content:
|
||||
- `bug` / `fix:` → reproduce, then fix
|
||||
- `enhancement` / `feature` / `feat:` → design, then implement
|
||||
- `documentation` / `docs:` → locate and update docs
|
||||
- `question` / `discussion` → answer in a comment, do **not** write code
|
||||
- Anything else → ask the user how to proceed
|
||||
|
||||
3. **Create a working branch** off the default branch:
|
||||
- `git checkout main && git pull --ff-only`
|
||||
- Branch name: <type>/$1-<slug> (e.g. `fix/42-borderColor-ignored`, `feat/57-keyboard-clear`, `docs/63-widget-lifecycle`)
|
||||
|
||||
4. **Do the work** based on type:
|
||||
|
||||
### Bug (`bug` label / `fix:` title)
|
||||
- Reproduce the failure first (write a failing test if feasible) — if you cannot reproduce, comment on the issue asking for clarification and stop
|
||||
- Locate the root cause; do not patch symptoms
|
||||
- Add or extend a regression test that fails before and passes after the fix
|
||||
- Run `go test ./... -race` and `golangci-lint run`
|
||||
|
||||
### Feature (`enhancement` / `feature` label / `feat:` title)
|
||||
- Re-read the motivation and proposed implementation in the issue body
|
||||
- For large, ambiguous, or breaking changes, sketch the design in a comment on the issue and wait for sign-off before writing code
|
||||
- Implement behind sensible defaults; add godoc on every exported symbol
|
||||
- Add unit tests covering the new behaviour and edge cases
|
||||
- Update `README.md` / `docs/` if the public surface changed
|
||||
- Run `go test ./... -race` and `golangci-lint run`
|
||||
|
||||
### Documentation (`documentation` label / `docs:` title)
|
||||
- Open the file/URL referenced in the issue's "Documentation Location"
|
||||
- Apply the suggested improvement; verify code samples compile (`go build ./...`)
|
||||
- No tests required, but run `golangci-lint run` if Go files were touched
|
||||
|
||||
5. **Report**:
|
||||
- Branch name (`git branch --show-current`)
|
||||
- Summary of files changed (`git status -s`) and the diff highlights
|
||||
- Test/lint results (pass/fail with key output)
|
||||
- Suggest the next step explicitly:
|
||||
- `/commit-push` to commit with a Conventional Commit subject (the message should reference `(#$1)` and include `Fixes #$1` so merge auto-closes)
|
||||
- then `/create-pr $1` to open the pull request
|
||||
|
||||
## Guidelines
|
||||
|
||||
- This prompt **stops at a clean working tree with the change applied** — do not run `git commit`, `git push`, or `gh pr create`
|
||||
- If the issue is unclear, post a clarifying comment on the issue and stop; do not guess
|
||||
- Keep the change scoped to the issue; surface unrelated cleanups separately
|
||||
- For breaking changes or architecture shifts, propose the design on the issue first and wait for maintainer sign-off
|
||||
- If the issue is a duplicate or already fixed on `main`, comment with the reference and stop
|
||||
- Do not close the issue manually — the eventual PR's `Fixes #$1` handles that on merge
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
description: Scaffold a new prompt template in .kit/prompts/
|
||||
---
|
||||
|
||||
Create a new kit prompt template. The user wants a prompt that does: $@
|
||||
|
||||
## What a prompt template is
|
||||
|
||||
A prompt template is a `.md` file in `.kit/prompts/` (project-local) or `~/.kit/prompts/` (global).
|
||||
It becomes a `/slug` slash command in the kit input box — typed as `/filename` with optional arguments.
|
||||
|
||||
## File format
|
||||
|
||||
```
|
||||
---
|
||||
description: One-line description shown in autocomplete
|
||||
---
|
||||
|
||||
Body text of the prompt. Reference user-supplied arguments
|
||||
with positional placeholders (see "Argument placeholders" below).
|
||||
```
|
||||
|
||||
- **Filename** → slug: `commit-push.md` becomes `/commit-push`
|
||||
- **Frontmatter**: only `description` is recognised; keep it under ~80 chars
|
||||
- **Body**: plain markdown; the full text is submitted as the user's message when the template fires
|
||||
- **Required args**: kit infers required positional args from the highest `$N` it finds *outside* backtick/tilde code fences — a stray `$2` in active prose means kit will refuse to run without 2 arguments
|
||||
|
||||
## Argument placeholders
|
||||
|
||||
kit performs shell-style substitution before sending the prompt to the model:
|
||||
|
||||
- `$1`, `$2`, … — positional arguments (1-indexed)
|
||||
- `${1}`, `${2}`, … — same, brace form (use when followed by digits/letters: `${1}_suffix`)
|
||||
- `$@` — all arguments joined by spaces (zero or more, optional)
|
||||
- `$+` — all arguments, **at least one required**
|
||||
- `$ARGUMENTS` / `${ARGUMENTS}` — alias for `$@`
|
||||
- `${@:N}` — args from the Nth onwards (1-indexed, bash-style)
|
||||
- `${@:N:L}` — `L` args starting from the Nth
|
||||
|
||||
### ⚠️ Critical: code fences and inline code preserve placeholders verbatim
|
||||
|
||||
Anything inside triple-backtick fences, `~~~` fences, or single-backtick `inline` code spans is **left untouched** so example code samples don't get corrupted. That means:
|
||||
|
||||
- An inline-coded `gh issue view $1` stays literal `$1` in the model's input ❌
|
||||
- The same command without backticks: gh issue view $1 → expands to `gh issue view 42` ✓
|
||||
|
||||
**Rule of thumb:** if you want a placeholder to substitute, keep it outside backticks and fences. If you want a literal `$1` in the output (e.g. teaching the user shell syntax), put it inside backticks.
|
||||
|
||||
### Workarounds for "I want it to look like code AND substitute"
|
||||
|
||||
1. **Drop the backticks** around just the placeholder portion — the rest can still read as a command line in prose
|
||||
2. **Use a 4-space-indented code block** instead of a triple-backtick fence — kit only skips backtick/tilde fences, so indentation-style code blocks still get substitution:
|
||||
|
||||
git push -u origin "$(git branch --show-current)"
|
||||
gh pr create --title "fix: ... (#$1)" --base main
|
||||
|
||||
3. **Bind once, reference loosely**: put `Issue: $1` at the top in prose, then leave the backticked examples literal — the model will substitute mentally
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Understand the workflow** the user described in $@ — ask a clarifying question if the intent is ambiguous
|
||||
2. **Choose a filename**: short, lowercase, hyphen-separated, descriptive (e.g. `code-review.md`)
|
||||
3. **Write the description**: one sentence, imperative, fits in autocomplete
|
||||
4. **Decide on arguments**:
|
||||
- No args needed → omit placeholders entirely
|
||||
- One required value (issue number, PR url, file path) → use `$1`
|
||||
- Free-form trailing context → end with a single `$@` line
|
||||
- Multiple distinct values → use `$1`, `$2`, … and document each at the top
|
||||
5. **Draft the body**:
|
||||
- Open with a single sentence stating the goal, weaving in `$1`/`$@` where the value belongs
|
||||
- Use `## Steps` for multi-step workflows; use plain prose for simple prompts
|
||||
- Be specific: name commands, flags, and file paths where relevant
|
||||
- **Audit every backtick and code fence**: any `$N` or `$@` inside them will not expand — was that intentional? If not, apply one of the workarounds above
|
||||
6. **Write the file** to `.kit/prompts/<slug>.md`
|
||||
7. **Verify substitution** by mentally (or actually) replacing `$1`/`$@` with a sample value and confirming every reference resolves — and that the prompt's *own* example snippets don't accidentally bump the required-arg count (wrap illustrative `$N` examples in triple-backtick fences, not 4-space indentation, so `RequiredArgs()` ignores them)
|
||||
8. **Confirm** by showing the final file content and the slash command that activates it (e.g. `/code-review 42`)
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Keep prompts action-oriented — they should tell kit *what to do*, not just *what to think about*
|
||||
- Prefer concrete steps over vague instructions
|
||||
- A prompt that does one thing well beats one that tries to cover every edge case
|
||||
- If the workflow already exists as a prompt, suggest extending it instead of duplicating
|
||||
- When in doubt about substitution behaviour, write the file and run `/<slug> testvalue` once to confirm — wrong placement of backticks is the #1 failure mode
|
||||
@@ -1,70 +0,0 @@
|
||||
---
|
||||
description: Semantic version tagging workflow - analyzes commits and tags releases
|
||||
---
|
||||
|
||||
# Release Tagging Workflow
|
||||
|
||||
Tag a new version of this Go project following semantic versioning.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Fetch remote tags**: `git fetch --tags origin`
|
||||
|
||||
2. **Find latest version**: `git tag -l | sort -V | tail -5` to see recent tags
|
||||
|
||||
3. **Analyze changes since last tag**:
|
||||
- `git log <latest-tag>..HEAD --oneline` - list commits
|
||||
- `git diff <latest-tag>..HEAD --stat` - see file stats
|
||||
- `git diff <latest-tag>..HEAD --name-only` - see changed files
|
||||
|
||||
4. **Determine version bump** (Semantic Versioning):
|
||||
- **MAJOR (X.0.0)**: Breaking API changes, incompatible modifications
|
||||
- **MINOR (0.X.0)**: New features, backward-compatible additions
|
||||
- **PATCH (0.0.X)**: Bug fixes, backward-compatible fixes
|
||||
|
||||
Look for indicators:
|
||||
- `feat:` or `feature:` commits → MINOR
|
||||
- `fix:` or `bugfix:` commits → PATCH
|
||||
- `breaking:` or `BREAKING CHANGE:` → MAJOR
|
||||
- Breaking API changes in `pkg/` or public interfaces → MAJOR
|
||||
- New commands, flags, or features → MINOR
|
||||
- Documentation-only changes → PATCH (or skip)
|
||||
|
||||
5. **Calculate new version**: Increment appropriate segment, reset lower segments to 0
|
||||
|
||||
6. **Draft tag message**:
|
||||
- Summarize key changes from commits
|
||||
- Group by type (Features, Fixes, Breaking Changes)
|
||||
- Keep concise but informative
|
||||
|
||||
7. **Create annotated tag**: `git tag -a vX.Y.Z -m "vX.Y.Z - <summary>\n\n<detailed list>"`
|
||||
|
||||
8. **Push tag**: `git push origin vX.Y.Z`
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Always fetch remote tags first to avoid conflicts
|
||||
- Use annotated tags (`-a`) with descriptive messages
|
||||
- Follow semver strictly - when in doubt, prefer conservative bump (patch over minor)
|
||||
- For Go projects, changes to `pkg/` or exported APIs warrant careful version consideration
|
||||
- If no changes since last tag, suggest skipping the release
|
||||
- Include commit summaries in the tag message body
|
||||
|
||||
## Example Tag Message Format
|
||||
|
||||
```
|
||||
v0.30.1 - Bug fixes for model handling and UI improvements
|
||||
|
||||
Fixes:
|
||||
- Properly handle think tags from Qwen/DeepSeek models
|
||||
- Handle custom provider model persistence and bare model names
|
||||
|
||||
Improvements:
|
||||
- UI style refactoring and cleanup
|
||||
```
|
||||
|
||||
Wait for the user to confirm the version and message before executing tag commands.
|
||||
|
||||
---
|
||||
|
||||
$@
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
description: Audit and update project documentation (README and docs site) for a recent change
|
||||
---
|
||||
|
||||
Review recent code changes, identify all documentation surfaces that should
|
||||
mention them, and update each one — grounded in the actual diff, not guesses.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Identify the change**:
|
||||
- If the user input ($@) names a commit / PR / branch / topic, use that as the focus
|
||||
- Otherwise inspect `git log origin/main..HEAD --oneline` and `git diff origin/main...HEAD --stat` to discover what shipped on the current branch
|
||||
- Read the actual diff (`git diff origin/main...HEAD`) — never document features that aren't in the code
|
||||
|
||||
2. **Inventory the doc surfaces**:
|
||||
- `README.md` at the repo root
|
||||
- Any docs site (commonly `www/`, `docs/`, `site/`) — list its pages and identify the one(s) most thematically related to the change
|
||||
- Inline godoc / API reference comments on the new exported symbols
|
||||
- `CHANGELOG.md` if the project keeps one
|
||||
- Any `examples/` directory entries that demonstrate the affected area
|
||||
|
||||
3. **Audit each surface** with `grep`:
|
||||
- Search for the names of related existing APIs (e.g. if you added `IterTools`, grep for `ListTools`) to find every page that already discusses the area
|
||||
- Decide for each hit: does it need a cross-reference, a side-by-side comparison, or to stay untouched?
|
||||
|
||||
4. **Decide where new content lives**:
|
||||
- Prefer extending an existing page over creating a new one
|
||||
- For a docs site, place new sections near related content (check the page's `## Heading` outline first)
|
||||
- Skip surfaces that genuinely don't apply (e.g. a server-focused README for a client-only change) and say so explicitly
|
||||
|
||||
5. **Draft the updates**:
|
||||
- Lead with a one-sentence statement of what's new and why
|
||||
- Show concrete code examples copied from real signatures — verify against the source files
|
||||
- Include a comparison / "when to use which" table when adding an alternative to an existing API
|
||||
- Note backwards-compatibility behaviour if relevant
|
||||
|
||||
6. **Verify the docs build** before committing:
|
||||
- For vocs / docusaurus / mkdocs sites, run the local build command (e.g. `npx vocs build`, `mkdocs build`) and fix any MDX/markdown errors
|
||||
- For godoc, run `go vet ./...` and `go doc <pkg> <Symbol>` to sanity-check rendering
|
||||
|
||||
7. **Report**:
|
||||
- List every file changed and every file deliberately left alone (with a one-line reason)
|
||||
- Suggest the next step (typically `/commit-push`) — do not auto-commit unless asked
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Read the diff before writing anything — invented API names erode trust faster than missing docs
|
||||
- One change per doc commit; keep doc updates separate from code changes when possible
|
||||
- Match the existing voice and formatting of each surface (headings, code-fence languages, table styles)
|
||||
- Prefer linking between pages over duplicating content
|
||||
|
||||
$@
|
||||
@@ -1,120 +0,0 @@
|
||||
# KIT Agent Guidelines
|
||||
|
||||
## Build/Test Commands
|
||||
- **Build**: `go build -o output/kit ./cmd/kit`
|
||||
- **Test all**: `go test -race ./...`
|
||||
- **Test single**: `go test -race ./cmd -run TestScriptExecution`
|
||||
- **Lint**: `go vet ./...`
|
||||
- **Format**: `go fmt ./...`
|
||||
|
||||
## Code Style
|
||||
- **Imports**: stdlib → third-party → local (blank lines between)
|
||||
- **Naming**: camelCase (unexported), PascalCase (exported)
|
||||
- **Errors**: Always check, wrap with `fmt.Errorf("context: %w", err)`
|
||||
- **Logging**: Use `github.com/charmbracelet/log` structured logging
|
||||
- **Types**: Prefer `any` over `interface{}`
|
||||
- **JSON**: snake_case tags with `omitempty` where appropriate
|
||||
- **Context**: First parameter for blocking operations
|
||||
|
||||
## Architecture
|
||||
- Multi-provider LLM support via `llm.Provider` interface
|
||||
- MCP client-server for tool integration
|
||||
- Builtin servers: bash, fetch, todo, fs
|
||||
- **Extension system** (`internal/extensions/`): Yaegi-interpreted Go, 13 lifecycle events, custom tools/commands/widgets/overlays/editor interceptors
|
||||
- **TUI** (`internal/ui/`): Bubble Tea v2 parent-child model (`AppModel` → `InputComponent`, `StreamComponent`, etc.)
|
||||
- **Decoupling pattern**: `cmd/root.go` has converter functions (e.g. `widgetProviderForUI()`) that bridge `internal/extensions/` types to `internal/ui/` types — the UI never imports extensions directly
|
||||
- **Public SDK** (`pkg/kit/`): The public-facing Go SDK for embedding Kit as a library. See rules below.
|
||||
|
||||
## Public SDK (`pkg/kit/`) Rules
|
||||
|
||||
`pkg/kit/` is the **public API surface** consumed by external Go developers. All exported symbols, types, function names, and godoc comments in this package are part of the SDK contract.
|
||||
|
||||
### No Dependency Name Leakage
|
||||
Internal dependency names (e.g. `charm.land/fantasy`, library-specific jargon) **must not** appear in:
|
||||
- **Exported function/method names** — use generic terms (`LLM`, `Provider`, `Message`) instead of library names
|
||||
- **Exported type names** — type aliases should use domain names (e.g. `LLMMessage`, not `FantasyMessage`)
|
||||
- **Godoc comments** on exported symbols — these are visible in `go doc` output and pkg.go.dev
|
||||
- **Struct field names and tags** on exported types
|
||||
|
||||
Using dependency types directly in **function bodies** (private implementation) is fine — that's invisible to SDK consumers.
|
||||
|
||||
### Naming Conventions for SDK Symbols
|
||||
- Type aliases re-exporting dependency types: use `LLM*` prefix (e.g. `LLMMessage`, `LLMUsage`, `LLMResponse`)
|
||||
- Conversion helpers: use `ConvertToLLM*` / `ConvertFromLLM*` (not the dependency name)
|
||||
- Provider queries: use `GetLLMProviders` (not `GetFantasyProviders`)
|
||||
- When wrapping internal methods, the `pkg/kit/` name should be dependency-agnostic even if the `internal/` method still uses the old name
|
||||
|
||||
### Deprecation Pattern
|
||||
When renaming a public SDK symbol, keep the old name as a deprecated wrapper for one release cycle:
|
||||
```go
|
||||
// Deprecated: Use NewName instead.
|
||||
func OldName() { return NewName() }
|
||||
```
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Yaegi (Extension Interpreter) Gotchas
|
||||
- **No interfaces across boundary**: All extension-facing API types must be concrete structs, never interfaces. Yaegi crashes on interface wrapper generation.
|
||||
- **Function field bug**: Named function references assigned to struct fields return zero values across the interpreter boundary. Always use anonymous closure literals:
|
||||
```go
|
||||
// WRONG: ctx.SetEditor(ext.EditorConfig{HandleKey: myHandler})
|
||||
// RIGHT: ctx.SetEditor(ext.EditorConfig{HandleKey: func(k, t string) ext.EditorKeyAction { return myHandler(k, t) }})
|
||||
```
|
||||
- **Symbol exports**: Every new type exposed to extensions must be added to `internal/extensions/symbols.go`
|
||||
|
||||
### BubbleTea Integration
|
||||
- **No `prog.Send()` from inside `Update()`**: Calling `prog.Send()` synchronously within a BubbleTea `Update()` handler deadlocks the event loop. Use `go appInstance.NotifyWidgetUpdate()` (async goroutine) instead.
|
||||
- **Height measurement**: `distributeHeight()` in `model.go` must measure using the same render path as `View()`. If an interceptor wraps rendering, measure with the wrapper too, or layout will mismatch.
|
||||
- **Channel-based prompts**: Extension prompt calls (PromptSelect, etc.) block on a `chan PromptResponse`. Extension slash commands run in dedicated goroutines (not `tea.Cmd`) to avoid stalling BubbleTea's Cmd scheduler.
|
||||
|
||||
### Extension State Management
|
||||
- **Thread-safe maps on Runner**: Widget/header/footer/editor state lives on the Runner with `sync.RWMutex`, queried by UI via callbacks
|
||||
- **Context function fields**: The `Context` struct uses function fields (`Print func(string)`, `SetWidget func(WidgetConfig)`) wired by closures in `cmd/root.go`
|
||||
- **Package-level vars in extensions**: Yaegi supports package-level variables captured in closures — this is how extensions maintain state across event callbacks
|
||||
|
||||
### Unicode in Widget Text
|
||||
- Widget content renders through `lipgloss.Style.Render()` which preserves ANSI escape codes
|
||||
- Use rune-based width calculations (`len([]rune(s))`) not byte length (`len(s)`) when aligning box-drawing characters or multi-byte symbols
|
||||
|
||||
## Testing
|
||||
|
||||
### Interactive TUI Testing with tmux
|
||||
Use tmux to test Kit interactively without blocking the agent:
|
||||
```bash
|
||||
tmux new-session -d -s kittest -x 120 -y 40 "output/kit -e examples/extensions/my-ext.go --no-session 2>kit_stderr.log"
|
||||
sleep 3
|
||||
tmux capture-pane -t kittest -p # read screen
|
||||
tmux send-keys -t kittest '/command' Enter # send input
|
||||
tmux kill-session -t kittest # cleanup
|
||||
```
|
||||
|
||||
### Non-Interactive Kit (Subprocess Spawning)
|
||||
Extensions can spawn Kit as a subprocess for sub-agent patterns:
|
||||
```bash
|
||||
kit --quiet --no-session --no-extensions --system-prompt /path/to/prompt.txt --model provider/model "question"
|
||||
```
|
||||
Positional args are the prompt. `@file` args attach file content. Key flags: `--quiet` (stdout only, no TUI), `--no-session` (ephemeral), `--no-extensions` (prevent recursive loading), `--system-prompt` (string or file path).
|
||||
|
||||
## External Repo Research
|
||||
- **ALWAYS use `btca`** to search external repos (e.g. iteratr, other reference codebases)
|
||||
- Never guess or manually search the filesystem for external projects
|
||||
- Example: `btca ask -r https://github.com/user/repo -q "How does X work?"`
|
||||
- See `.agents/skills/btca-cli/SKILL.md` for full btca usage
|
||||
|
||||
## BTCA Configured Resources
|
||||
The following external repositories are configured in `btca.config.jsonc` for research:
|
||||
|
||||
- bubbletea
|
||||
- lipgloss
|
||||
- bubbles
|
||||
- glamour
|
||||
- fantasy
|
||||
- catwalk
|
||||
- crush
|
||||
- pi
|
||||
- iteratr
|
||||
- yaegi
|
||||
- acp-go-sdk
|
||||
- opencode
|
||||
- herald
|
||||
- herald-md
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Mark III Labs, LLC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
-145
@@ -1,145 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
vars:
|
||||
BINARY: kit
|
||||
OUTPUT_DIR: output
|
||||
BUILD_FLAGS: -o {{.OUTPUT_DIR}}/{{.BINARY}}
|
||||
LDFLAGS: -s -w -X main.version=dev
|
||||
|
||||
tasks:
|
||||
default:
|
||||
desc: Show available tasks
|
||||
cmds:
|
||||
- task --list-all
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Build
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
build:
|
||||
desc: Build the kit binary
|
||||
cmds:
|
||||
- go build {{.BUILD_FLAGS}} -ldflags "{{.LDFLAGS}}" ./cmd/kit
|
||||
sources:
|
||||
- "**/*.go"
|
||||
- go.mod
|
||||
- go.sum
|
||||
generates:
|
||||
- "{{.OUTPUT_DIR}}/{{.BINARY}}"
|
||||
|
||||
build-all:
|
||||
desc: Build for all platforms (linux, darwin, windows)
|
||||
cmds:
|
||||
- GOOS=linux GOARCH=amd64 go build -o {{.OUTPUT_DIR}}/{{.BINARY}}-linux-amd64 -ldflags "{{.LDFLAGS}}" ./cmd/kit
|
||||
- GOOS=linux GOARCH=arm64 go build -o {{.OUTPUT_DIR}}/{{.BINARY}}-linux-arm64 -ldflags "{{.LDFLAGS}}" ./cmd/kit
|
||||
- GOOS=darwin GOARCH=amd64 go build -o {{.OUTPUT_DIR}}/{{.BINARY}}-darwin-amd64 -ldflags "{{.LDFLAGS}}" ./cmd/kit
|
||||
- GOOS=darwin GOARCH=arm64 go build -o {{.OUTPUT_DIR}}/{{.BINARY}}-darwin-arm64 -ldflags "{{.LDFLAGS}}" ./cmd/kit
|
||||
- GOOS=windows GOARCH=amd64 go build -o {{.OUTPUT_DIR}}/{{.BINARY}}-windows-amd64.exe -ldflags "{{.LDFLAGS}}" ./cmd/kit
|
||||
|
||||
install:
|
||||
desc: Install kit to $GOPATH/bin
|
||||
cmds:
|
||||
- go install -ldflags "{{.LDFLAGS}}" ./cmd/kit
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Test
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
test:
|
||||
desc: Run all tests with race detector
|
||||
cmds:
|
||||
- go test -race ./...
|
||||
|
||||
test-v:
|
||||
desc: Run all tests (verbose)
|
||||
cmds:
|
||||
- go test -race -v ./...
|
||||
|
||||
test-short:
|
||||
desc: Run tests in short mode (skip long-running tests)
|
||||
cmds:
|
||||
- go test -race -short ./...
|
||||
|
||||
test-pkg:
|
||||
desc: "Run tests for a specific package (usage: task test-pkg -- ./internal/config)"
|
||||
cmds:
|
||||
- go test -race -v {{.CLI_ARGS}}
|
||||
|
||||
test-run:
|
||||
desc: "Run a single test by name (usage: task test-run -- TestScriptExecution)"
|
||||
cmds:
|
||||
- go test -race -v ./... -run {{.CLI_ARGS}}
|
||||
|
||||
test-cover:
|
||||
desc: Run tests with coverage report
|
||||
cmds:
|
||||
- mkdir -p {{.OUTPUT_DIR}}
|
||||
- go test -race -coverprofile={{.OUTPUT_DIR}}/coverage.out ./...
|
||||
- go tool cover -html={{.OUTPUT_DIR}}/coverage.out -o {{.OUTPUT_DIR}}/coverage.html
|
||||
- echo "Coverage report written to {{.OUTPUT_DIR}}/coverage.html"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Code quality
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
lint:
|
||||
desc: Run golangci-lint and go vet
|
||||
cmds:
|
||||
- golangci-lint run ./...
|
||||
- go vet ./...
|
||||
|
||||
fmt:
|
||||
desc: Format all Go files
|
||||
cmds:
|
||||
- go fmt ./...
|
||||
|
||||
fmt-check:
|
||||
desc: Check formatting (fails if files need formatting)
|
||||
cmds:
|
||||
- test -z "$(gofmt -l .)" || (echo "Files need formatting:" && gofmt -l . && exit 1)
|
||||
|
||||
tidy:
|
||||
desc: Tidy go.mod and go.sum
|
||||
cmds:
|
||||
- go mod tidy
|
||||
|
||||
check:
|
||||
desc: Run all quality checks (fmt, vet, test)
|
||||
cmds:
|
||||
- task: fmt-check
|
||||
- task: lint
|
||||
- task: test
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Development
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
dev:
|
||||
desc: Build and run kit with optional args
|
||||
cmds:
|
||||
- task: build
|
||||
- "{{.OUTPUT_DIR}}/{{.BINARY}} {{.CLI_ARGS}}"
|
||||
|
||||
watch:
|
||||
desc: Watch for changes and rebuild (requires watchexec)
|
||||
cmds:
|
||||
- watchexec -e go -r -- task build
|
||||
|
||||
clean:
|
||||
desc: Remove build artifacts
|
||||
cmds:
|
||||
- rm -rf {{.OUTPUT_DIR}}
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Release
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
release-snapshot:
|
||||
desc: Build a release snapshot (no publish)
|
||||
cmds:
|
||||
- goreleaser release --snapshot --clean
|
||||
|
||||
release-check:
|
||||
desc: Validate goreleaser config
|
||||
cmds:
|
||||
- goreleaser check
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"version":"1.5.2","languages":{"en":{"hash":"en_80f5da5232","wasm":"en","page_count":21}},"include_characters":["_","‿","⁀","⁔","︳","︴","﹍","﹎","﹏","_"]}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,214 @@
|
||||
:root {
|
||||
--pagefind-ui-scale: 0.8;
|
||||
--pagefind-ui-primary: #034AD8;
|
||||
--pagefind-ui-fade: #707070;
|
||||
--pagefind-ui-text: #393939;
|
||||
--pagefind-ui-background: #ffffff;
|
||||
--pagefind-ui-border: #eeeeee;
|
||||
--pagefind-ui-tag: #eeeeee;
|
||||
--pagefind-ui-border-width: 2px;
|
||||
--pagefind-ui-border-radius: 8px;
|
||||
--pagefind-ui-image-border-radius: 8px;
|
||||
--pagefind-ui-image-box-ratio: 3 / 2;
|
||||
--pagefind-ui-font: system, -apple-system, ".SFNSText-Regular",
|
||||
"San Francisco", "Roboto", "Segoe UI", "Helvetica Neue",
|
||||
"Lucida Grande", sans-serif;
|
||||
}
|
||||
|
||||
[data-pfmod-hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
[data-pfmod-suppressed] {
|
||||
opacity: 0 !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
[data-pfmod-sr-hidden] {
|
||||
-webkit-clip: rect(0 0 0 0) !important;
|
||||
clip: rect(0 0 0 0) !important;
|
||||
-webkit-clip-path: inset(100%) !important;
|
||||
clip-path: inset(100%) !important;
|
||||
height: 1px !important;
|
||||
overflow: hidden !important;
|
||||
overflow: clip !important;
|
||||
position: absolute !important;
|
||||
white-space: nowrap !important;
|
||||
width: 1px !important;
|
||||
}
|
||||
|
||||
[data-pfmod-loading] {
|
||||
color: var(--pagefind-ui-text);
|
||||
background-color: var(--pagefind-ui-text);
|
||||
border-radius: var(--pagefind-ui-border-radius);
|
||||
opacity: 0.1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Input */
|
||||
|
||||
.pagefind-modular-input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pagefind-modular-input-wrapper::before {
|
||||
background-color: var(--pagefind-ui-text);
|
||||
width: calc(18px * var(--pagefind-ui-scale));
|
||||
height: calc(18px * var(--pagefind-ui-scale));
|
||||
top: calc(23px * var(--pagefind-ui-scale));
|
||||
left: calc(20px * var(--pagefind-ui-scale));
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: block;
|
||||
opacity: 0.7;
|
||||
-webkit-mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");
|
||||
mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");
|
||||
-webkit-mask-size: 100%;
|
||||
mask-size: 100%;
|
||||
z-index: 9;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.pagefind-modular-input {
|
||||
height: calc(64px * var(--pagefind-ui-scale));
|
||||
padding: 0 calc(70px * var(--pagefind-ui-scale)) 0 calc(54px * var(--pagefind-ui-scale));
|
||||
background-color: var(--pagefind-ui-background);
|
||||
border: var(--pagefind-ui-border-width) solid var(--pagefind-ui-border);
|
||||
border-radius: var(--pagefind-ui-border-radius);
|
||||
font-size: calc(21px * var(--pagefind-ui-scale));
|
||||
position: relative;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.pagefind-modular-input::placeholder {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.pagefind-modular-input-clear {
|
||||
position: absolute;
|
||||
top: calc(2px * var(--pagefind-ui-scale));
|
||||
right: calc(2px * var(--pagefind-ui-scale));
|
||||
height: calc(60px * var(--pagefind-ui-scale));
|
||||
border-radius: var(--pagefind-ui-border-radius);
|
||||
padding: 0 calc(15px * var(--pagefind-ui-scale)) 0 calc(2px * var(--pagefind-ui-scale));
|
||||
color: var(--pagefind-ui-text);
|
||||
font-size: calc(14px * var(--pagefind-ui-scale));
|
||||
cursor: pointer;
|
||||
background-color: var(--pagefind-ui-background);
|
||||
border: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
/* ResultList */
|
||||
|
||||
.pagefind-modular-list-result {
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: min(calc(40px * var(--pagefind-ui-scale)), 3%);
|
||||
padding: calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale));
|
||||
border-top: solid var(--pagefind-ui-border-width) var(--pagefind-ui-border);
|
||||
}
|
||||
|
||||
.pagefind-modular-list-result:last-of-type {
|
||||
border-bottom: solid var(--pagefind-ui-border-width) var(--pagefind-ui-border);
|
||||
}
|
||||
|
||||
.pagefind-modular-list-thumb {
|
||||
width: min(30%,
|
||||
calc((30% - (100px * var(--pagefind-ui-scale))) * 100000));
|
||||
max-width: calc(120px * var(--pagefind-ui-scale));
|
||||
margin-top: calc(10px * var(--pagefind-ui-scale));
|
||||
aspect-ratio: var(--pagefind-ui-image-box-ratio);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pagefind-modular-list-image {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-size: 0;
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
border-radius: var(--pagefind-ui-image-border-radius);
|
||||
}
|
||||
|
||||
.pagefind-modular-list-inner {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin-top: calc(10px * var(--pagefind-ui-scale));
|
||||
}
|
||||
|
||||
.pagefind-modular-list-title {
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
font-size: calc(21px * var(--pagefind-ui-scale));
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.pagefind-modular-list-link {
|
||||
color: var(--pagefind-ui-text);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pagefind-modular-list-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.pagefind-modular-list-excerpt {
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
font-size: calc(16px * var(--pagefind-ui-scale));
|
||||
margin-top: calc(4px * var(--pagefind-ui-scale));
|
||||
margin-bottom: 0;
|
||||
min-width: calc(250px * var(--pagefind-ui-scale));
|
||||
}
|
||||
|
||||
/* FilterPills */
|
||||
|
||||
.pagefind-modular-filter-pills-wrapper {
|
||||
overflow-x: scroll;
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.pagefind-modular-filter-pills {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.pagefind-modular-filter-pill {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: none;
|
||||
appearance: none;
|
||||
padding: 0 calc(24px * var(--pagefind-ui-scale));
|
||||
background-color: var(--pagefind-ui-background);
|
||||
color: var(--pagefind-ui-fade);
|
||||
border: var(--pagefind-ui-border-width) solid var(--pagefind-ui-border);
|
||||
border-radius: calc(25px * var(--pagefind-ui-scale));
|
||||
font-size: calc(18px * var(--pagefind-ui-scale));
|
||||
height: calc(50px * var(--pagefind-ui-scale));
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pagefind-modular-filter-pill:hover {
|
||||
border-color: var(--pagefind-ui-primary);
|
||||
}
|
||||
|
||||
.pagefind-modular-filter-pill[aria-pressed="true"] {
|
||||
border-color: var(--pagefind-ui-primary);
|
||||
color: var(--pagefind-ui-primary);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
@@ -1,8 +1,18 @@
|
||||
---
|
||||
title: JSON Output
|
||||
description: Machine-readable JSON output for scripting and automation.
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>JSON Output | Kit</title>
|
||||
<meta name="description" content="Machine-readable JSON output for scripting and automation.">
|
||||
<link rel="canonical" href="/advanced/json-output">
|
||||
<link rel="stylesheet" href="/assets/index-Di_r5hA0.css">
|
||||
<script type="module" src="/assets/index-EtDEWCgb.js"></script>
|
||||
<script type="application/ld+json">{"@context":"https://schema.org","@type":"TechArticle","headline":"JSON Output","description":"Machine-readable JSON output for scripting and automation.","url":"https://go-kit.dev/advanced/json-output","isPartOf":{"@type":"WebSite","name":"Kit","url":"https://go-kit.dev"}}</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="tome-root"></div>
|
||||
<div data-pagefind-body style="display:none"><h1>JSON Output</h1>
|
||||
# JSON Output
|
||||
|
||||
Use the `--json` flag to get structured output for scripting and automation:
|
||||
@@ -92,4 +102,6 @@ For Go programs, use the SDK's `PromptResult` method instead of parsing JSON:
|
||||
result, err := host.PromptResult(ctx, "Count files")
|
||||
fmt.Println(result.Response)
|
||||
fmt.Println(result.Usage.TotalTokens)
|
||||
```
|
||||
```</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,8 +1,18 @@
|
||||
---
|
||||
title: Subagents
|
||||
description: Multi-agent orchestration with Kit subagents.
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Subagents | Kit</title>
|
||||
<meta name="description" content="Multi-agent orchestration with Kit subagents.">
|
||||
<link rel="canonical" href="/advanced/subagents">
|
||||
<link rel="stylesheet" href="/assets/index-Di_r5hA0.css">
|
||||
<script type="module" src="/assets/index-EtDEWCgb.js"></script>
|
||||
<script type="application/ld+json">{"@context":"https://schema.org","@type":"TechArticle","headline":"Subagents","description":"Multi-agent orchestration with Kit subagents.","url":"https://go-kit.dev/advanced/subagents","isPartOf":{"@type":"WebSite","name":"Kit","url":"https://go-kit.dev"}}</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="tome-root"></div>
|
||||
<div data-pagefind-body style="display:none"><h1>Subagents</h1>
|
||||
# Subagents
|
||||
|
||||
Kit supports multi-agent orchestration through both subprocess spawning and in-process subagents.
|
||||
@@ -168,4 +178,6 @@ host.OnToolCall(func(e kit.ToolCallEvent) {
|
||||
|
||||
The listener receives the same event types as `Subscribe()` (`ToolCallEvent`, `MessageUpdateEvent`, `ReasoningDeltaEvent`, etc.) but scoped to the child agent's activity. Listeners are cleaned up automatically when the subagent completes.
|
||||
|
||||
If no listeners are registered for a tool call, no event dispatching overhead is incurred.
|
||||
If no listeners are registered for a tool call, no event dispatching overhead is incurred.</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,8 +1,18 @@
|
||||
---
|
||||
title: Testing with tmux
|
||||
description: Test Kit's TUI non-interactively using tmux.
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Testing with tmux | Kit</title>
|
||||
<meta name="description" content="Test Kit's TUI non-interactively using tmux.">
|
||||
<link rel="canonical" href="/advanced/testing">
|
||||
<link rel="stylesheet" href="/assets/index-Di_r5hA0.css">
|
||||
<script type="module" src="/assets/index-EtDEWCgb.js"></script>
|
||||
<script type="application/ld+json">{"@context":"https://schema.org","@type":"TechArticle","headline":"Testing with tmux","description":"Test Kit's TUI non-interactively using tmux.","url":"https://go-kit.dev/advanced/testing","isPartOf":{"@type":"WebSite","name":"Kit","url":"https://go-kit.dev"}}</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="tome-root"></div>
|
||||
<div data-pagefind-body style="display:none"><h1>Testing with tmux</h1>
|
||||
# Testing with tmux
|
||||
|
||||
Kit's interactive TUI can be tested non-interactively using tmux. This is useful for automated testing, CI pipelines, and extension development.
|
||||
@@ -71,4 +81,6 @@ tmux kill-session -t kittest
|
||||
- Redirect stderr to a log file (`2>kit.log`) for debugging
|
||||
- Use `--no-session` to avoid creating session files during tests
|
||||
- Add sufficient `sleep` between commands for the TUI to render
|
||||
- Use `grep` on captured pane output to verify specific content
|
||||
- Use `grep` on captured pane output to verify specific content</div>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,428 @@
|
||||
const e={frontmatter:{title:"Commands",description:"Complete reference for all Kit CLI subcommands.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="commands"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#commands"><span class="icon icon-link"></span></a>Commands</h1>
|
||||
<h2 id="authentication"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#authentication"><span class="icon icon-link"></span></a>Authentication</h2>
|
||||
<p>For OAuth-enabled providers like Anthropic.</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> login</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> [provider] </span><span style="color:#6A737D;--shiki-dark:#6A737D"># Start OAuth flow (e.g., anthropic)</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> login</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> [provider] --set-default </span><span style="color:#6A737D;--shiki-dark:#6A737D"># Set provider's default model as system default</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> logout</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> [provider] </span><span style="color:#6A737D;--shiki-dark:#6A737D"># Remove credentials for provider</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> status</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Check authentication status</span></span></code></pre>
|
||||
<h2 id="model-database"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#model-database"><span class="icon icon-link"></span></a>Model database</h2>
|
||||
<p>Manage the local model database that maps provider names to API configurations.</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> models</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> [provider] </span><span style="color:#6A737D;--shiki-dark:#6A737D"># List available models (optionally filter by provider)</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> models</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --all</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Show all providers (not just LLM-compatible)</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> update-models</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> [source] </span><span style="color:#6A737D;--shiki-dark:#6A737D"># Update model database</span></span></code></pre>
|
||||
<p>The <code>update-models</code> command accepts an optional source argument:</p>
|
||||
<ul>
|
||||
<li><em>(none)</em> — update from <a href="https://models.dev">models.dev</a></li>
|
||||
<li>A URL — fetch from a custom endpoint</li>
|
||||
<li>A file path — load from a local file</li>
|
||||
<li><code>embedded</code> — reset to the bundled database</li>
|
||||
</ul>
|
||||
<h2 id="extension-management"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#extension-management"><span class="icon icon-link"></span></a>Extension management</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> extensions</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> list</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # List discovered extensions</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> extensions</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> validate</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Validate extension files</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> extensions</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> init</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Generate example extension template</span></span></code></pre>
|
||||
<h3 id="installing-extensions-from-git"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#installing-extensions-from-git"><span class="icon icon-link"></span></a>Installing extensions from git</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#D73A49;--shiki-dark:#F97583"> <</span><span style="color:#032F62;--shiki-dark:#9ECBFF">git-ur</span><span style="color:#24292E;--shiki-dark:#E1E4E8">l</span><span style="color:#D73A49;--shiki-dark:#F97583">></span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Install extensions from git repositories</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -l</span><span style="color:#D73A49;--shiki-dark:#F97583"> <</span><span style="color:#032F62;--shiki-dark:#9ECBFF">git-ur</span><span style="color:#24292E;--shiki-dark:#E1E4E8">l</span><span style="color:#D73A49;--shiki-dark:#F97583">></span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Install to project-local .kit/git/ directory</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -u</span><span style="color:#D73A49;--shiki-dark:#F97583"> <</span><span style="color:#032F62;--shiki-dark:#9ECBFF">git-ur</span><span style="color:#24292E;--shiki-dark:#E1E4E8">l</span><span style="color:#D73A49;--shiki-dark:#F97583">></span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Update an already-installed package</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --uninstall</span><span style="color:#D73A49;--shiki-dark:#F97583"> <</span><span style="color:#032F62;--shiki-dark:#9ECBFF">pk</span><span style="color:#24292E;--shiki-dark:#E1E4E8">g</span><span style="color:#D73A49;--shiki-dark:#F97583">></span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Remove an installed package</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --all</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Install all extensions without prompting</span></span></code></pre>
|
||||
<h2 id="skills"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#skills"><span class="icon icon-link"></span></a>Skills</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> skill</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Install the Kit extensions skill via skills.sh</span></span></code></pre>
|
||||
<h3 id="skills-cli-flags"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#skills-cli-flags"><span class="icon icon-link"></span></a>Skills CLI flags</h3>
|
||||
<p>Control which skills are loaded at startup:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Load a specific skill file</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --skill</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> path/to/skill.md</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "prompt"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Load multiple skill files or directories (flag is repeatable)</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --skill</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ./skill1.md</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --skill</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ./skill2.md</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "prompt"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Load all skills from a custom directory instead of the default locations</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --skills-dir</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> /path/to/skills</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "prompt"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Disable all skill loading (auto-discovery and explicit)</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-skills</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "prompt"</span></span></code></pre>
|
||||
<p>Skills are auto-discovered from <code>~/.config/kit/skills/</code>, <code>.kit/skills/</code>, and <code>.agents/skills/</code> by default. Use <code>--skills-dir</code> to override the project-local search root, or <code>--skill</code> to load files explicitly (which disables auto-discovery). <code>--no-skills</code> suppresses all skill loading regardless of other flags.</p>
|
||||
<h2 id="interactive-slash-commands"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#interactive-slash-commands"><span class="icon icon-link"></span></a>Interactive slash commands</h2>
|
||||
<p>These commands are available inside the Kit TUI during an interactive session:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>/help</code></td>
|
||||
<td>Show available commands</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/tools</code></td>
|
||||
<td>List available MCP tools</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/servers</code></td>
|
||||
<td>Show connected MCP servers</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/model [name]</code></td>
|
||||
<td>Switch model or open model selector</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/theme [name]</code></td>
|
||||
<td>Switch color theme or list available themes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/thinking [level]</code></td>
|
||||
<td>Set thinking level (off, none, minimal, low, medium, high)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/compact [focus]</code></td>
|
||||
<td>Summarize older messages to free context</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/clear</code></td>
|
||||
<td>Clear conversation</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/clear-queue</code></td>
|
||||
<td>Clear queued messages</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/usage</code></td>
|
||||
<td>Show token usage</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/reset-usage</code></td>
|
||||
<td>Reset usage statistics</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/tree</code></td>
|
||||
<td>Navigate session tree</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/fork</code></td>
|
||||
<td>Fork to new session from an earlier message</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/new</code></td>
|
||||
<td>Start a new session (creates new session file)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/name [name]</code></td>
|
||||
<td>Set or show session display name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/resume</code></td>
|
||||
<td>Open session picker to switch sessions (alias: <code>/r</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/session</code></td>
|
||||
<td>Show session info</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/export [path]</code></td>
|
||||
<td>Export session as JSONL (default: auto-generated path)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/import <path></code></td>
|
||||
<td>Import a session from a JSONL file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/share</code></td>
|
||||
<td>Upload session to GitHub Gist and get a shareable viewer URL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/quit</code></td>
|
||||
<td>Exit Kit</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="prompt-history"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#prompt-history"><span class="icon icon-link"></span></a>Prompt history</h3>
|
||||
<p>Use <strong>↑</strong> and <strong>↓</strong> arrow keys to navigate through previously submitted prompts. Kit keeps the last 100 entries. Consecutive duplicates are skipped.</p>
|
||||
<h3 id="cancelling-operations"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#cancelling-operations"><span class="icon icon-link"></span></a>Cancelling operations</h3>
|
||||
<p>Press <strong>ESC twice</strong> to cancel the current operation:</p>
|
||||
<ul>
|
||||
<li>During a tool call: rolls back the entire turn to maintain API message pairing</li>
|
||||
<li>During streaming: stops the response generation</li>
|
||||
</ul>
|
||||
<p>This ensures that <code>tool_use</code> and <code>tool_result</code> messages are always sent to the API as matched pairs, avoiding errors from orphaned tool calls.</p>
|
||||
<h3 id="external-editor"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#external-editor"><span class="icon icon-link"></span></a>External editor</h3>
|
||||
<p>Press <strong>Ctrl+X e</strong> to open your <code>$VISUAL</code> or <code>$EDITOR</code> 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., <code>:cq</code> in Vim), the original input is preserved.</p>
|
||||
<h3 id="mid-turn-steering"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#mid-turn-steering"><span class="icon icon-link"></span></a>Mid-turn steering</h3>
|
||||
<p>Press <strong>Ctrl+X s</strong> 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:</p>
|
||||
<ul>
|
||||
<li>Works during streaming output</li>
|
||||
<li>Sends a steering instruction as a system message</li>
|
||||
<li>Model continues from the interruption point with the new guidance</li>
|
||||
</ul>
|
||||
<p>Example: While the model is writing code, press Ctrl+X s and type "Use async/await instead" to change the implementation approach.</p>
|
||||
<h3 id="image-attachments"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#image-attachments"><span class="icon icon-link"></span></a>Image attachments</h3>
|
||||
<p>Attach images to your next prompt straight from the clipboard:</p>
|
||||
<ul>
|
||||
<li>Copy an image (e.g. a screenshot) to the system clipboard, then press <strong>Ctrl+V</strong> in the input to attach it.</li>
|
||||
<li>Press <strong>Ctrl+U</strong> to clear all pending image attachments.</li>
|
||||
<li>Attachments are sent alongside your text when you submit, and cleared afterward.</li>
|
||||
</ul>
|
||||
<p>When a terminal supports color, Kit renders a small low-resolution <strong>thumbnail preview</strong> of each pending image directly in the input, below the <code>[N image(s) attached]</code> indicator, so you can confirm the right image was attached before sending.</p>
|
||||
<p>The preview is drawn with Unicode half-block characters and ordinary terminal colors — not a graphics protocol — so it renders correctly inside terminal multiplexers like <strong>tmux</strong> and <strong>zellij</strong>. Thumbnails are capped to a small cell box for a glanceable, low-res look.</p>
|
||||
<ul>
|
||||
<li>Best fidelity needs a <strong>truecolor</strong> terminal (<code>COLORTERM=truecolor</code>); Kit degrades to 256-color where truecolor is unavailable.</li>
|
||||
<li>On terminals with neither, the preview is skipped and the <code>[N image(s) attached]</code> text indicator is shown alone.</li>
|
||||
</ul>
|
||||
<p>You can also attach image files by referencing them with <code>@path/to/image.png</code> — binary files are auto-detected by MIME type. See <a href="/quick-start">Quick Start</a> for the <code>@</code> attachment syntax.</p>
|
||||
<h2 id="prompt-templates"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#prompt-templates"><span class="icon icon-link"></span></a>Prompt templates</h2>
|
||||
<h3 id="creating-templates"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#creating-templates"><span class="icon icon-link"></span></a>Creating templates</h3>
|
||||
<p>Templates use YAML frontmatter for metadata and support argument placeholders:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">---</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">description</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">Review code for issues</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">---</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">Review the following code for bugs and security issues.</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">Focus on $1 specifically.</span></span></code></pre>
|
||||
<p>Save to <code>~/.kit/prompts/review.md</code> or <code>.kit/prompts/review.md</code>.</p>
|
||||
<h3 id="using-templates"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#using-templates"><span class="icon icon-link"></span></a>Using templates</h3>
|
||||
<p>Templates appear as slash commands:</p>
|
||||
<pre><code>/review error handling
|
||||
</code></pre>
|
||||
<h3 id="argument-placeholders"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#argument-placeholders"><span class="icon icon-link"></span></a>Argument placeholders</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Placeholder</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>$1</code>, <code>$2</code>, etc.</td>
|
||||
<td>Individual arguments by position</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>$@</code>, <code>$ARGUMENTS</code></td>
|
||||
<td>All arguments joined with spaces (zero or more)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>$+</code></td>
|
||||
<td>All arguments joined with spaces (one or more required)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>\${@:N}</code></td>
|
||||
<td>Arguments from position N onwards</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>\${@:N:L}</code></td>
|
||||
<td>L arguments starting at position N</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Placeholders inside fenced code blocks (<code>\`\`\`</code>) and inline code spans are ignored, so documentation examples won't be substituted.</p>
|
||||
<h3 id="cli-flags"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#cli-flags"><span class="icon icon-link"></span></a>CLI flags</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Load a specific template by name</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --prompt-template</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> review</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Disable template loading</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-prompt-templates</span></span></code></pre>
|
||||
<h2 id="acp-server"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#acp-server"><span class="icon icon-link"></span></a>ACP server</h2>
|
||||
<p>Run Kit as an <a href="https://agentclientprotocol.com">ACP (Agent Client Protocol)</a> agent server. ACP-compatible clients communicate with Kit over JSON-RPC 2.0 on stdin/stdout.</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> acp</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Start as ACP agent</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> acp</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --debug</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # With debug logging to stderr</span></span></code></pre>`,headings:[{depth:2,text:"Authentication",id:"authentication"},{depth:2,text:"Model database",id:"model-database"},{depth:2,text:"Extension management",id:"extension-management"},{depth:3,text:"Installing extensions from git",id:"installing-extensions-from-git"},{depth:2,text:"Skills",id:"skills"},{depth:3,text:"Skills CLI flags",id:"skills-cli-flags"},{depth:2,text:"Interactive slash commands",id:"interactive-slash-commands"},{depth:3,text:"Prompt history",id:"prompt-history"},{depth:3,text:"Cancelling operations",id:"cancelling-operations"},{depth:3,text:"External editor",id:"external-editor"},{depth:3,text:"Mid-turn steering",id:"mid-turn-steering"},{depth:3,text:"Image attachments",id:"image-attachments"},{depth:2,text:"Prompt templates",id:"prompt-templates"},{depth:3,text:"Creating templates",id:"creating-templates"},{depth:3,text:"Using templates",id:"using-templates"},{depth:3,text:"Argument placeholders",id:"argument-placeholders"},{depth:3,text:"CLI flags",id:"cli-flags"},{depth:2,text:"ACP server",id:"acp-server"}],raw:`
|
||||
# Commands
|
||||
|
||||
## Authentication
|
||||
|
||||
For OAuth-enabled providers like Anthropic.
|
||||
|
||||
\`\`\`bash
|
||||
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
|
||||
\`\`\`
|
||||
|
||||
## Model database
|
||||
|
||||
Manage the local model database that maps provider names to API configurations.
|
||||
|
||||
\`\`\`bash
|
||||
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:
|
||||
- *(none)* — update from [models.dev](https://models.dev)
|
||||
- A URL — fetch from a custom endpoint
|
||||
- A file path — load from a local file
|
||||
- \`embedded\` — reset to the bundled database
|
||||
|
||||
## Extension management
|
||||
|
||||
\`\`\`bash
|
||||
kit extensions list # List discovered extensions
|
||||
kit extensions validate # Validate extension files
|
||||
kit extensions init # Generate example extension template
|
||||
\`\`\`
|
||||
|
||||
### Installing extensions from git
|
||||
|
||||
\`\`\`bash
|
||||
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
|
||||
\`\`\`
|
||||
|
||||
## Skills
|
||||
|
||||
\`\`\`bash
|
||||
kit skill # Install the Kit extensions skill via skills.sh
|
||||
\`\`\`
|
||||
|
||||
### Skills CLI flags
|
||||
|
||||
Control which skills are loaded at startup:
|
||||
|
||||
\`\`\`bash
|
||||
# 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"
|
||||
|
||||
# Load all skills from a custom directory instead of the default locations
|
||||
kit --skills-dir /path/to/skills "prompt"
|
||||
|
||||
# Disable all skill loading (auto-discovery and explicit)
|
||||
kit --no-skills "prompt"
|
||||
\`\`\`
|
||||
|
||||
Skills are auto-discovered from \`~/.config/kit/skills/\`, \`.kit/skills/\`, and \`.agents/skills/\` by default. Use \`--skills-dir\` to override the project-local search root, or \`--skill\` to load files explicitly (which disables auto-discovery). \`--no-skills\` suppresses all skill loading regardless of other flags.
|
||||
|
||||
## Interactive slash commands
|
||||
|
||||
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 |
|
||||
| \`/theme [name]\` | Switch color theme or list available themes |
|
||||
| \`/thinking [level]\` | Set thinking level (off, none, minimal, low, medium, high) |
|
||||
| \`/compact [focus]\` | Summarize older messages to free context |
|
||||
| \`/clear\` | Clear conversation |
|
||||
| \`/clear-queue\` | Clear queued messages |
|
||||
| \`/usage\` | Show token usage |
|
||||
| \`/reset-usage\` | Reset usage statistics |
|
||||
| \`/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 |
|
||||
| \`/quit\` | Exit Kit |
|
||||
|
||||
### Prompt history
|
||||
|
||||
Use **↑** and **↓** arrow keys to navigate through previously submitted prompts. Kit keeps the last 100 entries. Consecutive duplicates are skipped.
|
||||
|
||||
### Cancelling operations
|
||||
|
||||
Press **ESC twice** to cancel the current operation:
|
||||
- During a tool call: rolls back the entire turn to maintain API message pairing
|
||||
- During streaming: stops the response generation
|
||||
|
||||
This ensures that \`tool_use\` and \`tool_result\` messages are always sent to the API as matched pairs, avoiding errors from orphaned tool calls.
|
||||
|
||||
### External editor
|
||||
|
||||
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.
|
||||
|
||||
### Mid-turn steering
|
||||
|
||||
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:
|
||||
|
||||
- Works during streaming output
|
||||
- Sends a steering instruction as a system message
|
||||
- Model continues from the interruption point with the new guidance
|
||||
|
||||
Example: While the model is writing code, press Ctrl+X s and type "Use async/await instead" to change the implementation approach.
|
||||
|
||||
### Image attachments
|
||||
|
||||
Attach images to your next prompt straight from the clipboard:
|
||||
|
||||
- Copy an image (e.g. a screenshot) to the system clipboard, then press **Ctrl+V** in the input to attach it.
|
||||
- Press **Ctrl+U** to clear all pending image attachments.
|
||||
- Attachments are sent alongside your text when you submit, and cleared afterward.
|
||||
|
||||
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.
|
||||
|
||||
The preview is drawn with Unicode half-block characters and ordinary terminal colors — not a graphics protocol — so it renders correctly inside terminal multiplexers like **tmux** and **zellij**. Thumbnails are capped to a small cell box for a glanceable, low-res look.
|
||||
|
||||
- Best fidelity needs a **truecolor** terminal (\`COLORTERM=truecolor\`); Kit degrades to 256-color where truecolor is unavailable.
|
||||
- On terminals with neither, the preview is skipped and the \`[N image(s) attached]\` text indicator is shown alone.
|
||||
|
||||
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](/quick-start) for the \`@\` attachment syntax.
|
||||
|
||||
## Prompt templates
|
||||
|
||||
### Creating templates
|
||||
|
||||
Templates use YAML frontmatter for metadata and support argument placeholders:
|
||||
|
||||
\`\`\`markdown
|
||||
---
|
||||
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\`.
|
||||
|
||||
### Using templates
|
||||
|
||||
Templates appear as slash commands:
|
||||
|
||||
\`\`\`
|
||||
/review error handling
|
||||
\`\`\`
|
||||
|
||||
### Argument placeholders
|
||||
|
||||
| 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.
|
||||
|
||||
### CLI flags
|
||||
|
||||
\`\`\`bash
|
||||
# Load a specific template by name
|
||||
kit --prompt-template review
|
||||
|
||||
# Disable template loading
|
||||
kit --no-prompt-templates
|
||||
\`\`\`
|
||||
|
||||
## ACP server
|
||||
|
||||
Run Kit as an [ACP (Agent Client Protocol)](https://agentclientprotocol.com) agent server. ACP-compatible clients communicate with Kit over JSON-RPC 2.0 on stdin/stdout.
|
||||
|
||||
\`\`\`bash
|
||||
kit acp # Start as ACP agent
|
||||
kit acp --debug # With debug logging to stderr
|
||||
\`\`\`
|
||||
`};export{e as default};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,138 @@
|
||||
const e={frontmatter:{title:"Development",description:"Build, test, and contribute to Kit.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="development"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#development"><span class="icon icon-link"></span></a>Development</h1>
|
||||
<h2 id="build-and-test"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#build-and-test"><span class="icon icon-link"></span></a>Build and test</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Build</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> build</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -o</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> output/kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ./cmd/kit</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Run all tests</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> test</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -race</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ./...</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Run a specific test</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> test</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -race</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ./cmd</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -run</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> TestScriptExecution</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Lint</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> vet</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ./...</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Format</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> fmt</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ./...</span></span></code></pre>
|
||||
<h2 id="project-structure"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#project-structure"><span class="icon icon-link"></span></a>Project structure</h2>
|
||||
<pre><code>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 with sudo password prompt, 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
|
||||
</code></pre>
|
||||
<h2 id="architecture-overview"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#architecture-overview"><span class="icon icon-link"></span></a>Architecture overview</h2>
|
||||
<p>Kit is built around a few key architectural patterns:</p>
|
||||
<h3 id="multi-provider-llm-support"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#multi-provider-llm-support"><span class="icon icon-link"></span></a>Multi-provider LLM support</h3>
|
||||
<p>The <code>llm.Provider</code> interface abstracts different LLM providers. Each provider implements message formatting, tool calling, and streaming for its specific API.</p>
|
||||
<h3 id="mcp-client-server-model"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#mcp-client-server-model"><span class="icon icon-link"></span></a>MCP client-server model</h3>
|
||||
<p>External tools are integrated via the Model Context Protocol (MCP). Kit acts as an MCP client, connecting to MCP servers configured in <code>.kit.yml</code>.</p>
|
||||
<h3 id="extension-system"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#extension-system"><span class="icon icon-link"></span></a>Extension system</h3>
|
||||
<p>Extensions are Go source files interpreted at runtime by Yaegi. The <code>internal/extensions/</code> package manages loading, symbol export, and lifecycle dispatch. See the <a href="/extensions/overview">Extension System</a> docs for details.</p>
|
||||
<h3 id="tui-architecture"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#tui-architecture"><span class="icon icon-link"></span></a>TUI architecture</h3>
|
||||
<p>The interactive terminal UI is built with <a href="https://github.com/charmbracelet/bubbletea">Bubble Tea v2</a>, using a parent-child model where <code>AppModel</code> manages child components (<code>InputComponent</code>, <code>StreamComponent</code>, etc.).</p>
|
||||
<h3 id="decoupling-pattern"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#decoupling-pattern"><span class="icon icon-link"></span></a>Decoupling pattern</h3>
|
||||
<p><code>cmd/root.go</code> contains converter functions (e.g., <code>widgetProviderForUI()</code>) that bridge <code>internal/extensions/</code> types to <code>internal/ui/</code> types. The UI never imports the extensions package directly.</p>
|
||||
<h2 id="contributing"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#contributing"><span class="icon icon-link"></span></a>Contributing</h2>
|
||||
<p>Contributions are welcome! Please see the <a href="https://github.com/mark3labs/kit/blob/master/contribute/contribute.md">contribution guide</a> for guidelines.</p>
|
||||
<h2 id="community"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#community"><span class="icon icon-link"></span></a>Community</h2>
|
||||
<ul>
|
||||
<li><a href="https://discord.gg/RqSS2NQVsY">Discord</a></li>
|
||||
<li><a href="https://github.com/mark3labs/kit/issues">GitHub Issues</a></li>
|
||||
</ul>`,headings:[{depth:2,text:"Build and test",id:"build-and-test"},{depth:2,text:"Project structure",id:"project-structure"},{depth:2,text:"Architecture overview",id:"architecture-overview"},{depth:3,text:"Multi-provider LLM support",id:"multi-provider-llm-support"},{depth:3,text:"MCP client-server model",id:"mcp-client-server-model"},{depth:3,text:"Extension system",id:"extension-system"},{depth:3,text:"TUI architecture",id:"tui-architecture"},{depth:3,text:"Decoupling pattern",id:"decoupling-pattern"},{depth:2,text:"Contributing",id:"contributing"},{depth:2,text:"Community",id:"community"}],raw:`
|
||||
# Development
|
||||
|
||||
## Build and test
|
||||
|
||||
\`\`\`bash
|
||||
# Build
|
||||
go build -o output/kit ./cmd/kit
|
||||
|
||||
# Run all tests
|
||||
go test -race ./...
|
||||
|
||||
# Run a 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 with sudo password prompt, 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
|
||||
\`\`\`
|
||||
|
||||
## Architecture overview
|
||||
|
||||
Kit is built around a few key architectural patterns:
|
||||
|
||||
### Multi-provider LLM support
|
||||
|
||||
The \`llm.Provider\` interface abstracts different LLM providers. Each provider implements message formatting, tool calling, and streaming for its specific API.
|
||||
|
||||
### MCP client-server model
|
||||
|
||||
External tools are integrated via the Model Context Protocol (MCP). Kit acts as an MCP client, connecting to MCP servers configured in \`.kit.yml\`.
|
||||
|
||||
### Extension system
|
||||
|
||||
Extensions are Go source files interpreted at runtime by Yaegi. The \`internal/extensions/\` package manages loading, symbol export, and lifecycle dispatch. See the [Extension System](/extensions/overview) docs for details.
|
||||
|
||||
### TUI architecture
|
||||
|
||||
The interactive terminal UI is built with [Bubble Tea v2](https://github.com/charmbracelet/bubbletea), using a parent-child model where \`AppModel\` manages child components (\`InputComponent\`, \`StreamComponent\`, etc.).
|
||||
|
||||
### Decoupling pattern
|
||||
|
||||
\`cmd/root.go\` contains converter functions (e.g., \`widgetProviderForUI()\`) that bridge \`internal/extensions/\` types to \`internal/ui/\` types. The UI never imports the extensions package directly.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please see the [contribution guide](https://github.com/mark3labs/kit/blob/master/contribute/contribute.md) for guidelines.
|
||||
|
||||
## Community
|
||||
|
||||
- [Discord](https://discord.gg/RqSS2NQVsY)
|
||||
- [GitHub Issues](https://github.com/mark3labs/kit/issues)
|
||||
`};export{e as default};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,292 @@
|
||||
const t={frontmatter:{title:"Global Flags",description:"Complete reference for all Kit CLI flags.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="global-flags"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#global-flags"><span class="icon icon-link"></span></a>Global Flags</h1>
|
||||
<p>All flags can be passed to the root <code>kit</code> command.</p>
|
||||
<h2 id="model-and-provider"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#model-and-provider"><span class="icon icon-link"></span></a>Model and provider</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flag</th>
|
||||
<th>Short</th>
|
||||
<th>Default</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>--model</code></td>
|
||||
<td><code>-m</code></td>
|
||||
<td><code>anthropic/claude-sonnet-latest</code></td>
|
||||
<td>Model to use (provider/model format)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--provider-api-key</code></td>
|
||||
<td>—</td>
|
||||
<td>—</td>
|
||||
<td>API key for the provider</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--provider-url</code></td>
|
||||
<td>—</td>
|
||||
<td>—</td>
|
||||
<td>Base URL for provider API</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--tls-skip-verify</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Skip TLS certificate verification</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="session-management"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#session-management"><span class="icon icon-link"></span></a>Session management</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flag</th>
|
||||
<th>Short</th>
|
||||
<th>Default</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>--session</code></td>
|
||||
<td><code>-s</code></td>
|
||||
<td>—</td>
|
||||
<td>Open specific JSONL session file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--continue</code></td>
|
||||
<td><code>-c</code></td>
|
||||
<td><code>false</code></td>
|
||||
<td>Resume most recent session for current directory</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--resume</code></td>
|
||||
<td><code>-r</code></td>
|
||||
<td><code>false</code></td>
|
||||
<td>Interactive session picker</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--no-session</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Ephemeral mode, no persistence</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="behavior"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#behavior"><span class="icon icon-link"></span></a>Behavior</h2>
|
||||
<p>These flags control Kit's behavior. When a prompt is passed as a positional argument, Kit runs in non-interactive mode.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flag</th>
|
||||
<th>Short</th>
|
||||
<th>Default</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>--quiet</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Suppress all output (non-interactive only)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--json</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Output response as JSON (non-interactive only)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--no-exit</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Enter interactive mode after prompt completes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--max-steps</code></td>
|
||||
<td>—</td>
|
||||
<td><code>0</code></td>
|
||||
<td>Maximum agent steps (0 for unlimited)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--stream</code></td>
|
||||
<td>—</td>
|
||||
<td><code>true</code></td>
|
||||
<td>Enable streaming output</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--compact</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Enable compact output mode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--auto-compact</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Auto-compact conversation near context limit</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="extensions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#extensions"><span class="icon icon-link"></span></a>Extensions</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flag</th>
|
||||
<th>Short</th>
|
||||
<th>Default</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>--extension</code></td>
|
||||
<td><code>-e</code></td>
|
||||
<td>—</td>
|
||||
<td>Load additional extension file(s) (repeatable)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--no-extensions</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Disable all extensions</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--prompt-template</code></td>
|
||||
<td>—</td>
|
||||
<td>—</td>
|
||||
<td>Load a specific prompt template by name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--no-prompt-templates</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Disable prompt template loading</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="skills"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#skills"><span class="icon icon-link"></span></a>Skills</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flag</th>
|
||||
<th>Short</th>
|
||||
<th>Default</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>--skill</code></td>
|
||||
<td>—</td>
|
||||
<td>—</td>
|
||||
<td>Load skill file or directory (repeatable)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--skills-dir</code></td>
|
||||
<td>—</td>
|
||||
<td>—</td>
|
||||
<td>Override the project-local skills directory for auto-discovery</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--no-skills</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Disable skill loading (auto-discovery and explicit)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="generation-parameters"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#generation-parameters"><span class="icon icon-link"></span></a>Generation parameters</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flag</th>
|
||||
<th>Short</th>
|
||||
<th>Default</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>--max-tokens</code></td>
|
||||
<td>—</td>
|
||||
<td><code>8192</code></td>
|
||||
<td>Base cap for output tokens. Auto-raised per-model up to 32768 when the model's catalog ceiling is higher and no explicit value is set.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--temperature</code></td>
|
||||
<td>—</td>
|
||||
<td><code>0.7</code></td>
|
||||
<td>Randomness 0.0–1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--top-p</code></td>
|
||||
<td>—</td>
|
||||
<td><code>0.95</code></td>
|
||||
<td>Nucleus sampling 0.0–1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--top-k</code></td>
|
||||
<td>—</td>
|
||||
<td><code>40</code></td>
|
||||
<td>Limit top K tokens</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--stop-sequences</code></td>
|
||||
<td>—</td>
|
||||
<td>—</td>
|
||||
<td>Custom stop sequences (comma-separated)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--frequency-penalty</code></td>
|
||||
<td>—</td>
|
||||
<td><code>0.0</code></td>
|
||||
<td>Penalize frequent tokens (0.0–2.0)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--presence-penalty</code></td>
|
||||
<td>—</td>
|
||||
<td><code>0.0</code></td>
|
||||
<td>Penalize present tokens (0.0–2.0)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--thinking-level</code></td>
|
||||
<td>—</td>
|
||||
<td><code>off</code></td>
|
||||
<td>Extended thinking level: off, none, minimal, low, medium, high</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="system"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#system"><span class="icon icon-link"></span></a>System</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flag</th>
|
||||
<th>Short</th>
|
||||
<th>Default</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>--config</code></td>
|
||||
<td>—</td>
|
||||
<td><code>~/.kit.yml</code></td>
|
||||
<td>Config file path</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--system-prompt</code></td>
|
||||
<td>—</td>
|
||||
<td>—</td>
|
||||
<td>System prompt text or file path</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--debug</code></td>
|
||||
<td>—</td>
|
||||
<td><code>false</code></td>
|
||||
<td>Enable debug logging</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>`,headings:[{depth:2,text:"Model and provider",id:"model-and-provider"},{depth:2,text:"Session management",id:"session-management"},{depth:2,text:"Behavior",id:"behavior"},{depth:2,text:"Extensions",id:"extensions"},{depth:2,text:"Skills",id:"skills"},{depth:2,text:"Generation parameters",id:"generation-parameters"},{depth:2,text:"System",id:"system"}],raw:"\n# Global Flags\n\nAll flags can be passed to the root `kit` command.\n\n## Model and provider\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--model` | `-m` | `anthropic/claude-sonnet-latest` | Model to use (provider/model format) |\n| `--provider-api-key` | — | — | API key for the provider |\n| `--provider-url` | — | — | Base URL for provider API |\n| `--tls-skip-verify` | — | `false` | Skip TLS certificate verification |\n\n## Session management\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--session` | `-s` | — | Open specific JSONL session file |\n| `--continue` | `-c` | `false` | Resume most recent session for current directory |\n| `--resume` | `-r` | `false` | Interactive session picker |\n| `--no-session` | — | `false` | Ephemeral mode, no persistence |\n\n## Behavior\n\nThese flags control Kit's behavior. When a prompt is passed as a positional argument, Kit runs in non-interactive mode.\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--quiet` | — | `false` | Suppress all output (non-interactive only) |\n| `--json` | — | `false` | Output response as JSON (non-interactive only) |\n| `--no-exit` | — | `false` | Enter interactive mode after prompt completes |\n| `--max-steps` | — | `0` | Maximum agent steps (0 for unlimited) |\n| `--stream` | — | `true` | Enable streaming output |\n| `--compact` | — | `false` | Enable compact output mode |\n| `--auto-compact` | — | `false` | Auto-compact conversation near context limit |\n\n## Extensions\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--extension` | `-e` | — | Load additional extension file(s) (repeatable) |\n| `--no-extensions` | — | `false` | Disable all extensions |\n| `--prompt-template` | — | — | Load a specific prompt template by name |\n| `--no-prompt-templates` | — | `false` | Disable prompt template loading |\n\n## Skills\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--skill` | — | — | Load skill file or directory (repeatable) |\n| `--skills-dir` | — | — | Override the project-local skills directory for auto-discovery |\n| `--no-skills` | — | `false` | Disable skill loading (auto-discovery and explicit) |\n\n## Generation parameters\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--max-tokens` | — | `8192` | Base cap for output tokens. Auto-raised per-model up to 32768 when the model's catalog ceiling is higher and no explicit value is set. |\n| `--temperature` | — | `0.7` | Randomness 0.0–1.0 |\n| `--top-p` | — | `0.95` | Nucleus sampling 0.0–1.0 |\n| `--top-k` | — | `40` | Limit top K tokens |\n| `--stop-sequences` | — | — | Custom stop sequences (comma-separated) |\n| `--frequency-penalty` | — | `0.0` | Penalize frequent tokens (0.0–2.0) |\n| `--presence-penalty` | — | `0.0` | Penalize present tokens (0.0–2.0) |\n| `--thinking-level` | — | `off` | Extended thinking level: off, none, minimal, low, medium, high |\n\n## System\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--config` | — | `~/.kit.yml` | Config file path |\n| `--system-prompt` | — | — | System prompt text or file path |\n| `--debug` | — | `false` | Enable debug logging |\n"};export{t as default};
|
||||
@@ -0,0 +1 @@
|
||||
:root,:root[data-theme=dark],:root[data-theme=light],html,html[data-theme=dark],#tome-root,#tome-root *,[data-theme],body,div{--bg: #08080a !important;--sf: #0e0e12 !important;--sfH: #141418 !important;--bd: #1a1a22 !important;--tx: #e8e0e0 !important;--tx2: #8a8090 !important;--txM: #6a6070 !important;--ac: #e03030 !important;--acD: rgba(224, 48, 48, .12) !important;--acT: #ff4444 !important;--cdBg: #0a0a0e !important;--cdTx: #c8a0a0 !important;--sbBg: #0a0a0d !important;--hdBg: rgba(8, 8, 10, .92) !important}h1,h2,h3,h4,h5,h6{color:#e8e0e0!important;font-style:normal!important}
|
||||
@@ -0,0 +1,77 @@
|
||||
const t={frontmatter:{title:"Kit",description:"Kit is a powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system.",hidden:!1,toc:!1,draft:!1},html:`<div style="text-align: center; margin: 2rem 0;">
|
||||
<img src="/logo.jpg" alt="KIT" style="max-width: 400px; width: 100%; margin: 0 auto; display: block;">
|
||||
</div>
|
||||
<p>A powerful, extensible AI coding agent CLI with multi-provider support, built-in tools, and a rich extension system.</p>
|
||||
<h2 id="features"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#features"><span class="icon icon-link"></span></a>Features</h2>
|
||||
<ul>
|
||||
<li><strong>Multi-Provider LLM Support</strong> — Anthropic, OpenAI, Google Gemini, Ollama, Azure OpenAI, AWS Bedrock, OpenRouter, and more</li>
|
||||
<li><strong>Built-in Core Tools</strong> — bash (with interactive sudo password prompt), read, write, edit, grep, find, ls, subagent with no MCP overhead</li>
|
||||
<li><strong>Smart @ Attachments</strong> — Binary files auto-detected via MIME type, MCP resources via <code>@mcp:server:uri</code></li>
|
||||
<li><strong>MCP Integration</strong> — Connect external MCP servers for expanded capabilities (tools, prompts, and resources)</li>
|
||||
<li><strong>Extension System</strong> — Write custom tools, commands, widgets, and UI modifications in Go</li>
|
||||
<li><strong>Interactive TUI</strong> — Rich terminal interface powered by Bubble Tea with streaming, syntax highlighting, and custom rendering</li>
|
||||
<li><strong>Session Management</strong> — Tree-based conversation history with branching support</li>
|
||||
<li><strong>Non-Interactive Mode</strong> — Script-friendly positional args with JSON output</li>
|
||||
<li><strong>ACP Server</strong> — Run Kit as an <a href="https://agentclientprotocol.com">Agent Client Protocol</a> agent over stdio</li>
|
||||
<li><strong>Go SDK</strong> — Embed Kit in your own applications</li>
|
||||
</ul>
|
||||
<h2 id="quick-links"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#quick-links"><span class="icon icon-link"></span></a>Quick links</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Resource</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="/installation">Installation</a></td>
|
||||
<td>Get Kit up and running</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/quick-start">Quick Start</a></td>
|
||||
<td>Your first Kit session</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/configuration">Configuration</a></td>
|
||||
<td>Customize Kit for your workflow</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/extensions/overview">Extensions</a></td>
|
||||
<td>Build custom tools and UI components</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/sdk/overview">Go SDK</a></td>
|
||||
<td>Embed Kit in your applications</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>`,headings:[{depth:2,text:"Features",id:"features"},{depth:2,text:"Quick links",id:"quick-links"}],raw:`
|
||||
<div style="text-align: center; margin: 2rem 0;">
|
||||
<img src="/logo.jpg" alt="KIT" style="max-width: 400px; width: 100%; margin: 0 auto; display: block;" />
|
||||
</div>
|
||||
|
||||
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 with 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 (tools, prompts, and resources)
|
||||
- **Extension System** — Write custom tools, commands, widgets, and UI modifications in Go
|
||||
- **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
|
||||
|
||||
## Quick links
|
||||
|
||||
| Resource | Description |
|
||||
|----------|-------------|
|
||||
| [Installation](/installation) | Get Kit up and running |
|
||||
| [Quick Start](/quick-start) | Your first Kit session |
|
||||
| [Configuration](/configuration) | Customize Kit for your workflow |
|
||||
| [Extensions](/extensions/overview) | Build custom tools and UI components |
|
||||
| [Go SDK](/sdk/overview) | Embed Kit in your applications |
|
||||
`};export{t as default};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,88 @@
|
||||
const s={frontmatter:{title:"Installation",description:"Install Kit using npm, bun, pnpm, Go, or build from source.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="installation"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#installation"><span class="icon icon-link"></span></a>Installation</h1>
|
||||
<h2 id="using-npm--bun--pnpm"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#using-npm--bun--pnpm"><span class="icon icon-link"></span></a>Using npm / bun / pnpm</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">npm</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -g</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> @mark3labs/kit</span></span></code></pre>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">bun</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -g</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> @mark3labs/kit</span></span></code></pre>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">pnpm</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -g</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> @mark3labs/kit</span></span></code></pre>
|
||||
<h2 id="using-go"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#using-go"><span class="icon icon-link"></span></a>Using Go</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> github.com/mark3labs/kit/cmd/kit@latest</span></span></code></pre>
|
||||
<h2 id="building-from-source"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#building-from-source"><span class="icon icon-link"></span></a>Building from source</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">git</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> clone</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> https://github.com/mark3labs/kit.git</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF">cd</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kit</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> build</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -o</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ./cmd/kit</span></span></code></pre>
|
||||
<h2 id="verifying-the-installation"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#verifying-the-installation"><span class="icon icon-link"></span></a>Verifying the installation</h2>
|
||||
<p>After installing, verify Kit is available:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --help</span></span></code></pre>
|
||||
<h2 id="setting-up-a-provider"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#setting-up-a-provider"><span class="icon icon-link"></span></a>Setting up a provider</h2>
|
||||
<p>Kit needs at least one LLM provider configured. Set an API key for your preferred provider:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Anthropic (default provider)</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">export</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ANTHROPIC_API_KEY</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"sk-..."</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># OpenAI</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">export</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> OPENAI_API_KEY</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"sk-..."</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Google Gemini</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">export</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> GOOGLE_API_KEY</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"..."</span></span></code></pre>
|
||||
<p>For OAuth-enabled providers like Anthropic, you can also authenticate interactively:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> login</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> anthropic</span></span></code></pre>
|
||||
<p>See <a href="/providers">Providers</a> for the full list of supported providers and their configuration.</p>`,headings:[{depth:2,text:"Using npm / bun / pnpm",id:"using-npm--bun--pnpm"},{depth:2,text:"Using Go",id:"using-go"},{depth:2,text:"Building from source",id:"building-from-source"},{depth:2,text:"Verifying the installation",id:"verifying-the-installation"},{depth:2,text:"Setting up a provider",id:"setting-up-a-provider"}],raw:`
|
||||
# Installation
|
||||
|
||||
## Using npm / bun / pnpm
|
||||
|
||||
\`\`\`bash
|
||||
npm install -g @mark3labs/kit
|
||||
\`\`\`
|
||||
|
||||
\`\`\`bash
|
||||
bun install -g @mark3labs/kit
|
||||
\`\`\`
|
||||
|
||||
\`\`\`bash
|
||||
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
|
||||
\`\`\`
|
||||
|
||||
## Verifying the installation
|
||||
|
||||
After installing, verify Kit is available:
|
||||
|
||||
\`\`\`bash
|
||||
kit --help
|
||||
\`\`\`
|
||||
|
||||
## Setting up a provider
|
||||
|
||||
Kit needs at least one LLM provider configured. Set an API key for your preferred provider:
|
||||
|
||||
\`\`\`bash
|
||||
# Anthropic (default provider)
|
||||
export ANTHROPIC_API_KEY="sk-..."
|
||||
|
||||
# OpenAI
|
||||
export OPENAI_API_KEY="sk-..."
|
||||
|
||||
# Google Gemini
|
||||
export GOOGLE_API_KEY="..."
|
||||
\`\`\`
|
||||
|
||||
For OAuth-enabled providers like Anthropic, you can also authenticate interactively:
|
||||
|
||||
\`\`\`bash
|
||||
kit auth login anthropic
|
||||
\`\`\`
|
||||
|
||||
See [Providers](/providers) for the full list of supported providers and their configuration.
|
||||
`};export{s as default};
|
||||
@@ -0,0 +1,240 @@
|
||||
const s={frontmatter:{title:"JSON Output",description:"Machine-readable JSON output for scripting and automation.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="json-output"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#json-output"><span class="icon icon-link"></span></a>JSON Output</h1>
|
||||
<p>Use the <code>--json</code> flag to get structured output for scripting and automation:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Explain main.go"</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --json</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --quiet</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-session</span></span></code></pre>
|
||||
<h2 id="response-format"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#response-format"><span class="icon icon-link"></span></a>Response format</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "response"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Final assistant response text"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "model"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"anthropic/claude-haiku-latest"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "stop_reason"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"end_turn"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "session_id"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"a1b2c3d4e5f6"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "usage"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "input_tokens"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">1024</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "output_tokens"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">512</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "total_tokens"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">1536</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "cache_read_tokens"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">0</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "cache_creation_tokens"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">0</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "messages"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "role"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"assistant"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> "parts"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="color:#005CC5;--shiki-dark:#79B8FF">"type"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"text"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#005CC5;--shiki-dark:#79B8FF">"data"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"..."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="color:#005CC5;--shiki-dark:#79B8FF">"type"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"tool_call"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#005CC5;--shiki-dark:#79B8FF">"data"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: {</span><span style="color:#005CC5;--shiki-dark:#79B8FF">"name"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"..."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#005CC5;--shiki-dark:#79B8FF">"args"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"..."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">}},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="color:#005CC5;--shiki-dark:#79B8FF">"type"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"tool_result"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#005CC5;--shiki-dark:#79B8FF">"data"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: {</span><span style="color:#005CC5;--shiki-dark:#79B8FF">"name"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"..."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#005CC5;--shiki-dark:#79B8FF">"result"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"..."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">}}</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ]</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ]</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h2 id="fields"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#fields"><span class="icon icon-link"></span></a>Fields</h2>
|
||||
<h3 id="top-level"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#top-level"><span class="icon icon-link"></span></a>Top-level</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>response</code></td>
|
||||
<td>string</td>
|
||||
<td>The final assistant response text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>model</code></td>
|
||||
<td>string</td>
|
||||
<td>The model that was used</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>stop_reason</code></td>
|
||||
<td>string</td>
|
||||
<td>Why the model stopped (e.g., <code>end_turn</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>session_id</code></td>
|
||||
<td>string</td>
|
||||
<td>Session identifier (omitted in <code>--no-session</code> mode)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>usage</code></td>
|
||||
<td>object</td>
|
||||
<td>Token usage statistics</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>messages</code></td>
|
||||
<td>array</td>
|
||||
<td>Full conversation history</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="usage"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#usage"><span class="icon icon-link"></span></a>Usage</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>input_tokens</code></td>
|
||||
<td>int</td>
|
||||
<td>Tokens sent to the model</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>output_tokens</code></td>
|
||||
<td>int</td>
|
||||
<td>Tokens generated by the model</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>total_tokens</code></td>
|
||||
<td>int</td>
|
||||
<td>Sum of input and output tokens</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>cache_read_tokens</code></td>
|
||||
<td>int</td>
|
||||
<td>Tokens read from prompt cache</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>cache_creation_tokens</code></td>
|
||||
<td>int</td>
|
||||
<td>Tokens written to prompt cache</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="message-parts"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#message-parts"><span class="icon icon-link"></span></a>Message parts</h3>
|
||||
<p>Each message contains a <code>parts</code> array with typed entries:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>text</code></td>
|
||||
<td>Assistant text content</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>tool_call</code></td>
|
||||
<td>Tool invocation with name and args</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>tool_result</code></td>
|
||||
<td>Tool execution result</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>reasoning</code></td>
|
||||
<td>Extended thinking content</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>finish</code></td>
|
||||
<td>End-of-turn marker</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="parsing-in-scripts"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#parsing-in-scripts"><span class="icon icon-link"></span></a>Parsing in scripts</h2>
|
||||
<h3 id="bash--jq"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#bash--jq"><span class="icon icon-link"></span></a>bash + jq</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">result</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8">$(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Count files"</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --json</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --quiet</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-session</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">response</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8">$(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">echo</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#24292E;--shiki-dark:#E1E4E8">$result</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#D73A49;--shiki-dark:#F97583"> |</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> jq</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -r</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> '.response'</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">tokens</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8">$(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">echo</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#24292E;--shiki-dark:#E1E4E8">$result</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#D73A49;--shiki-dark:#F97583"> |</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> jq</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> '.usage.total_tokens'</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
|
||||
<h3 id="go-sdk"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#go-sdk"><span class="icon icon-link"></span></a>Go SDK</h3>
|
||||
<p>For Go programs, use the SDK's <code>PromptResult</code> method instead of parsing JSON:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">result, err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">PromptResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Count files"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Println</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(result.Response)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Println</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(result.Usage.TotalTokens)</span></span></code></pre>`,headings:[{depth:2,text:"Response format",id:"response-format"},{depth:2,text:"Fields",id:"fields"},{depth:3,text:"Top-level",id:"top-level"},{depth:3,text:"Usage",id:"usage"},{depth:3,text:"Message parts",id:"message-parts"},{depth:2,text:"Parsing in scripts",id:"parsing-in-scripts"},{depth:3,text:"bash + jq",id:"bash--jq"},{depth:3,text:"Go SDK",id:"go-sdk"}],raw:`
|
||||
# JSON Output
|
||||
|
||||
Use the \`--json\` flag to get structured output for scripting and automation:
|
||||
|
||||
\`\`\`bash
|
||||
kit "Explain main.go" --json --quiet --no-session
|
||||
\`\`\`
|
||||
|
||||
## Response format
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"response": "Final assistant response text",
|
||||
"model": "anthropic/claude-haiku-latest",
|
||||
"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": "..."}}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Fields
|
||||
|
||||
### Top-level
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| \`response\` | string | The final assistant response text |
|
||||
| \`model\` | string | The model that was used |
|
||||
| \`stop_reason\` | string | Why the model stopped (e.g., \`end_turn\`) |
|
||||
| \`session_id\` | string | Session identifier (omitted in \`--no-session\` mode) |
|
||||
| \`usage\` | object | Token usage statistics |
|
||||
| \`messages\` | array | Full conversation history |
|
||||
|
||||
### Usage
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| \`input_tokens\` | int | Tokens sent to the model |
|
||||
| \`output_tokens\` | int | Tokens generated by the model |
|
||||
| \`total_tokens\` | int | Sum of input and output tokens |
|
||||
| \`cache_read_tokens\` | int | Tokens read from prompt cache |
|
||||
| \`cache_creation_tokens\` | int | Tokens written to prompt cache |
|
||||
|
||||
### Message parts
|
||||
|
||||
Each message contains a \`parts\` array with typed entries:
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| \`text\` | Assistant text content |
|
||||
| \`tool_call\` | Tool invocation with name and args |
|
||||
| \`tool_result\` | Tool execution result |
|
||||
| \`reasoning\` | Extended thinking content |
|
||||
| \`finish\` | End-of-turn marker |
|
||||
|
||||
## Parsing in scripts
|
||||
|
||||
### bash + jq
|
||||
|
||||
\`\`\`bash
|
||||
result=$(kit "Count files" --json --quiet --no-session)
|
||||
response=$(echo "$result" | jq -r '.response')
|
||||
tokens=$(echo "$result" | jq '.usage.total_tokens')
|
||||
\`\`\`
|
||||
|
||||
### Go SDK
|
||||
|
||||
For Go programs, use the SDK's \`PromptResult\` method instead of parsing JSON:
|
||||
|
||||
\`\`\`go
|
||||
result, err := host.PromptResult(ctx, "Count files")
|
||||
fmt.Println(result.Response)
|
||||
fmt.Println(result.Usage.TotalTokens)
|
||||
\`\`\`
|
||||
`};export{s as default};
|
||||
@@ -0,0 +1,213 @@
|
||||
const s={frontmatter:{title:"Loading Extensions",description:"How Kit discovers and loads extensions.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="loading-extensions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#loading-extensions"><span class="icon icon-link"></span></a>Loading Extensions</h1>
|
||||
<h2 id="auto-discovery"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#auto-discovery"><span class="icon icon-link"></span></a>Auto-discovery</h2>
|
||||
<p>Kit automatically discovers and loads extensions from these paths, in order:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Path</th>
|
||||
<th>Scope</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>~/.config/kit/extensions/*.go</code></td>
|
||||
<td>Global single files</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>~/.config/kit/extensions/*/main.go</code></td>
|
||||
<td>Global subdirectory extensions</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>.kit/extensions/*.go</code></td>
|
||||
<td>Project-local single files</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>.kit/extensions/*/main.go</code></td>
|
||||
<td>Project-local subdirectory extensions</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>~/.local/share/kit/git/</code></td>
|
||||
<td>Global git-installed packages</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>.kit/git/</code></td>
|
||||
<td>Project-local git-installed packages</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="explicit-loading"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#explicit-loading"><span class="icon icon-link"></span></a>Explicit loading</h2>
|
||||
<p>Load extensions by path using the <code>-e</code> flag:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -e</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> path/to/extension.go</span></span></code></pre>
|
||||
<p>Load multiple extensions:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -e</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ext1.go</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -e</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ext2.go</span></span></code></pre>
|
||||
<h2 id="disabling-extensions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#disabling-extensions"><span class="icon icon-link"></span></a>Disabling extensions</h2>
|
||||
<p>Disable all auto-discovered extensions:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-extensions</span></span></code></pre>
|
||||
<p>You can combine <code>--no-extensions</code> with <code>-e</code> to load only specific extensions:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-extensions</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -e</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> my-extension.go</span></span></code></pre>
|
||||
<h2 id="installing-from-git"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#installing-from-git"><span class="icon icon-link"></span></a>Installing from git</h2>
|
||||
<p>Install extensions from git repositories using <code>kit install</code>:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Install globally (to ~/.local/share/kit/git/)</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> https://github.com/user/my-kit-extension.git</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Install project-locally (to .kit/git/)</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -l</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> https://github.com/user/my-kit-extension.git</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Update an installed package</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -u</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> https://github.com/user/my-kit-extension.git</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Remove</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --uninstall</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> my-kit-extension</span></span></code></pre>
|
||||
<h2 id="extension-structure"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#extension-structure"><span class="icon icon-link"></span></a>Extension structure</h2>
|
||||
<h3 id="single-file-extensions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#single-file-extensions"><span class="icon icon-link"></span></a>Single-file extensions</h3>
|
||||
<p>A single <code>.go</code> file with an <code>Init</code> function:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">//go:build ignore</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">package</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> main</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">import</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit/ext</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> Init</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">api</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">API</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // register handlers, tools, commands, etc.</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<p>The <code>//go:build ignore</code> directive prevents the Go toolchain from trying to compile the file as part of a normal build.</p>
|
||||
<h3 id="subdirectory-extensions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#subdirectory-extensions"><span class="icon icon-link"></span></a>Subdirectory extensions</h3>
|
||||
<p>For more complex extensions, create a directory with a <code>main.go</code> entry point:</p>
|
||||
<pre><code>.kit/extensions/my-extension/
|
||||
├── main.go # Must contain Init(api ext.API)
|
||||
├── helpers.go # Additional source files
|
||||
└── config.go
|
||||
</code></pre>
|
||||
<h3 id="package-level-state"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#package-level-state"><span class="icon icon-link"></span></a>Package-level state</h3>
|
||||
<p>Yaegi supports package-level variables captured in closures. This is the standard way to maintain state across event callbacks:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">package</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> main</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">import</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit/ext</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">var</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> callCount </span><span style="color:#D73A49;--shiki-dark:#F97583">int</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> Init</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">api</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">API</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> api.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnToolCall</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">_</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolCallEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#E36209;--shiki-dark:#FFAB70">ctx</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> callCount</span><span style="color:#D73A49;--shiki-dark:#F97583">++</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetFooter</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">HeaderFooterConfig</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Content: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WidgetContent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Text: fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Sprintf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Tools called: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, callCount),</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>`,headings:[{depth:2,text:"Auto-discovery",id:"auto-discovery"},{depth:2,text:"Explicit loading",id:"explicit-loading"},{depth:2,text:"Disabling extensions",id:"disabling-extensions"},{depth:2,text:"Installing from git",id:"installing-from-git"},{depth:2,text:"Extension structure",id:"extension-structure"},{depth:3,text:"Single-file extensions",id:"single-file-extensions"},{depth:3,text:"Subdirectory extensions",id:"subdirectory-extensions"},{depth:3,text:"Package-level state",id:"package-level-state"}],raw:`
|
||||
# Loading Extensions
|
||||
|
||||
## Auto-discovery
|
||||
|
||||
Kit automatically discovers and loads extensions from these paths, in order:
|
||||
|
||||
| Path | Scope |
|
||||
|------|-------|
|
||||
| \`~/.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
|
||||
|
||||
Load extensions by path using the \`-e\` flag:
|
||||
|
||||
\`\`\`bash
|
||||
kit -e path/to/extension.go
|
||||
\`\`\`
|
||||
|
||||
Load multiple extensions:
|
||||
|
||||
\`\`\`bash
|
||||
kit -e ext1.go -e ext2.go
|
||||
\`\`\`
|
||||
|
||||
## Disabling extensions
|
||||
|
||||
Disable all auto-discovered extensions:
|
||||
|
||||
\`\`\`bash
|
||||
kit --no-extensions
|
||||
\`\`\`
|
||||
|
||||
You can combine \`--no-extensions\` with \`-e\` to load only specific extensions:
|
||||
|
||||
\`\`\`bash
|
||||
kit --no-extensions -e my-extension.go
|
||||
\`\`\`
|
||||
|
||||
## Installing from git
|
||||
|
||||
Install extensions from git repositories using \`kit install\`:
|
||||
|
||||
\`\`\`bash
|
||||
# Install globally (to ~/.local/share/kit/git/)
|
||||
kit install https://github.com/user/my-kit-extension.git
|
||||
|
||||
# Install project-locally (to .kit/git/)
|
||||
kit install -l https://github.com/user/my-kit-extension.git
|
||||
|
||||
# Update an installed package
|
||||
kit install -u https://github.com/user/my-kit-extension.git
|
||||
|
||||
# Remove
|
||||
kit install --uninstall my-kit-extension
|
||||
\`\`\`
|
||||
|
||||
## Extension structure
|
||||
|
||||
### Single-file extensions
|
||||
|
||||
A single \`.go\` file with an \`Init\` function:
|
||||
|
||||
\`\`\`go
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import "kit/ext"
|
||||
|
||||
func Init(api ext.API) {
|
||||
// register handlers, tools, commands, etc.
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
The \`//go:build ignore\` directive prevents the Go toolchain from trying to compile the file as part of a normal build.
|
||||
|
||||
### Subdirectory extensions
|
||||
|
||||
For more complex extensions, create a directory with a \`main.go\` entry point:
|
||||
|
||||
\`\`\`
|
||||
.kit/extensions/my-extension/
|
||||
├── main.go # Must contain Init(api ext.API)
|
||||
├── helpers.go # Additional source files
|
||||
└── config.go
|
||||
\`\`\`
|
||||
|
||||
### Package-level state
|
||||
|
||||
Yaegi supports package-level variables captured in closures. This is the standard way to maintain state across event callbacks:
|
||||
|
||||
\`\`\`go
|
||||
package main
|
||||
|
||||
import "kit/ext"
|
||||
|
||||
var callCount int
|
||||
|
||||
func Init(api ext.API) {
|
||||
api.OnToolCall(func(_ ext.ToolCallEvent, ctx ext.Context) {
|
||||
callCount++
|
||||
ctx.SetFooter(ext.HeaderFooterConfig{
|
||||
Content: ext.WidgetContent{
|
||||
Text: fmt.Sprintf("Tools called: %d", callCount),
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
\`\`\`
|
||||
`};export{s as default};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,56 @@
|
||||
const e={frontmatter:{title:"Extension System",description:"Overview of Kit's Go-based extension system.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="extension-system"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#extension-system"><span class="icon icon-link"></span></a>Extension System</h1>
|
||||
<p>Extensions are Go source files interpreted at runtime via <a href="https://github.com/traefik/yaegi">Yaegi</a>. They can add custom tools, slash commands, widgets, keyboard shortcuts, and intercept lifecycle events — all without recompiling Kit.</p>
|
||||
<h2 id="minimal-extension"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#minimal-extension"><span class="icon icon-link"></span></a>Minimal extension</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">//go:build ignore</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">package</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> main</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">import</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit/ext</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> Init</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">api</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">API</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> api.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnSessionStart</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">_</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SessionStartEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#E36209;--shiki-dark:#FFAB70">ctx</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetFooter</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">HeaderFooterConfig</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Content: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WidgetContent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Text: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Custom Footer"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<p>Run it with:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -e</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> examples/extensions/minimal.go</span></span></code></pre>
|
||||
<h2 id="how-extensions-work"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#how-extensions-work"><span class="icon icon-link"></span></a>How extensions work</h2>
|
||||
<ol>
|
||||
<li>Kit discovers extension files from <a href="/extensions/loading">auto-discovery paths</a> or explicit <code>-e</code> flags</li>
|
||||
<li>Each <code>.go</code> file is loaded into a Yaegi interpreter with access to the <code>kit/ext</code> package</li>
|
||||
<li>Kit calls the <code>Init(api ext.API)</code> function in each extension</li>
|
||||
<li>The extension registers callbacks, tools, commands, and UI components via the <code>api</code> and <code>ctx</code> objects</li>
|
||||
</ol>
|
||||
<h2 id="key-concepts"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#key-concepts"><span class="icon icon-link"></span></a>Key concepts</h2>
|
||||
<h3 id="the-api-object"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#the-api-object"><span class="icon icon-link"></span></a>The <code>API</code> object</h3>
|
||||
<p>Passed to <code>Init()</code>, the <code>API</code> object is used to register lifecycle event handlers and static components:</p>
|
||||
<ul>
|
||||
<li><strong>Lifecycle handlers</strong> — <code>api.OnSessionStart(...)</code>, <code>api.OnToolCall(...)</code>, etc.</li>
|
||||
<li><strong>Tools</strong> — <code>api.RegisterTool(ext.ToolDef{...})</code></li>
|
||||
<li><strong>Commands</strong> — <code>api.RegisterCommand(ext.CommandDef{...})</code></li>
|
||||
<li><strong>Shortcuts</strong> — <code>api.RegisterShortcut(ext.ShortcutDef{...}, handler)</code></li>
|
||||
<li><strong>Tool renderers</strong> — <code>api.RegisterToolRenderer(ext.ToolRenderConfig{...})</code></li>
|
||||
<li><strong>Message renderers</strong> — <code>api.RegisterMessageRenderer(ext.MessageRendererConfig{...})</code></li>
|
||||
<li><strong>Options</strong> — <code>api.RegisterOption(ext.OptionDef{...})</code></li>
|
||||
</ul>
|
||||
<h3 id="the-context-object"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#the-context-object"><span class="icon icon-link"></span></a>The <code>Context</code> object</h3>
|
||||
<p>Passed to event handlers, the <code>Context</code> object provides runtime access to Kit's state and UI:</p>
|
||||
<ul>
|
||||
<li><strong>Output</strong> — <code>ctx.Print(...)</code>, <code>ctx.PrintInfo(...)</code>, <code>ctx.PrintError(...)</code></li>
|
||||
<li><strong>UI components</strong> — <code>ctx.SetWidget(...)</code>, <code>ctx.SetHeader(...)</code>, <code>ctx.SetFooter(...)</code>, <code>ctx.SetStatus(...)</code></li>
|
||||
<li><strong>Editor</strong> — <code>ctx.SetEditor(...)</code>, <code>ctx.ResetEditor()</code></li>
|
||||
<li><strong>Prompts</strong> — <code>ctx.PromptSelect(...)</code>, <code>ctx.PromptConfirm(...)</code>, <code>ctx.PromptInput(...)</code></li>
|
||||
<li><strong>Overlays</strong> — <code>ctx.ShowOverlay(...)</code></li>
|
||||
<li><strong>Messages</strong> — <code>ctx.SendMessage(...)</code>, <code>ctx.GetMessages()</code></li>
|
||||
<li><strong>Model</strong> — <code>ctx.SetModel(...)</code>, <code>ctx.GetAvailableModels()</code></li>
|
||||
<li><strong>Tools</strong> — <code>ctx.GetAllTools()</code>, <code>ctx.SetActiveTools(...)</code></li>
|
||||
<li><strong>Context stats</strong> — <code>ctx.GetContextStats()</code></li>
|
||||
<li><strong>Session data</strong> — <code>ctx.AppendEntry(...)</code>, <code>ctx.GetEntries(...)</code> (append-only, in conversation tree)</li>
|
||||
<li><strong>Session state</strong> — <code>ctx.SetState(...)</code>, <code>ctx.GetState(...)</code>, <code>ctx.DeleteState(...)</code>, <code>ctx.ListState()</code> (last-write-wins, sidecar file)</li>
|
||||
<li><strong>Subagents</strong> — <code>ctx.SpawnSubagent(...)</code></li>
|
||||
<li><strong>LLM completion</strong> — <code>ctx.Complete(...)</code></li>
|
||||
<li><strong>Custom events</strong> — <code>ctx.EmitCustomEvent(...)</code></li>
|
||||
</ul>
|
||||
<p>See <a href="/extensions/capabilities">Capabilities</a> for full details on each component type, and <a href="/extensions/testing">Testing</a> for writing tests for your extensions.</p>`,headings:[{depth:2,text:"Minimal extension",id:"minimal-extension"},{depth:2,text:"How extensions work",id:"how-extensions-work"},{depth:2,text:"Key concepts",id:"key-concepts"},{depth:3,text:"The API object",id:"the-api-object"},{depth:3,text:"The Context object",id:"the-context-object"}],raw:'\n# Extension System\n\nExtensions are Go source files interpreted at runtime via [Yaegi](https://github.com/traefik/yaegi). They can add custom tools, slash commands, widgets, keyboard shortcuts, and intercept lifecycle events — all without recompiling Kit.\n\n## Minimal extension\n\n```go\n//go:build ignore\n\npackage main\n\nimport "kit/ext"\n\nfunc Init(api ext.API) {\n api.OnSessionStart(func(_ ext.SessionStartEvent, ctx ext.Context) {\n ctx.SetFooter(ext.HeaderFooterConfig{\n Content: ext.WidgetContent{Text: "Custom Footer"},\n })\n })\n}\n```\n\nRun it with:\n\n```bash\nkit -e examples/extensions/minimal.go\n```\n\n## How extensions work\n\n1. Kit discovers extension files from [auto-discovery paths](/extensions/loading) or explicit `-e` flags\n2. Each `.go` file is loaded into a Yaegi interpreter with access to the `kit/ext` package\n3. Kit calls the `Init(api ext.API)` function in each extension\n4. The extension registers callbacks, tools, commands, and UI components via the `api` and `ctx` objects\n\n## Key concepts\n\n### The `API` object\n\nPassed to `Init()`, the `API` object is used to register lifecycle event handlers and static components:\n\n- **Lifecycle handlers** — `api.OnSessionStart(...)`, `api.OnToolCall(...)`, etc.\n- **Tools** — `api.RegisterTool(ext.ToolDef{...})`\n- **Commands** — `api.RegisterCommand(ext.CommandDef{...})`\n- **Shortcuts** — `api.RegisterShortcut(ext.ShortcutDef{...}, handler)`\n- **Tool renderers** — `api.RegisterToolRenderer(ext.ToolRenderConfig{...})`\n- **Message renderers** — `api.RegisterMessageRenderer(ext.MessageRendererConfig{...})`\n- **Options** — `api.RegisterOption(ext.OptionDef{...})`\n\n### The `Context` object\n\nPassed to event handlers, the `Context` object provides runtime access to Kit\'s state and UI:\n\n- **Output** — `ctx.Print(...)`, `ctx.PrintInfo(...)`, `ctx.PrintError(...)`\n- **UI components** — `ctx.SetWidget(...)`, `ctx.SetHeader(...)`, `ctx.SetFooter(...)`, `ctx.SetStatus(...)`\n- **Editor** — `ctx.SetEditor(...)`, `ctx.ResetEditor()`\n- **Prompts** — `ctx.PromptSelect(...)`, `ctx.PromptConfirm(...)`, `ctx.PromptInput(...)`\n- **Overlays** — `ctx.ShowOverlay(...)`\n- **Messages** — `ctx.SendMessage(...)`, `ctx.GetMessages()`\n- **Model** — `ctx.SetModel(...)`, `ctx.GetAvailableModels()`\n- **Tools** — `ctx.GetAllTools()`, `ctx.SetActiveTools(...)`\n- **Context stats** — `ctx.GetContextStats()`\n- **Session data** — `ctx.AppendEntry(...)`, `ctx.GetEntries(...)` (append-only, in conversation tree)\n- **Session state** — `ctx.SetState(...)`, `ctx.GetState(...)`, `ctx.DeleteState(...)`, `ctx.ListState()` (last-write-wins, sidecar file)\n- **Subagents** — `ctx.SpawnSubagent(...)`\n- **LLM completion** — `ctx.Complete(...)`\n- **Custom events** — `ctx.EmitCustomEvent(...)`\n\nSee [Capabilities](/extensions/capabilities) for full details on each component type, and [Testing](/extensions/testing) for writing tests for your extensions.\n'};export{e as default};
|
||||
@@ -0,0 +1,797 @@
|
||||
const s={frontmatter:{title:"Go SDK",description:"Embed Kit in your Go applications.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="go-sdk"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#go-sdk"><span class="icon icon-link"></span></a>Go SDK</h1>
|
||||
<p>The <code>pkg/kit</code> package lets you embed Kit as a library in your Go applications.</p>
|
||||
<h2 id="installation"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#installation"><span class="icon icon-link"></span></a>Installation</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> get</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> github.com/mark3labs/kit/pkg/kit</span></span></code></pre>
|
||||
<h2 id="basic-usage"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#basic-usage"><span class="icon icon-link"></span></a>Basic usage</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">package</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> main</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">import</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">context</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">log</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#6F42C1;--shiki-dark:#B392F0">github.com/mark3labs/kit/pkg/kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="color:#24292E;--shiki-dark:#E1E4E8">() {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> context.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Background</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Create Kit instance with default configuration</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> host, err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#005CC5;--shiki-dark:#79B8FF">nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> err </span><span style="color:#D73A49;--shiki-dark:#F97583">!=</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> log.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Fatal</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(err)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> defer</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Close</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Send a prompt</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> response, err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Prompt</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"What is 2+2?"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> err </span><span style="color:#D73A49;--shiki-dark:#F97583">!=</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> log.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Fatal</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(err)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0"> println</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(response)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h2 id="functional-options-newagent"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#functional-options-newagent"><span class="icon icon-link"></span></a>Functional options (<code>NewAgent</code>)</h2>
|
||||
<p>For simple programmatic setups, <code>kit.NewAgent</code> offers an ergonomic
|
||||
functional-options front door over <code>kit.New</code>. Streaming is <strong>enabled by
|
||||
default</strong>; pass <code>kit.WithStreaming(false)</code> to opt out.</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">NewAgent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WithModel</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"anthropic/claude-sonnet-4-5-20250929"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">),</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WithSystemPrompt</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"You are a helpful assistant."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">),</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WithMaxTokens</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">8192</span><span style="color:#24292E;--shiki-dark:#E1E4E8">),</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WithThinkingLevel</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"medium"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">),</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Ephemeral</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(), </span><span style="color:#6A737D;--shiki-dark:#6A737D">// in-memory session, no persistence</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> err </span><span style="color:#D73A49;--shiki-dark:#F97583">!=</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> log.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Fatal</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(err)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">defer</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Close</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span></code></pre>
|
||||
<p>Available options:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Option</th>
|
||||
<th>Sets</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>WithModel(string)</code></td>
|
||||
<td><code>Options.Model</code> (provider/model format)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithSystemPrompt(string)</code></td>
|
||||
<td><code>Options.SystemPrompt</code> (inline text or file path)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithStreaming(bool)</code></td>
|
||||
<td><code>Options.Streaming</code> (default <code>true</code> under <code>NewAgent</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithMaxTokens(int)</code></td>
|
||||
<td><code>Options.MaxTokens</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithThinkingLevel(string)</code></td>
|
||||
<td><code>Options.ThinkingLevel</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithTools(...Tool)</code></td>
|
||||
<td><code>Options.Tools</code> (replaces the default set)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithExtraTools(...Tool)</code></td>
|
||||
<td><code>Options.ExtraTools</code> (adds alongside defaults)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithProviderAPIKey(string)</code></td>
|
||||
<td><code>Options.ProviderAPIKey</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithProviderURL(string)</code></td>
|
||||
<td><code>Options.ProviderURL</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithConfigFile(string)</code></td>
|
||||
<td><code>Options.ConfigFile</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>WithDebug()</code></td>
|
||||
<td><code>Options.Debug = true</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Ephemeral()</code></td>
|
||||
<td><code>Options.NoSession = true</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Options are applied in order, so later options override earlier ones. <code>Option</code>
|
||||
is a plain <code>func(*Options)</code>, so you can define your own. For advanced
|
||||
configuration not covered by the helpers (custom MCP config, in-process MCP
|
||||
servers, session backends, MCP task tuning) construct an <code>Options</code> value
|
||||
explicitly and call <code>kit.New</code>.</p>
|
||||
<h3 id="when-to-use-which"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#when-to-use-which"><span class="icon icon-link"></span></a>When to use which</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Constructor</th>
|
||||
<th>Use when</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>kit.NewAgent(ctx, ...Option)</code></td>
|
||||
<td>Quick programmatic setups; you only need the common fields. Streaming defaults on.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>kit.New(ctx, *Options)</code></td>
|
||||
<td>You need fields without a <code>With*</code> helper (<code>MCPConfig</code>, <code>InProcessMCPServers</code>, <code>SessionManager</code>, MCP task tuning, etc.), or you already hold an <code>Options</code> value.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="per-instance-config-isolation"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#per-instance-config-isolation"><span class="icon icon-link"></span></a>Per-instance config isolation</h2>
|
||||
<p>Each <code>kit.New</code> / <code>kit.NewAgent</code> call owns an <strong>isolated configuration store</strong>,
|
||||
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 (<code>SetModel</code>, <code>SetThinkingLevel</code>) only touch the owning
|
||||
instance. This makes subagent spawning and multi-Kit embedding race-free with
|
||||
no external synchronization required.</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">a, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">NewAgent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WithThinkingLevel</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"low"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">))</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">b, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">NewAgent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WithThinkingLevel</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"high"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">))</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">a.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetThinkingLevel</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"medium"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// a.GetThinkingLevel() == "medium"; b.GetThinkingLevel() is still "high"</span></span></code></pre>
|
||||
<h2 id="multi-turn-conversations"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#multi-turn-conversations"><span class="icon icon-link"></span></a>Multi-turn conversations</h2>
|
||||
<p>Conversations retain context automatically across calls:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Prompt</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"My name is Alice"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">response, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Prompt</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"What's my name?"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// response: "Your name is Alice"</span></span></code></pre>
|
||||
<h2 id="additional-prompt-methods"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#additional-prompt-methods"><span class="icon icon-link"></span></a>Additional prompt methods</h2>
|
||||
<p>The SDK provides several prompt variants:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>Prompt(ctx, message)</code></td>
|
||||
<td>Simple prompt, returns response string</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>PromptWithOptions(ctx, message, opts)</code></td>
|
||||
<td>With per-call options</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>PromptResult(ctx, message)</code></td>
|
||||
<td>Returns full <code>TurnResult</code> with usage stats</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>PromptResultWithFiles(ctx, message, files)</code></td>
|
||||
<td>Multimodal with file attachments</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Steer(ctx, instruction)</code></td>
|
||||
<td>System-level steering without user message</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>FollowUp(ctx, text)</code></td>
|
||||
<td>Continue without new user input</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="custom-tools"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#custom-tools"><span class="icon icon-link"></span></a>Custom tools</h2>
|
||||
<p>Create custom tools with <code>kit.NewTool</code>. The JSON schema is auto-generated from the input struct — no external dependencies required:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">type</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> WeatherInput</span><span style="color:#D73A49;--shiki-dark:#F97583"> struct</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> City </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> \`json:"city" description:"City name"\`</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">weatherTool </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">NewTool</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"get_weather"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Get current weather for a city"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">ctx</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#E36209;--shiki-dark:#FFAB70">input</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> WeatherInput</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) (</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolOutput</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#D73A49;--shiki-dark:#F97583">error</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> return</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">TextResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"72°F, sunny in "</span><span style="color:#D73A49;--shiki-dark:#F97583"> +</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> input.City), </span><span style="color:#005CC5;--shiki-dark:#79B8FF">nil</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Options</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ExtraTools: []</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Tool</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{weatherTool},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
|
||||
<p>Struct tags control the schema:</p>
|
||||
<ul>
|
||||
<li><code>json:"name"</code> — parameter name</li>
|
||||
<li><code>description:"..."</code> — description shown to the LLM</li>
|
||||
<li><code>enum:"a,b,c"</code> — restrict valid values</li>
|
||||
<li><code>omitempty</code> — marks the parameter as optional</li>
|
||||
</ul>
|
||||
<p>Return values:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Helper</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>kit.TextResult(s)</code></td>
|
||||
<td>Successful text result</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>kit.ErrorResult(s)</code></td>
|
||||
<td>Error result (LLM sees it as a tool error)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>kit.ImageResult(s, data, mediaType)</code></td>
|
||||
<td>Image result with binary data (e.g. <code>"image/png"</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>kit.MediaResult(s, data, mediaType)</code></td>
|
||||
<td>Non-image media result (e.g. <code>"audio/mpeg"</code>)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Binary data (images, audio, etc.) in <code>ToolOutput.Data</code> is automatically forwarded to the LLM when <code>MediaType</code> is set. For advanced use, return a <code>kit.ToolOutput</code> struct directly with <code>Data</code>, <code>MediaType</code>, and <code>Metadata</code> fields.</p>
|
||||
<p>Use <code>kit.NewParallelTool</code> for tools that are safe to run concurrently. Use <code>kit.ToolCallIDFromContext(ctx)</code> to retrieve the LLM-assigned call ID for logging or tracing.</p>
|
||||
<h2 id="generation--provider-overrides"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#generation--provider-overrides"><span class="icon icon-link"></span></a>Generation & provider overrides</h2>
|
||||
<p>SDK consumers can configure generation parameters and provider endpoints
|
||||
entirely in-code via <code>Options</code>, without touching <code>.kit.yml</code> or <code>viper.Set()</code>:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Options</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Model: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"anthropic/claude-sonnet-4-5-20250929"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> MaxTokens: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">16384</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#6A737D;--shiki-dark:#6A737D">// 0 = auto-resolve (env → config → per-model → floor)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ThinkingLevel: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"high"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#6A737D;--shiki-dark:#6A737D">// "off" | "none" | "minimal" | "low" | "medium" | "high"</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Temperature: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ptrFloat32</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">0.2</span><span style="color:#24292E;--shiki-dark:#E1E4E8">), </span><span style="color:#6A737D;--shiki-dark:#6A737D">// nil = provider/per-model default</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ProviderAPIKey: os.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Getenv</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"MY_SECRET"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">), </span><span style="color:#6A737D;--shiki-dark:#6A737D">// overrides pre-existing viper state</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ProviderURL: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"https://proxy.internal/v1"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ptrFloat32</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">v</span><span style="color:#D73A49;--shiki-dark:#F97583"> float32</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) </span><span style="color:#D73A49;--shiki-dark:#F97583">*float32</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="color:#D73A49;--shiki-dark:#F97583">return</span><span style="color:#D73A49;--shiki-dark:#F97583"> &</span><span style="color:#24292E;--shiki-dark:#E1E4E8">v }</span></span></code></pre>
|
||||
<p>See <a href="/sdk/options#generation-parameters">Options</a> for the full field reference,
|
||||
including <code>TopP</code>, <code>TopK</code>, <code>FrequencyPenalty</code>, <code>PresencePenalty</code>, and <code>TLSSkipVerify</code>.</p>
|
||||
<h2 id="event-system"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#event-system"><span class="icon icon-link"></span></a>Event system</h2>
|
||||
<p>Subscribe to events for monitoring:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">unsubscribe </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnToolCall</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">event</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolCallEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Println</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Tool called:"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, event.Name)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">defer</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> unsubscribe</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnToolResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">event</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolResultEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Println</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Tool result:"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, event.Name)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnMessageUpdate</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">event</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">MessageUpdateEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Print</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(event.Chunk)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
|
||||
<h2 id="model-management"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#model-management"><span class="icon icon-link"></span></a>Model management</h2>
|
||||
<p>Switch models at runtime:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetModel</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"openai/gpt-4o"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">info </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetModelInfo</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">models </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetAvailableModels</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span></code></pre>
|
||||
<h2 id="dynamic-mcp-servers"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#dynamic-mcp-servers"><span class="icon icon-link"></span></a>Dynamic MCP servers</h2>
|
||||
<p>Add and remove MCP servers at runtime:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">n, err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AddMCPServer</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"github"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">MCPServerConfig</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Command: []</span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"npx"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"-y"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"@modelcontextprotocol/server-github"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Printf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Loaded </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%d</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> tools</span><span style="color:#005CC5;--shiki-dark:#79B8FF">\\n</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, n)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">err </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">RemoveMCPServer</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"github"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">servers </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ListMCPServers</span><span style="color:#24292E;--shiki-dark:#E1E4E8">() </span><span style="color:#6A737D;--shiki-dark:#6A737D">// []kit.MCPServerStatus</span></span></code></pre>
|
||||
<h3 id="in-process-mcp-servers"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#in-process-mcp-servers"><span class="icon icon-link"></span></a>In-process MCP servers</h3>
|
||||
<p>Register mcp-go servers running in the same process — zero subprocess overhead:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">import</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">github.com/mark3labs/mcp-go/mcp</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">github.com/mark3labs/mcp-go/server</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">mcpSrv </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> server.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">NewMCPServer</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-tools"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"1.0.0"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> server.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WithToolCapabilities</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#005CC5;--shiki-dark:#79B8FF">true</span><span style="color:#24292E;--shiki-dark:#E1E4E8">),</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">mcpSrv.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AddTool</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(mcp.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">NewTool</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"search_docs"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> mcp.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WithDescription</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Search documentation"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">),</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> mcp.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">WithString</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"query"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, mcp.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Required</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()),</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">), searchHandler)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// At init time</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Options</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> InProcessMCPServers: </span><span style="color:#D73A49;--shiki-dark:#F97583">map</span><span style="color:#24292E;--shiki-dark:#E1E4E8">[</span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#24292E;--shiki-dark:#E1E4E8">]</span><span style="color:#D73A49;--shiki-dark:#F97583">*</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">MCPServer</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "docs"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: mcpSrv,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Or at runtime</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">n, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AddInProcessMCPServer</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"docs"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, mcpSrv)</span></span></code></pre>
|
||||
<h2 id="runtime-skills-and-context-files"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#runtime-skills-and-context-files"><span class="icon icon-link"></span></a>Runtime skills and context files</h2>
|
||||
<p>Kit auto-discovers skills and <code>AGENTS.md</code>-style context files during <code>New()</code>,
|
||||
but multi-tenant hosts (chatbots, web services, per-user agents) often need
|
||||
to swap these <strong>after</strong> construction. The runtime mutators below recompose
|
||||
the system prompt and apply it to the agent so the next turn picks up the
|
||||
updated instructions — no restart, no file shuffling.</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Add a programmatic skill — no file on disk required.</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AddSkill</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Skill</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Name: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"polite-french"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Description: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Respond in French and always greet the user."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Content: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Always reply in French. Open every response with 'Bonjour'."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Or load one from disk.</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadAndAddSkill</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"/var/skills/refund-policy.md"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Project context (AGENTS.md equivalents): inline content from a DB...</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AddContextFileContent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Sprintf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"session://</span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="color:#032F62;--shiki-dark:#9ECBFF">/AGENTS.md"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, userID),</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> rulesFromDB,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// ...or load from disk.</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadAndAddContextFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"/etc/agents/tenant-acme.md"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Remove individually when a session ends.</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">RemoveSkill</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"polite-french"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">RemoveContextFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Sprintf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"session://</span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="color:#032F62;--shiki-dark:#9ECBFF">/AGENTS.md"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, userID))</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Or replace the whole set in one call.</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetSkills</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(activeSkillsForUser)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetContextFiles</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(activeContextForUser)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Inspect current state (snapshot copies — safe to mutate).</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">skills </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetSkills</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">ctxFiles </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetContextFiles</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span></code></pre>
|
||||
<p>Key points:</p>
|
||||
<ul>
|
||||
<li><strong>Auto-refresh.</strong> Every <code>Add*</code> / <code>Remove*</code> / <code>Set*</code> call recomposes the system
|
||||
prompt against the captured base prompt (preserving per-model overrides and
|
||||
<code>--system-prompt</code> resolution) and pushes the result onto the agent. Call
|
||||
<code>host.RefreshSystemPrompt()</code> only if you mutate state through a different
|
||||
path and need to force a re-render.</li>
|
||||
<li><strong>Dedup keys.</strong> Skills dedupe by <code>Name</code>; context files dedupe by <code>Path</code>.
|
||||
Re-adding the same key replaces the entry instead of appending a duplicate.</li>
|
||||
<li><strong>Path is opaque.</strong> <code>ContextFile.Path</code> does not have to point at a real file
|
||||
— it's only used for dedup and for the <code>Instructions from: <Path></code> header
|
||||
injected into the prompt. URIs like <code>session://user-123/AGENTS.md</code> work fine.</li>
|
||||
<li><strong>Thread safety.</strong> All readers and mutators are safe to call concurrently
|
||||
from multiple goroutines; the underlying state is guarded by an internal
|
||||
<code>RWMutex</code>.</li>
|
||||
<li><strong>Init-time options still apply.</strong> <code>Options.Skills</code>, <code>Options.SkillsDir</code>,
|
||||
<code>Options.NoSkills</code>, and <code>Options.NoContextFiles</code> continue to control the
|
||||
startup set; the runtime API mutates from whatever state <code>New()</code> produced.
|
||||
See <a href="/sdk/options#skills--configuration">SDK options</a>.</li>
|
||||
</ul>
|
||||
<h2 id="mcp-prompts-and-resources"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#mcp-prompts-and-resources"><span class="icon icon-link"></span></a>MCP prompts and resources</h2>
|
||||
<p>Query prompts and resources exposed by connected MCP servers:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// List and expand prompts</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">prompts </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ListMCPPrompts</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">result, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetMCPPrompt</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"server"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"prompt-name"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#D73A49;--shiki-dark:#F97583">map</span><span style="color:#24292E;--shiki-dark:#E1E4E8">[</span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#24292E;--shiki-dark:#E1E4E8">]</span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"key"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"value"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// List and read resources</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">resources </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ListMCPResources</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">content, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ReadMCPResource</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"server"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"file:///path"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
|
||||
<h2 id="mcp-tasks-long-running-tools"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#mcp-tasks-long-running-tools"><span class="icon icon-link"></span></a>MCP tasks (long-running tools)</h2>
|
||||
<p>Kit advertises <a href="https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks">MCP task support</a>
|
||||
during <code>initialize</code>, so cooperating servers can return a <code>taskId</code> immediately
|
||||
and let Kit poll <code>tasks/get</code> / <code>tasks/result</code> until the operation completes.
|
||||
This avoids HTTP/SSE proxy timeouts on long tools and gives you clean
|
||||
cancellation via context.</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Options</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> MCPTaskMode: </span><span style="color:#D73A49;--shiki-dark:#F97583">map</span><span style="color:#24292E;--shiki-dark:#E1E4E8">[</span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#24292E;--shiki-dark:#E1E4E8">]</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">MCPTaskMode</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "build-server"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: kit.MCPTaskModeAlways,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> MCPTaskProgress: </span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">p</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">MCPTaskProgress</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> log.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Printf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="color:#032F62;--shiki-dark:#9ECBFF">: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, p.TaskID, p.Status)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> },</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Inspect / cancel in-flight tasks</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">tasks, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ListMCPTasks</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"build-server"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">_, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">CancelMCPTask</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"build-server"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, tasks[</span><span style="color:#005CC5;--shiki-dark:#79B8FF">0</span><span style="color:#24292E;--shiki-dark:#E1E4E8">].TaskID)</span></span></code></pre>
|
||||
<p>Defaults to <code>MCPTaskModeAuto</code> per server, so any existing MCP server keeps
|
||||
its previous synchronous behaviour. See <a href="/sdk/options#mcp-tasks">SDK options → MCP Tasks</a>
|
||||
for the full surface.</p>
|
||||
<h2 id="context-and-compaction"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#context-and-compaction"><span class="icon icon-link"></span></a>Context and compaction</h2>
|
||||
<p>Monitor and manage context usage:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">tokens </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">EstimateContextTokens</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">stats </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetContextStats</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ShouldCompact</span><span style="color:#24292E;--shiki-dark:#E1E4E8">() {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> result, err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Compact</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#005CC5;--shiki-dark:#79B8FF">nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">""</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h2 id="in-process-subagents"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#in-process-subagents"><span class="icon icon-link"></span></a>In-process subagents</h2>
|
||||
<p>Spawn child Kit instances without subprocess overhead:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">result, err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Subagent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SubagentConfig</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Prompt: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Analyze the test files"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Model: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"anthropic/claude-haiku-3-5-20241022"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> NoSession: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">true</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Timeout: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">2</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> time.Minute,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
|
||||
<p>See <a href="/sdk/options">Options</a>, <a href="/sdk/callbacks">Callbacks</a>, and <a href="/sdk/sessions">Sessions</a> for more details.</p>`,headings:[{depth:2,text:"Installation",id:"installation"},{depth:2,text:"Basic usage",id:"basic-usage"},{depth:2,text:"Functional options (NewAgent)",id:"functional-options-newagent"},{depth:3,text:"When to use which",id:"when-to-use-which"},{depth:2,text:"Per-instance config isolation",id:"per-instance-config-isolation"},{depth:2,text:"Multi-turn conversations",id:"multi-turn-conversations"},{depth:2,text:"Additional prompt methods",id:"additional-prompt-methods"},{depth:2,text:"Custom tools",id:"custom-tools"},{depth:2,text:"Generation & provider overrides",id:"generation--provider-overrides"},{depth:2,text:"Event system",id:"event-system"},{depth:2,text:"Model management",id:"model-management"},{depth:2,text:"Dynamic MCP servers",id:"dynamic-mcp-servers"},{depth:3,text:"In-process MCP servers",id:"in-process-mcp-servers"},{depth:2,text:"Runtime skills and context files",id:"runtime-skills-and-context-files"},{depth:2,text:"MCP prompts and resources",id:"mcp-prompts-and-resources"},{depth:2,text:"MCP tasks (long-running tools)",id:"mcp-tasks-long-running-tools"},{depth:2,text:"Context and compaction",id:"context-and-compaction"},{depth:2,text:"In-process subagents",id:"in-process-subagents"}],raw:`
|
||||
# Go SDK
|
||||
|
||||
The \`pkg/kit\` package lets you embed Kit as a library in your Go applications.
|
||||
|
||||
## Installation
|
||||
|
||||
\`\`\`bash
|
||||
go get github.com/mark3labs/kit/pkg/kit
|
||||
\`\`\`
|
||||
|
||||
## Basic usage
|
||||
|
||||
\`\`\`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 host.Close()
|
||||
|
||||
// Send a prompt
|
||||
response, err := host.Prompt(ctx, "What is 2+2?")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
println(response)
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## 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
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer host.Close()
|
||||
\`\`\`
|
||||
|
||||
Available options:
|
||||
|
||||
| Option | Sets |
|
||||
|--------|------|
|
||||
| \`WithModel(string)\` | \`Options.Model\` (provider/model format) |
|
||||
| \`WithSystemPrompt(string)\` | \`Options.SystemPrompt\` (inline text or file path) |
|
||||
| \`WithStreaming(bool)\` | \`Options.Streaming\` (default \`true\` under \`NewAgent\`) |
|
||||
| \`WithMaxTokens(int)\` | \`Options.MaxTokens\` |
|
||||
| \`WithThinkingLevel(string)\` | \`Options.ThinkingLevel\` |
|
||||
| \`WithTools(...Tool)\` | \`Options.Tools\` (replaces the default set) |
|
||||
| \`WithExtraTools(...Tool)\` | \`Options.ExtraTools\` (adds alongside defaults) |
|
||||
| \`WithProviderAPIKey(string)\` | \`Options.ProviderAPIKey\` |
|
||||
| \`WithProviderURL(string)\` | \`Options.ProviderURL\` |
|
||||
| \`WithConfigFile(string)\` | \`Options.ConfigFile\` |
|
||||
| \`WithDebug()\` | \`Options.Debug = true\` |
|
||||
| \`Ephemeral()\` | \`Options.NoSession = true\` |
|
||||
|
||||
Options are applied in order, so later options override earlier ones. \`Option\`
|
||||
is a plain \`func(*Options)\`, so you can define your own. 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\`.
|
||||
|
||||
### When to use which
|
||||
|
||||
| Constructor | Use when |
|
||||
|-------------|----------|
|
||||
| \`kit.NewAgent(ctx, ...Option)\` | Quick programmatic setups; you only need the common fields. Streaming defaults on. |
|
||||
| \`kit.New(ctx, *Options)\` | You need fields without a \`With*\` helper (\`MCPConfig\`, \`InProcessMCPServers\`, \`SessionManager\`, MCP task tuning, etc.), or you already hold an \`Options\` value. |
|
||||
|
||||
## 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.
|
||||
|
||||
\`\`\`go
|
||||
a, _ := kit.NewAgent(ctx, kit.WithThinkingLevel("low"))
|
||||
b, _ := kit.NewAgent(ctx, kit.WithThinkingLevel("high"))
|
||||
|
||||
a.SetThinkingLevel(ctx, "medium")
|
||||
// a.GetThinkingLevel() == "medium"; b.GetThinkingLevel() is still "high"
|
||||
\`\`\`
|
||||
|
||||
## Multi-turn conversations
|
||||
|
||||
Conversations retain context automatically across calls:
|
||||
|
||||
\`\`\`go
|
||||
host.Prompt(ctx, "My name is Alice")
|
||||
response, _ := host.Prompt(ctx, "What's my name?")
|
||||
// response: "Your name is Alice"
|
||||
\`\`\`
|
||||
|
||||
## Additional prompt methods
|
||||
|
||||
The SDK provides several prompt variants:
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| \`Prompt(ctx, message)\` | Simple prompt, returns response string |
|
||||
| \`PromptWithOptions(ctx, message, opts)\` | With per-call options |
|
||||
| \`PromptResult(ctx, message)\` | Returns full \`TurnResult\` with usage stats |
|
||||
| \`PromptResultWithFiles(ctx, message, files)\` | Multimodal with file attachments |
|
||||
| \`Steer(ctx, instruction)\` | System-level steering without user message |
|
||||
| \`FollowUp(ctx, text)\` | Continue without new user input |
|
||||
|
||||
## Custom tools
|
||||
|
||||
Create custom tools with \`kit.NewTool\`. The JSON schema is auto-generated from the input struct — no external dependencies required:
|
||||
|
||||
\`\`\`go
|
||||
type WeatherInput struct {
|
||||
City string \`json:"city" description:"City name"\`
|
||||
}
|
||||
|
||||
weatherTool := kit.NewTool("get_weather", "Get current weather for a city",
|
||||
func(ctx context.Context, input WeatherInput) (kit.ToolOutput, error) {
|
||||
return kit.TextResult("72°F, sunny in " + input.City), nil
|
||||
},
|
||||
)
|
||||
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
ExtraTools: []kit.Tool{weatherTool},
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
Struct tags control the schema:
|
||||
|
||||
- \`json:"name"\` — parameter name
|
||||
- \`description:"..."\` — description shown to the LLM
|
||||
- \`enum:"a,b,c"\` — restrict valid values
|
||||
- \`omitempty\` — marks the parameter as optional
|
||||
|
||||
Return values:
|
||||
|
||||
| Helper | Description |
|
||||
|--------|-------------|
|
||||
| \`kit.TextResult(s)\` | Successful text result |
|
||||
| \`kit.ErrorResult(s)\` | Error result (LLM sees it as a tool error) |
|
||||
| \`kit.ImageResult(s, data, mediaType)\` | Image result with binary data (e.g. \`"image/png"\`) |
|
||||
| \`kit.MediaResult(s, data, mediaType)\` | Non-image media result (e.g. \`"audio/mpeg"\`) |
|
||||
|
||||
Binary data (images, audio, etc.) in \`ToolOutput.Data\` is automatically forwarded to the LLM when \`MediaType\` is set. For advanced use, return a \`kit.ToolOutput\` struct directly with \`Data\`, \`MediaType\`, and \`Metadata\` fields.
|
||||
|
||||
Use \`kit.NewParallelTool\` for tools that are safe to run concurrently. Use \`kit.ToolCallIDFromContext(ctx)\` to retrieve the LLM-assigned call ID for logging or tracing.
|
||||
|
||||
## Generation & provider overrides
|
||||
|
||||
SDK consumers can configure generation parameters and provider endpoints
|
||||
entirely in-code via \`Options\`, without touching \`.kit.yml\` or \`viper.Set()\`:
|
||||
|
||||
\`\`\`go
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
Model: "anthropic/claude-sonnet-4-5-20250929",
|
||||
MaxTokens: 16384, // 0 = auto-resolve (env → config → per-model → floor)
|
||||
ThinkingLevel: "high", // "off" | "none" | "minimal" | "low" | "medium" | "high"
|
||||
Temperature: ptrFloat32(0.2), // nil = provider/per-model default
|
||||
ProviderAPIKey: os.Getenv("MY_SECRET"), // overrides pre-existing viper state
|
||||
ProviderURL: "https://proxy.internal/v1",
|
||||
})
|
||||
|
||||
func ptrFloat32(v float32) *float32 { return &v }
|
||||
\`\`\`
|
||||
|
||||
See [Options](/sdk/options#generation-parameters) for the full field reference,
|
||||
including \`TopP\`, \`TopK\`, \`FrequencyPenalty\`, \`PresencePenalty\`, and \`TLSSkipVerify\`.
|
||||
|
||||
## Event system
|
||||
|
||||
Subscribe to events for monitoring:
|
||||
|
||||
\`\`\`go
|
||||
unsubscribe := host.OnToolCall(func(event kit.ToolCallEvent) {
|
||||
fmt.Println("Tool called:", event.Name)
|
||||
})
|
||||
defer unsubscribe()
|
||||
|
||||
host.OnToolResult(func(event kit.ToolResultEvent) {
|
||||
fmt.Println("Tool result:", event.Name)
|
||||
})
|
||||
|
||||
host.OnMessageUpdate(func(event kit.MessageUpdateEvent) {
|
||||
fmt.Print(event.Chunk)
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
## Model management
|
||||
|
||||
Switch models at runtime:
|
||||
|
||||
\`\`\`go
|
||||
host.SetModel(ctx, "openai/gpt-4o")
|
||||
info := host.GetModelInfo()
|
||||
models := host.GetAvailableModels()
|
||||
\`\`\`
|
||||
|
||||
## Dynamic MCP servers
|
||||
|
||||
Add and remove MCP servers at runtime:
|
||||
|
||||
\`\`\`go
|
||||
n, err := host.AddMCPServer(ctx, "github", kit.MCPServerConfig{
|
||||
Command: []string{"npx", "-y", "@modelcontextprotocol/server-github"},
|
||||
})
|
||||
fmt.Printf("Loaded %d tools\\n", n)
|
||||
|
||||
err = host.RemoveMCPServer("github")
|
||||
servers := host.ListMCPServers() // []kit.MCPServerStatus
|
||||
\`\`\`
|
||||
|
||||
### In-process MCP servers
|
||||
|
||||
Register mcp-go servers running in the same process — zero subprocess overhead:
|
||||
|
||||
\`\`\`go
|
||||
import (
|
||||
"github.com/mark3labs/mcp-go/mcp"
|
||||
"github.com/mark3labs/mcp-go/server"
|
||||
)
|
||||
|
||||
mcpSrv := server.NewMCPServer("my-tools", "1.0.0",
|
||||
server.WithToolCapabilities(true),
|
||||
)
|
||||
mcpSrv.AddTool(mcp.NewTool("search_docs",
|
||||
mcp.WithDescription("Search documentation"),
|
||||
mcp.WithString("query", mcp.Required()),
|
||||
), searchHandler)
|
||||
|
||||
// At init time
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
InProcessMCPServers: map[string]*kit.MCPServer{
|
||||
"docs": mcpSrv,
|
||||
},
|
||||
})
|
||||
|
||||
// Or at runtime
|
||||
n, _ := host.AddInProcessMCPServer(ctx, "docs", mcpSrv)
|
||||
\`\`\`
|
||||
|
||||
## Runtime skills and context files
|
||||
|
||||
Kit auto-discovers skills and \`AGENTS.md\`-style context files during \`New()\`,
|
||||
but multi-tenant hosts (chatbots, web services, per-user agents) often need
|
||||
to swap these **after** construction. The runtime mutators below recompose
|
||||
the system prompt and apply it to the agent so the next turn picks up the
|
||||
updated instructions — no restart, no file shuffling.
|
||||
|
||||
\`\`\`go
|
||||
// Add a 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")
|
||||
|
||||
// Project context (AGENTS.md equivalents): inline content from a DB...
|
||||
host.AddContextFileContent(
|
||||
fmt.Sprintf("session://%s/AGENTS.md", userID),
|
||||
rulesFromDB,
|
||||
)
|
||||
// ...or load from disk.
|
||||
host.LoadAndAddContextFile("/etc/agents/tenant-acme.md")
|
||||
|
||||
// Remove individually when a session ends.
|
||||
host.RemoveSkill("polite-french")
|
||||
host.RemoveContextFile(fmt.Sprintf("session://%s/AGENTS.md", userID))
|
||||
|
||||
// Or replace the whole set in one call.
|
||||
host.SetSkills(activeSkillsForUser)
|
||||
host.SetContextFiles(activeContextForUser)
|
||||
|
||||
// Inspect current state (snapshot copies — safe to mutate).
|
||||
skills := host.GetSkills()
|
||||
ctxFiles := host.GetContextFiles()
|
||||
\`\`\`
|
||||
|
||||
Key points:
|
||||
|
||||
- **Auto-refresh.** Every \`Add*\` / \`Remove*\` / \`Set*\` call recomposes the system
|
||||
prompt against the captured base prompt (preserving per-model overrides and
|
||||
\`--system-prompt\` resolution) and pushes the result onto the agent. Call
|
||||
\`host.RefreshSystemPrompt()\` only if you mutate state through a different
|
||||
path and need to force a re-render.
|
||||
- **Dedup keys.** Skills dedupe by \`Name\`; context files dedupe by \`Path\`.
|
||||
Re-adding the same key replaces the entry instead of appending a duplicate.
|
||||
- **Path is opaque.** \`ContextFile.Path\` does not have to point at a real file
|
||||
— it's only used for dedup and for the \`Instructions from: <Path>\` header
|
||||
injected into the prompt. URIs like \`session://user-123/AGENTS.md\` work fine.
|
||||
- **Thread safety.** All readers and mutators are safe to call concurrently
|
||||
from multiple goroutines; the underlying state is guarded by an internal
|
||||
\`RWMutex\`.
|
||||
- **Init-time options still apply.** \`Options.Skills\`, \`Options.SkillsDir\`,
|
||||
\`Options.NoSkills\`, and \`Options.NoContextFiles\` continue to control the
|
||||
startup set; the runtime API mutates from whatever state \`New()\` produced.
|
||||
See [SDK options](/sdk/options#skills--configuration).
|
||||
|
||||
## MCP prompts and resources
|
||||
|
||||
Query prompts and resources exposed by connected MCP servers:
|
||||
|
||||
\`\`\`go
|
||||
// List and expand prompts
|
||||
prompts := host.ListMCPPrompts()
|
||||
result, _ := host.GetMCPPrompt(ctx, "server", "prompt-name", map[string]string{"key": "value"})
|
||||
|
||||
// List and read resources
|
||||
resources := host.ListMCPResources()
|
||||
content, _ := host.ReadMCPResource(ctx, "server", "file:///path")
|
||||
\`\`\`
|
||||
|
||||
## MCP tasks (long-running tools)
|
||||
|
||||
Kit advertises [MCP task support](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks)
|
||||
during \`initialize\`, so cooperating servers can return a \`taskId\` immediately
|
||||
and let Kit poll \`tasks/get\` / \`tasks/result\` until the operation completes.
|
||||
This avoids HTTP/SSE proxy timeouts on long tools and gives you clean
|
||||
cancellation via context.
|
||||
|
||||
\`\`\`go
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
MCPTaskMode: map[string]kit.MCPTaskMode{
|
||||
"build-server": kit.MCPTaskModeAlways,
|
||||
},
|
||||
MCPTaskProgress: func(p kit.MCPTaskProgress) {
|
||||
log.Printf("%s: %s", p.TaskID, p.Status)
|
||||
},
|
||||
})
|
||||
|
||||
// Inspect / cancel in-flight tasks
|
||||
tasks, _ := host.ListMCPTasks(ctx, "build-server")
|
||||
_, _ = host.CancelMCPTask(ctx, "build-server", tasks[0].TaskID)
|
||||
\`\`\`
|
||||
|
||||
Defaults to \`MCPTaskModeAuto\` per server, so any existing MCP server keeps
|
||||
its previous synchronous behaviour. See [SDK options → MCP Tasks](/sdk/options#mcp-tasks)
|
||||
for the full surface.
|
||||
|
||||
## Context and compaction
|
||||
|
||||
Monitor and manage context usage:
|
||||
|
||||
\`\`\`go
|
||||
tokens := host.EstimateContextTokens()
|
||||
stats := host.GetContextStats()
|
||||
|
||||
if host.ShouldCompact() {
|
||||
result, err := host.Compact(ctx, nil, "")
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## In-process subagents
|
||||
|
||||
Spawn child Kit instances without subprocess overhead:
|
||||
|
||||
\`\`\`go
|
||||
result, err := host.Subagent(ctx, kit.SubagentConfig{
|
||||
Prompt: "Analyze the test files",
|
||||
Model: "anthropic/claude-haiku-3-5-20241022",
|
||||
NoSession: true,
|
||||
Timeout: 2 * time.Minute,
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
See [Options](/sdk/options), [Callbacks](/sdk/callbacks), and [Sessions](/sdk/sessions) for more details.
|
||||
`};export{s as default};
|
||||
@@ -0,0 +1,406 @@
|
||||
const s={frontmatter:{title:"Providers",description:"Supported LLM providers and model configuration.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="providers"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#providers"><span class="icon icon-link"></span></a>Providers</h1>
|
||||
<p>Kit supports a wide range of LLM providers through a unified <code>provider/model</code> string format.</p>
|
||||
<h2 id="supported-providers"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#supported-providers"><span class="icon icon-link"></span></a>Supported providers</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Provider</th>
|
||||
<th>Prefix</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Anthropic</strong></td>
|
||||
<td><code>anthropic/</code></td>
|
||||
<td>Claude models (native, prompt caching, OAuth)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>OpenAI</strong></td>
|
||||
<td><code>openai/</code></td>
|
||||
<td>GPT models</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>GitHub Copilot</strong></td>
|
||||
<td><code>copilot/</code></td>
|
||||
<td>Copilot models through GitHub device login (experimental)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Google</strong></td>
|
||||
<td><code>google/</code> or <code>gemini/</code></td>
|
||||
<td>Gemini models</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Ollama</strong></td>
|
||||
<td><code>ollama/</code></td>
|
||||
<td>Local models</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Azure OpenAI</strong></td>
|
||||
<td><code>azure/</code></td>
|
||||
<td>Azure-hosted OpenAI</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>AWS Bedrock</strong></td>
|
||||
<td><code>bedrock/</code></td>
|
||||
<td>Bedrock models</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Google Vertex</strong></td>
|
||||
<td><code>google-vertex-anthropic/</code></td>
|
||||
<td>Claude on Vertex AI</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>OpenRouter</strong></td>
|
||||
<td><code>openrouter/</code></td>
|
||||
<td>Multi-provider router</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Vercel AI</strong></td>
|
||||
<td><code>vercel/</code></td>
|
||||
<td>Vercel AI SDK models</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Custom</strong></td>
|
||||
<td><code>custom/</code></td>
|
||||
<td>Any OpenAI-compatible endpoint</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Auto-routed</strong></td>
|
||||
<td>any</td>
|
||||
<td>Any provider from the models.dev database</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="model-string-format"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#model-string-format"><span class="icon icon-link"></span></a>Model string format</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">provider/model</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Standard format</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">anthropic/claude-sonnet-latest</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">openai/gpt-4o</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">copilot/gpt-5.5</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">ollama/llama3</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">google/gemini-2.5-flash</span></span></code></pre>
|
||||
<h2 id="model-aliases"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#model-aliases"><span class="icon icon-link"></span></a>Model aliases</h2>
|
||||
<p>Kit provides aliases for commonly used models:</p>
|
||||
<h3 id="anthropic-claude"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#anthropic-claude"><span class="icon icon-link"></span></a>Anthropic Claude</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-opus-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-opus-4-6</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-sonnet-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-sonnet-4-6</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-haiku-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-haiku-4-5</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-4-opus-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-opus-4-6</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-4-sonnet-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-sonnet-4-6</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-4-haiku-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-haiku-4-5</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-3-7-sonnet-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-3-7-sonnet-20250219</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-3-5-sonnet-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-3-5-sonnet-20241022</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-3-5-haiku-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-3-5-haiku-20241022</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">claude-3-opus-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> claude-3-opus-20240229</span></span></code></pre>
|
||||
<h3 id="openai-gpt"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#openai-gpt"><span class="icon icon-link"></span></a>OpenAI GPT</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">o1-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> o1</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">o3-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> o3</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">o4-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> o4-mini</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gpt-5-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gpt-5.4</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gpt-5-chat-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gpt-5.4</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gpt-4-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gpt-4o</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gpt-4</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gpt-4o</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gpt-3.5-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gpt-3.5-turbo</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gpt-3.5</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gpt-3.5-turbo</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">codex-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> codex-mini-latest</span></span></code></pre>
|
||||
<h3 id="google-gemini"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#google-gemini"><span class="icon icon-link"></span></a>Google Gemini</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gemini-pro-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gemini-2.5-pro</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gemini-flash-latest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gemini-2.5-flash</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gemini-flash</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gemini-2.5-flash</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">gemini-pro</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> →</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> gemini-2.5-pro</span></span></code></pre>
|
||||
<h2 id="specifying-a-model"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#specifying-a-model"><span class="icon icon-link"></span></a>Specifying a model</h2>
|
||||
<p>Via CLI flag:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --model</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> openai/gpt-4o</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -m</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ollama/llama3</span></span></code></pre>
|
||||
<p>Via config file:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">model</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">anthropic/claude-sonnet-latest</span></span></code></pre>
|
||||
<p>Via environment variable:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">export</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> KIT_MODEL</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"google/gemini-2.0-flash-exp"</span></span></code></pre>
|
||||
<h2 id="authentication"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#authentication"><span class="icon icon-link"></span></a>Authentication</h2>
|
||||
<h3 id="api-keys"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#api-keys"><span class="icon icon-link"></span></a>API keys</h3>
|
||||
<p>Set the appropriate environment variable for your provider:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">export</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ANTHROPIC_API_KEY</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"sk-..."</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">export</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> OPENAI_API_KEY</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"sk-..."</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">export</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> GOOGLE_API_KEY</span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"..."</span></span></code></pre>
|
||||
<p>Or pass it directly:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --provider-api-key</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "sk-..."</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --model</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> openai/gpt-4o</span></span></code></pre>
|
||||
<h3 id="oauth"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#oauth"><span class="icon icon-link"></span></a>OAuth</h3>
|
||||
<p>For providers that support OAuth:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> login</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> anthropic</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Anthropic OAuth</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> login</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> openai</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # ChatGPT/Codex OAuth</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> login</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> copilot</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # GitHub Copilot device login (experimental)</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> status</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Check authentication status</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> auth</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> logout</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> copilot</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Remove credentials</span></span></code></pre>
|
||||
<p>The experimental <code>copilot/</code> provider requires an active GitHub Copilot subscription
|
||||
and uses GitHub device login; no OpenAI account or OpenAI API key is required.</p>
|
||||
<h3 id="custom-provider-url"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#custom-provider-url"><span class="icon icon-link"></span></a>Custom provider URL</h3>
|
||||
<p>For self-hosted or proxy endpoints:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --provider-url</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "https://my-proxy.example.com/v1"</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --model</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> openai/gpt-4o</span></span></code></pre>
|
||||
<p>When <code>--provider-url</code> is set with an explicit <code>--model</code>, Kit routes through the
|
||||
<code>custom</code> (OpenAI-compatible) wire and strips any provider prefix from the model
|
||||
name. So <code>openai/gpt-4o</code>, <code>google/gemma-4-12b</code>, and bare <code>gpt-4o</code> all resolve
|
||||
to the same endpoint — Kit treats <code>--provider-url</code> as authoritative about <em>where</em>
|
||||
to send the request, and the model string as just the upstream model id.</p>
|
||||
<p>This avoids name collisions when a local server (LM Studio, Ollama, vLLM, ...)
|
||||
happens to expose a model whose name matches a known cloud provider.</p>
|
||||
<p>When <code>--provider-url</code> is provided without <code>--model</code>, Kit automatically defaults to <code>custom/custom</code>:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --provider-url</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "http://localhost:8080/v1"</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Hello"</span></span></code></pre>
|
||||
<p>The <code>custom/custom</code> model has zero cost, 262K context window, and supports reasoning. It routes through the <code>openaicompat</code> provider and accepts any OpenAI-compatible API endpoint.</p>
|
||||
<p>Optionally set <code>CUSTOM_API_KEY</code> environment variable or use <code>--provider-api-key</code> for endpoints requiring authentication.</p>
|
||||
<h2 id="auto-routed-providers"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#auto-routed-providers"><span class="icon icon-link"></span></a>Auto-routed providers</h2>
|
||||
<p>Any provider in the <a href="https://models.dev">models.dev</a> database can be used with the
|
||||
standard <code>provider/model</code> format, even without a dedicated native integration. Kit
|
||||
auto-routes the request through the matching <strong>wire protocol</strong> — the actual API
|
||||
shape the provider speaks — rather than requiring a per-provider code path:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Wire protocol</th>
|
||||
<th>npm package (models.dev)</th>
|
||||
<th>Transport used</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>OpenAI (Responses API)</td>
|
||||
<td><code>@ai-sdk/openai</code></td>
|
||||
<td>OpenAI</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OpenAI (chat completions)</td>
|
||||
<td><code>@ai-sdk/openai-compatible</code></td>
|
||||
<td>OpenAI-compatible</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Anthropic</td>
|
||||
<td><code>@ai-sdk/anthropic</code></td>
|
||||
<td>Anthropic</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Google Gemini</td>
|
||||
<td><code>@ai-sdk/google</code></td>
|
||||
<td>Google</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The provider's <code>api</code> URL from the database is used as the base URL. A provider
|
||||
whose npm package isn't recognized but that has an <code>api</code> URL falls back to the
|
||||
OpenAI-compatible wire.</p>
|
||||
<p>Because routing follows the wire protocol, aggregator/proxy providers work across
|
||||
<strong>all</strong> of their models — including ones they re-flavor onto a different protocol
|
||||
via a per-model override. For example, an aggregator that proxies Claude, GPT,
|
||||
<em>and</em> Gemini routes them to the Anthropic, OpenAI, and Google transports
|
||||
respectively:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --model</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> opencode/claude-haiku-4-5</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Hello"</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # → Anthropic wire</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --model</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> opencode/gpt-5</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Hello"</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # → OpenAI wire</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --model</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> opencode/gemini-3.5-flash</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Hello"</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # → Google wire</span></span></code></pre>
|
||||
<p>Provide the provider's API key the same way as any other — via its environment
|
||||
variable (e.g. <code>OPENCODE_API_KEY</code>) or <code>--provider-api-key</code>.</p>
|
||||
<h2 id="model-database"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#model-database"><span class="icon icon-link"></span></a>Model database</h2>
|
||||
<p>Kit ships with a local model database that maps provider names to API configurations. You can manage it with:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> models</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # List available models</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> models</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> openai</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Filter by provider</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> models</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --all</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Show all providers</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> update-models</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Update from models.dev</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> update-models</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> embedded</span><span style="color:#6A737D;--shiki-dark:#6A737D"> # Reset to bundled database</span></span></code></pre>`,headings:[{depth:2,text:"Supported providers",id:"supported-providers"},{depth:2,text:"Model string format",id:"model-string-format"},{depth:2,text:"Model aliases",id:"model-aliases"},{depth:3,text:"Anthropic Claude",id:"anthropic-claude"},{depth:3,text:"OpenAI GPT",id:"openai-gpt"},{depth:3,text:"Google Gemini",id:"google-gemini"},{depth:2,text:"Specifying a model",id:"specifying-a-model"},{depth:2,text:"Authentication",id:"authentication"},{depth:3,text:"API keys",id:"api-keys"},{depth:3,text:"OAuth",id:"oauth"},{depth:3,text:"Custom provider URL",id:"custom-provider-url"},{depth:2,text:"Auto-routed providers",id:"auto-routed-providers"},{depth:2,text:"Model database",id:"model-database"}],raw:`
|
||||
# Providers
|
||||
|
||||
Kit supports a wide range of LLM providers through a unified \`provider/model\` string format.
|
||||
|
||||
## Supported providers
|
||||
|
||||
| Provider | Prefix | Description |
|
||||
|----------|--------|-------------|
|
||||
| **Anthropic** | \`anthropic/\` | Claude models (native, prompt caching, OAuth) |
|
||||
| **OpenAI** | \`openai/\` | GPT models |
|
||||
| **GitHub Copilot** | \`copilot/\` | Copilot models through GitHub device login (experimental) |
|
||||
| **Google** | \`google/\` or \`gemini/\` | Gemini models |
|
||||
| **Ollama** | \`ollama/\` | Local models |
|
||||
| **Azure OpenAI** | \`azure/\` | Azure-hosted OpenAI |
|
||||
| **AWS Bedrock** | \`bedrock/\` | Bedrock models |
|
||||
| **Google Vertex** | \`google-vertex-anthropic/\` | Claude on Vertex AI |
|
||||
| **OpenRouter** | \`openrouter/\` | Multi-provider router |
|
||||
| **Vercel AI** | \`vercel/\` | Vercel AI SDK models |
|
||||
| **Custom** | \`custom/\` | Any OpenAI-compatible endpoint |
|
||||
| **Auto-routed** | any | Any provider from the models.dev database |
|
||||
|
||||
## Model string format
|
||||
|
||||
\`\`\`bash
|
||||
provider/model # Standard format
|
||||
anthropic/claude-sonnet-latest
|
||||
openai/gpt-4o
|
||||
copilot/gpt-5.5
|
||||
ollama/llama3
|
||||
google/gemini-2.5-flash
|
||||
\`\`\`
|
||||
|
||||
## Model aliases
|
||||
|
||||
Kit provides aliases for commonly used models:
|
||||
|
||||
### Anthropic Claude
|
||||
|
||||
\`\`\`bash
|
||||
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
|
||||
|
||||
\`\`\`bash
|
||||
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
|
||||
|
||||
\`\`\`bash
|
||||
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
|
||||
\`\`\`
|
||||
|
||||
## Specifying a model
|
||||
|
||||
Via CLI flag:
|
||||
|
||||
\`\`\`bash
|
||||
kit --model openai/gpt-4o
|
||||
kit -m ollama/llama3
|
||||
\`\`\`
|
||||
|
||||
Via config file:
|
||||
|
||||
\`\`\`yaml
|
||||
model: anthropic/claude-sonnet-latest
|
||||
\`\`\`
|
||||
|
||||
Via environment variable:
|
||||
|
||||
\`\`\`bash
|
||||
export KIT_MODEL="google/gemini-2.0-flash-exp"
|
||||
\`\`\`
|
||||
|
||||
## Authentication
|
||||
|
||||
### API keys
|
||||
|
||||
Set the appropriate environment variable for your provider:
|
||||
|
||||
\`\`\`bash
|
||||
export ANTHROPIC_API_KEY="sk-..."
|
||||
export OPENAI_API_KEY="sk-..."
|
||||
export GOOGLE_API_KEY="..."
|
||||
\`\`\`
|
||||
|
||||
Or pass it directly:
|
||||
|
||||
\`\`\`bash
|
||||
kit --provider-api-key "sk-..." --model openai/gpt-4o
|
||||
\`\`\`
|
||||
|
||||
### OAuth
|
||||
|
||||
For providers that support OAuth:
|
||||
|
||||
\`\`\`bash
|
||||
kit auth login anthropic # Anthropic OAuth
|
||||
kit auth login openai # ChatGPT/Codex OAuth
|
||||
kit auth login copilot # GitHub Copilot device login (experimental)
|
||||
kit auth status # Check authentication status
|
||||
kit auth logout copilot # Remove credentials
|
||||
\`\`\`
|
||||
|
||||
The experimental \`copilot/\` provider requires an active GitHub Copilot subscription
|
||||
and uses GitHub device login; no OpenAI account or OpenAI API key is required.
|
||||
|
||||
### Custom provider URL
|
||||
|
||||
For self-hosted or proxy endpoints:
|
||||
|
||||
\`\`\`bash
|
||||
kit --provider-url "https://my-proxy.example.com/v1" --model openai/gpt-4o
|
||||
\`\`\`
|
||||
|
||||
When \`--provider-url\` is set with an explicit \`--model\`, Kit routes through the
|
||||
\`custom\` (OpenAI-compatible) wire and strips any provider prefix from the model
|
||||
name. So \`openai/gpt-4o\`, \`google/gemma-4-12b\`, and bare \`gpt-4o\` all resolve
|
||||
to the same endpoint — Kit treats \`--provider-url\` as authoritative about *where*
|
||||
to send the request, and the model string as just the upstream model id.
|
||||
|
||||
This avoids name collisions when a local server (LM Studio, Ollama, vLLM, ...)
|
||||
happens to expose a model whose name matches a known cloud provider.
|
||||
|
||||
When \`--provider-url\` is provided without \`--model\`, Kit automatically defaults to \`custom/custom\`:
|
||||
|
||||
\`\`\`bash
|
||||
kit --provider-url "http://localhost:8080/v1" "Hello"
|
||||
\`\`\`
|
||||
|
||||
The \`custom/custom\` model has zero cost, 262K context window, and supports reasoning. It routes through the \`openaicompat\` provider and accepts any OpenAI-compatible API endpoint.
|
||||
|
||||
Optionally set \`CUSTOM_API_KEY\` environment variable or use \`--provider-api-key\` for endpoints requiring authentication.
|
||||
|
||||
## Auto-routed providers
|
||||
|
||||
Any provider in the [models.dev](https://models.dev) database can be used with the
|
||||
standard \`provider/model\` format, even without a dedicated native integration. Kit
|
||||
auto-routes the request through the matching **wire protocol** — the actual API
|
||||
shape the provider speaks — rather than requiring a per-provider code path:
|
||||
|
||||
| Wire protocol | npm package (models.dev) | Transport used |
|
||||
|---------------|--------------------------|----------------|
|
||||
| OpenAI (Responses API) | \`@ai-sdk/openai\` | OpenAI |
|
||||
| OpenAI (chat completions) | \`@ai-sdk/openai-compatible\` | OpenAI-compatible |
|
||||
| Anthropic | \`@ai-sdk/anthropic\` | Anthropic |
|
||||
| Google Gemini | \`@ai-sdk/google\` | Google |
|
||||
|
||||
The provider's \`api\` URL from the database is used as the base URL. A provider
|
||||
whose npm package isn't recognized but that has an \`api\` URL falls back to the
|
||||
OpenAI-compatible wire.
|
||||
|
||||
Because routing follows the wire protocol, aggregator/proxy providers work across
|
||||
**all** of their models — including ones they re-flavor onto a different protocol
|
||||
via a per-model override. For example, an aggregator that proxies Claude, GPT,
|
||||
*and* Gemini routes them to the Anthropic, OpenAI, and Google transports
|
||||
respectively:
|
||||
|
||||
\`\`\`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
|
||||
\`\`\`
|
||||
|
||||
Provide the provider's API key the same way as any other — via its environment
|
||||
variable (e.g. \`OPENCODE_API_KEY\`) or \`--provider-api-key\`.
|
||||
|
||||
## Model database
|
||||
|
||||
Kit ships with a local model database that maps provider names to API configurations. You can manage it with:
|
||||
|
||||
\`\`\`bash
|
||||
kit models # List available models
|
||||
kit models openai # Filter by provider
|
||||
kit models --all # Show all providers
|
||||
kit update-models # Update from models.dev
|
||||
kit update-models embedded # Reset to bundled database
|
||||
\`\`\`
|
||||
`};export{s as default};
|
||||
@@ -0,0 +1,125 @@
|
||||
const s={frontmatter:{title:"Quick Start",description:"Get up and running with Kit in minutes.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="quick-start"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#quick-start"><span class="icon icon-link"></span></a>Quick Start</h1>
|
||||
<h2 id="basic-usage"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#basic-usage"><span class="icon icon-link"></span></a>Basic usage</h2>
|
||||
<p>Start an interactive session:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span></span></code></pre>
|
||||
<p>Run a one-off prompt:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "List files in src/"</span></span></code></pre>
|
||||
<p>Attach files as context using the <code>@</code> prefix:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> @main.go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> @test.go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Review these files"</span></span></code></pre>
|
||||
<p>Binary files (images, audio, PDFs) are automatically detected via MIME type and sent as multimodal attachments. You can also reference MCP resources:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> @mcp:myserver:file:///data/report.csv</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Summarize this data"</span></span></code></pre>
|
||||
<p>Use a specific model:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --model</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> anthropic/claude-sonnet-latest</span></span></code></pre>
|
||||
<h2 id="non-interactive-mode"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#non-interactive-mode"><span class="icon icon-link"></span></a>Non-interactive mode</h2>
|
||||
<p>Kit can run as a non-interactive tool for scripting and automation.</p>
|
||||
<p>Get JSON output:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Explain main.go"</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --json</span></span></code></pre>
|
||||
<p>Quiet mode (final response only, no TUI):</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Run tests"</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --quiet</span></span></code></pre>
|
||||
<p>Ephemeral mode (no session file created):</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Quick question"</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-session</span></span></code></pre>
|
||||
<h2 id="resuming-sessions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#resuming-sessions"><span class="icon icon-link"></span></a>Resuming sessions</h2>
|
||||
<p>Continue the most recent session for the current directory:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --continue</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># or</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -c</span></span></code></pre>
|
||||
<p>Pick from previous sessions interactively:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --resume</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># or</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -r</span></span></code></pre>
|
||||
<h2 id="acp-server-mode"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#acp-server-mode"><span class="icon icon-link"></span></a>ACP server mode</h2>
|
||||
<p>Kit can run as an <a href="https://agentclientprotocol.com">ACP (Agent Client Protocol)</a> agent server, enabling ACP-compatible clients (such as <a href="https://github.com/sst/opencode">OpenCode</a>) to drive Kit as a remote coding agent over stdio:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Start Kit as an ACP server (JSON-RPC 2.0 on stdin/stdout)</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> acp</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># With debug logging to stderr</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> acp</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --debug</span></span></code></pre>
|
||||
<p>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.</p>`,headings:[{depth:2,text:"Basic usage",id:"basic-usage"},{depth:2,text:"Non-interactive mode",id:"non-interactive-mode"},{depth:2,text:"Resuming sessions",id:"resuming-sessions"},{depth:2,text:"ACP server mode",id:"acp-server-mode"}],raw:`
|
||||
# Quick Start
|
||||
|
||||
## Basic usage
|
||||
|
||||
Start an interactive session:
|
||||
|
||||
\`\`\`bash
|
||||
kit
|
||||
\`\`\`
|
||||
|
||||
Run a one-off prompt:
|
||||
|
||||
\`\`\`bash
|
||||
kit "List files in src/"
|
||||
\`\`\`
|
||||
|
||||
Attach files as context using the \`@\` prefix:
|
||||
|
||||
\`\`\`bash
|
||||
kit @main.go @test.go "Review these files"
|
||||
\`\`\`
|
||||
|
||||
Binary files (images, audio, PDFs) are automatically detected via MIME type and sent as multimodal attachments. You can also reference MCP resources:
|
||||
|
||||
\`\`\`bash
|
||||
kit @mcp:myserver:file:///data/report.csv "Summarize this data"
|
||||
\`\`\`
|
||||
|
||||
Use a specific model:
|
||||
|
||||
\`\`\`bash
|
||||
kit --model anthropic/claude-sonnet-latest
|
||||
\`\`\`
|
||||
|
||||
## Non-interactive mode
|
||||
|
||||
Kit can run as a non-interactive tool for scripting and automation.
|
||||
|
||||
Get JSON output:
|
||||
|
||||
\`\`\`bash
|
||||
kit "Explain main.go" --json
|
||||
\`\`\`
|
||||
|
||||
Quiet mode (final response only, no TUI):
|
||||
|
||||
\`\`\`bash
|
||||
kit "Run tests" --quiet
|
||||
\`\`\`
|
||||
|
||||
Ephemeral mode (no session file created):
|
||||
|
||||
\`\`\`bash
|
||||
kit "Quick question" --no-session
|
||||
\`\`\`
|
||||
|
||||
## Resuming sessions
|
||||
|
||||
Continue the most recent session for the current directory:
|
||||
|
||||
\`\`\`bash
|
||||
kit --continue
|
||||
# or
|
||||
kit -c
|
||||
\`\`\`
|
||||
|
||||
Pick from previous sessions interactively:
|
||||
|
||||
\`\`\`bash
|
||||
kit --resume
|
||||
# or
|
||||
kit -r
|
||||
\`\`\`
|
||||
|
||||
## 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 (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.
|
||||
`};export{s as default};
|
||||
@@ -0,0 +1,223 @@
|
||||
const e={frontmatter:{title:"Session Management",description:"How Kit persists and manages conversation sessions.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="session-management"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#session-management"><span class="icon icon-link"></span></a>Session Management</h1>
|
||||
<p>Kit uses a tree-based session model that supports branching and forking conversations.</p>
|
||||
<h2 id="session-storage"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#session-storage"><span class="icon icon-link"></span></a>Session storage</h2>
|
||||
<p>Sessions are stored as JSONL (JSON Lines) files:</p>
|
||||
<pre><code>~/.kit/sessions/<cwd-path>/<timestamp>_<id>.jsonl
|
||||
</code></pre>
|
||||
<p>Path separators in the working directory are replaced with <code>--</code>. For example, <code>/home/user/project</code> becomes <code>home--user--project</code>.</p>
|
||||
<p>Each line in the session file is a JSON entry representing a message, tool call, model change, or extension data. The tree structure allows branching from any message to explore alternate paths.</p>
|
||||
<h2 id="compaction"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#compaction"><span class="icon icon-link"></span></a>Compaction</h2>
|
||||
<p>When conversations grow long, Kit can compact them to free up context window space. The compaction system:</p>
|
||||
<ul>
|
||||
<li><strong>Non-destructive</strong>: Old messages remain on disk for history; only the LLM context is summarized</li>
|
||||
<li><strong>File tracking</strong>: Tracks which files were read and modified across compactions</li>
|
||||
<li><strong>Split-turn handling</strong>: Can summarize large single turns by splitting them</li>
|
||||
<li><strong>Tool result truncation</strong>: Caps tool output during serialization to stay within token budgets</li>
|
||||
</ul>
|
||||
<p>Use <code>/compact [focus]</code> to manually compact, or enable <code>--auto-compact</code> to compact automatically near the context limit.</p>
|
||||
<h2 id="auto-cleanup"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#auto-cleanup"><span class="icon icon-link"></span></a>Auto-cleanup</h2>
|
||||
<p>Kit automatically cleans up empty sessions on shutdown and when using <code>/resume</code>. A session is considered empty if it has no messages beyond the initial system prompt. This prevents cluttering your sessions directory with unused files.</p>
|
||||
<p>To start fresh without creating a session file at all, use ephemeral mode:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-session</span></span></code></pre>
|
||||
<h2 id="resuming-sessions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#resuming-sessions"><span class="icon icon-link"></span></a>Resuming sessions</h2>
|
||||
<h3 id="continue-most-recent"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#continue-most-recent"><span class="icon icon-link"></span></a>Continue most recent</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --continue</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -c</span></span></code></pre>
|
||||
<h3 id="interactive-picker"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#interactive-picker"><span class="icon icon-link"></span></a>Interactive picker</h3>
|
||||
<p>Choose from previous sessions interactively:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --resume</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -r</span></span></code></pre>
|
||||
<p>The session picker supports search, scope/filter toggles (all sessions vs. current directory), and session deletion. You can also open it during a session with the <code>/resume</code> slash command.</p>
|
||||
<h3 id="open-a-specific-session"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#open-a-specific-session"><span class="icon icon-link"></span></a>Open a specific session</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --session</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> path/to/session.jsonl</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> path/to/session.jsonl</span></span></code></pre>
|
||||
<h2 id="session-commands"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#session-commands"><span class="icon icon-link"></span></a>Session commands</h2>
|
||||
<p>These slash commands are available during an interactive session:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>/name [name]</code></td>
|
||||
<td>Set or display the session's display name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/session</code></td>
|
||||
<td>Show session info (path, ID, message count)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/resume</code></td>
|
||||
<td>Open the session picker to switch sessions</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/export [path]</code></td>
|
||||
<td>Export session as JSONL (auto-generates path if omitted)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/import <path></code></td>
|
||||
<td>Import and switch to a session from a JSONL file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/share</code></td>
|
||||
<td>Upload session to GitHub Gist and get a shareable viewer URL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/tree</code></td>
|
||||
<td>Navigate the session tree</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/fork</code></td>
|
||||
<td>Fork to new session from an earlier message (creates new session file)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>/new</code></td>
|
||||
<td>Start a new session (creates new session file)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="ephemeral-mode"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#ephemeral-mode"><span class="icon icon-link"></span></a>Ephemeral mode</h2>
|
||||
<p>Run without creating a session file:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-session</span></span></code></pre>
|
||||
<p>This is useful for one-off prompts, scripting, and subagent patterns where persistence isn't needed.</p>
|
||||
<h2 id="sharing-sessions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#sharing-sessions"><span class="icon icon-link"></span></a>Sharing sessions</h2>
|
||||
<p>The <code>/share</code> command uploads your session JSONL to GitHub Gist (via the <code>gh</code> CLI) and prints a shareable viewer URL:</p>
|
||||
<pre><code>/share
|
||||
</code></pre>
|
||||
<p>The shared session includes:</p>
|
||||
<ul>
|
||||
<li>The <strong>system prompt</strong> that was active during the conversation</li>
|
||||
<li>The <strong>model</strong> used (e.g., <code>anthropic/claude-sonnet-4-5</code>)</li>
|
||||
</ul>
|
||||
<p>The viewer displays this information in a collapsible "System Prompt" section at the top of the session, with the model shown as a badge in the header.</p>
|
||||
<p>The viewer is available at <code>https://go-kit.dev/session/#GIST_ID</code> and supports all message types including text, reasoning blocks, tool calls, images, and model changes.</p>
|
||||
<p>You can also load any JSONL session via URL parameter: <code>https://go-kit.dev/session/?url=https://example.com/session.jsonl</code></p>
|
||||
<h2 id="preferences-persistence"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#preferences-persistence"><span class="icon icon-link"></span></a>Preferences persistence</h2>
|
||||
<p>Kit automatically saves your preferences across sessions to <code>~/.config/kit/preferences.yml</code>:</p>
|
||||
<ul>
|
||||
<li><strong>Theme</strong> — Set via <code>/theme <name></code></li>
|
||||
<li><strong>Model</strong> — Set via <code>/model <name></code> or the model selector</li>
|
||||
<li><strong>Thinking level</strong> — Set via <code>/thinking <level></code> or Shift+Tab cycling</li>
|
||||
</ul>
|
||||
<p>These preferences are restored on next launch. Precedence: CLI flag > config file > saved preference > default.</p>`,headings:[{depth:2,text:"Session storage",id:"session-storage"},{depth:2,text:"Compaction",id:"compaction"},{depth:2,text:"Auto-cleanup",id:"auto-cleanup"},{depth:2,text:"Resuming sessions",id:"resuming-sessions"},{depth:3,text:"Continue most recent",id:"continue-most-recent"},{depth:3,text:"Interactive picker",id:"interactive-picker"},{depth:3,text:"Open a specific session",id:"open-a-specific-session"},{depth:2,text:"Session commands",id:"session-commands"},{depth:2,text:"Ephemeral mode",id:"ephemeral-mode"},{depth:2,text:"Sharing sessions",id:"sharing-sessions"},{depth:2,text:"Preferences persistence",id:"preferences-persistence"}],raw:`
|
||||
# Session Management
|
||||
|
||||
Kit uses a tree-based session model that supports branching and forking conversations.
|
||||
|
||||
## Session storage
|
||||
|
||||
Sessions are stored as JSONL (JSON Lines) files:
|
||||
|
||||
\`\`\`
|
||||
~/.kit/sessions/<cwd-path>/<timestamp>_<id>.jsonl
|
||||
\`\`\`
|
||||
|
||||
Path separators in the working directory are replaced with \`--\`. For example, \`/home/user/project\` becomes \`home--user--project\`.
|
||||
|
||||
Each line in the session file is a JSON entry representing a message, tool call, model change, or extension data. The tree structure allows branching from any message to explore alternate paths.
|
||||
|
||||
## Compaction
|
||||
|
||||
When conversations grow long, Kit can compact them to free up context window space. The compaction system:
|
||||
|
||||
- **Non-destructive**: Old messages remain on disk for history; only the LLM context is summarized
|
||||
- **File tracking**: Tracks which files were read and modified across compactions
|
||||
- **Split-turn handling**: Can summarize large single turns by splitting them
|
||||
- **Tool result truncation**: Caps tool output during serialization to stay within token budgets
|
||||
|
||||
Use \`/compact [focus]\` to manually compact, or enable \`--auto-compact\` to compact automatically near the context limit.
|
||||
|
||||
## Auto-cleanup
|
||||
|
||||
Kit automatically cleans up empty sessions on shutdown and when using \`/resume\`. A session is considered empty if it has no messages beyond the initial system prompt. This prevents cluttering your sessions directory with unused files.
|
||||
|
||||
To start fresh without creating a session file at all, use ephemeral mode:
|
||||
|
||||
\`\`\`bash
|
||||
kit --no-session
|
||||
\`\`\`
|
||||
|
||||
## Resuming sessions
|
||||
|
||||
### Continue most recent
|
||||
|
||||
\`\`\`bash
|
||||
kit --continue
|
||||
kit -c
|
||||
\`\`\`
|
||||
|
||||
### Interactive picker
|
||||
|
||||
Choose from previous sessions interactively:
|
||||
|
||||
\`\`\`bash
|
||||
kit --resume
|
||||
kit -r
|
||||
\`\`\`
|
||||
|
||||
The session picker supports search, scope/filter toggles (all sessions vs. current directory), and session deletion. You can also open it during a session with the \`/resume\` slash command.
|
||||
|
||||
### Open a specific session
|
||||
|
||||
\`\`\`bash
|
||||
kit --session path/to/session.jsonl
|
||||
kit -s path/to/session.jsonl
|
||||
\`\`\`
|
||||
|
||||
## Session commands
|
||||
|
||||
These slash commands are available during an interactive session:
|
||||
|
||||
| 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 (creates new session file) |
|
||||
| \`/new\` | Start a new session (creates new session file) |
|
||||
|
||||
## Ephemeral mode
|
||||
|
||||
Run without creating a session file:
|
||||
|
||||
\`\`\`bash
|
||||
kit --no-session
|
||||
\`\`\`
|
||||
|
||||
This is useful for one-off prompts, scripting, and subagent patterns where persistence isn't needed.
|
||||
|
||||
## Sharing sessions
|
||||
|
||||
The \`/share\` command uploads your session JSONL to GitHub Gist (via the \`gh\` CLI) and prints a shareable viewer URL:
|
||||
|
||||
\`\`\`
|
||||
/share
|
||||
\`\`\`
|
||||
|
||||
The shared session includes:
|
||||
- The **system prompt** that was active during the conversation
|
||||
- The **model** used (e.g., \`anthropic/claude-sonnet-4-5\`)
|
||||
|
||||
The viewer displays this information in a collapsible "System Prompt" section at the top of the session, with the model shown as a badge in the header.
|
||||
|
||||
The viewer is available at \`https://go-kit.dev/session/#GIST_ID\` and supports all message types including text, reasoning blocks, tool calls, images, and model changes.
|
||||
|
||||
You can also load any JSONL session via URL parameter: \`https://go-kit.dev/session/?url=https://example.com/session.jsonl\`
|
||||
|
||||
## Preferences persistence
|
||||
|
||||
Kit automatically saves your preferences across sessions to \`~/.config/kit/preferences.yml\`:
|
||||
|
||||
- **Theme** — Set via \`/theme <name>\`
|
||||
- **Model** — Set via \`/model <name>\` or the model selector
|
||||
- **Thinking level** — Set via \`/thinking <level>\` or Shift+Tab cycling
|
||||
|
||||
These preferences are restored on next launch. Precedence: CLI flag > config file > saved preference > default.
|
||||
`};export{e as default};
|
||||
@@ -0,0 +1,163 @@
|
||||
const s={frontmatter:{title:"SDK Sessions",description:"Session management in the Kit Go SDK.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="sdk-sessions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#sdk-sessions"><span class="icon icon-link"></span></a>SDK Sessions</h1>
|
||||
<h2 id="automatic-persistence"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#automatic-persistence"><span class="icon icon-link"></span></a>Automatic persistence</h2>
|
||||
<p>By default, Kit automatically persists sessions to JSONL files. Multi-turn conversations retain context across calls:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Prompt</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"My name is Alice"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">response, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Prompt</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"What's my name?"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// response: "Your name is Alice"</span></span></code></pre>
|
||||
<h2 id="accessing-session-info"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#accessing-session-info"><span class="icon icon-link"></span></a>Accessing session info</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Get the current session file path</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">path </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetSessionPath</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Get the session ID</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">id </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetSessionID</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Get the current model string</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">model </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetModelString</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span></code></pre>
|
||||
<h2 id="configuring-sessions-via-options"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#configuring-sessions-via-options"><span class="icon icon-link"></span></a>Configuring sessions via Options</h2>
|
||||
<p>Session behavior is configured at initialization:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Open a specific session file</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Options</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> SessionPath: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"./my-session.jsonl"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Resume the most recent session for the current directory</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Options</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Continue: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">true</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Ephemeral mode (no file persistence)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Options</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> NoSession: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">true</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Custom session directory</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Options</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> SessionDir: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"/custom/sessions/"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
|
||||
<h2 id="clearing-history"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#clearing-history"><span class="icon icon-link"></span></a>Clearing history</h2>
|
||||
<p>Clear the in-memory conversation history (does not delete the session file):</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ClearSession</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span></code></pre>
|
||||
<h2 id="tree-based-sessions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#tree-based-sessions"><span class="icon icon-link"></span></a>Tree-based sessions</h2>
|
||||
<p>Kit's session model is tree-based, supporting branching. You can branch from any entry to explore alternate conversation paths:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Access the tree session manager</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">ts </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetTreeSession</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Branch from a specific entry</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Branch</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"entry-id-123"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
|
||||
<h2 id="listing-and-managing-sessions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#listing-and-managing-sessions"><span class="icon icon-link"></span></a>Listing and managing sessions</h2>
|
||||
<p>Package-level functions for session discovery:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// List sessions for a specific directory</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">sessions </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ListSessions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"/home/user/project"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// List all sessions across all directories</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">all </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ListAllSessions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Delete a session file</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">DeleteSession</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"/path/to/session.jsonl"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
|
||||
<h2 id="custom-session-manager"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#custom-session-manager"><span class="icon icon-link"></span></a>Custom session manager</h2>
|
||||
<p>For advanced use cases (databases, cloud storage, multi-user apps), implement the <code>SessionManager</code> interface to replace the default JSONL file backend:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> kit.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#D73A49;--shiki-dark:#F97583">&</span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Options</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> SessionManager: myCustomSession,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
|
||||
<p>The interface requires methods for message storage, branching, compaction, extension data, and lifecycle management. See the <a href="https://github.com/mark3labs/kit">SDK skill reference</a> for the complete interface definition.</p>
|
||||
<p>When using a custom <code>SessionManager</code>, the <code>SessionPath</code>, <code>Continue</code>, and <code>NoSession</code> options are ignored — your manager handles its own storage and session selection.</p>`,headings:[{depth:2,text:"Automatic persistence",id:"automatic-persistence"},{depth:2,text:"Accessing session info",id:"accessing-session-info"},{depth:2,text:"Configuring sessions via Options",id:"configuring-sessions-via-options"},{depth:2,text:"Clearing history",id:"clearing-history"},{depth:2,text:"Tree-based sessions",id:"tree-based-sessions"},{depth:2,text:"Listing and managing sessions",id:"listing-and-managing-sessions"},{depth:2,text:"Custom session manager",id:"custom-session-manager"}],raw:`
|
||||
# SDK Sessions
|
||||
|
||||
## Automatic persistence
|
||||
|
||||
By default, Kit automatically persists sessions to JSONL files. Multi-turn conversations retain context across calls:
|
||||
|
||||
\`\`\`go
|
||||
host.Prompt(ctx, "My name is Alice")
|
||||
response, _ := host.Prompt(ctx, "What's my name?")
|
||||
// response: "Your name is Alice"
|
||||
\`\`\`
|
||||
|
||||
## Accessing session info
|
||||
|
||||
\`\`\`go
|
||||
// Get the current session file path
|
||||
path := host.GetSessionPath()
|
||||
|
||||
// Get the session ID
|
||||
id := host.GetSessionID()
|
||||
|
||||
// Get the current model string
|
||||
model := host.GetModelString()
|
||||
\`\`\`
|
||||
|
||||
## Configuring sessions via Options
|
||||
|
||||
Session behavior is configured at initialization:
|
||||
|
||||
\`\`\`go
|
||||
// Open a specific session file
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
SessionPath: "./my-session.jsonl",
|
||||
})
|
||||
|
||||
// Resume the most recent session for the current directory
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
Continue: true,
|
||||
})
|
||||
|
||||
// Ephemeral mode (no file persistence)
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
NoSession: true,
|
||||
})
|
||||
|
||||
// Custom session directory
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
SessionDir: "/custom/sessions/",
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
## Clearing history
|
||||
|
||||
Clear the in-memory conversation history (does not delete the session file):
|
||||
|
||||
\`\`\`go
|
||||
host.ClearSession()
|
||||
\`\`\`
|
||||
|
||||
## Tree-based sessions
|
||||
|
||||
Kit's session model is tree-based, supporting branching. You can branch from any entry to explore alternate conversation paths:
|
||||
|
||||
\`\`\`go
|
||||
// Access the tree session manager
|
||||
ts := host.GetTreeSession()
|
||||
|
||||
// Branch from a specific entry
|
||||
err := host.Branch("entry-id-123")
|
||||
\`\`\`
|
||||
|
||||
## Listing and managing sessions
|
||||
|
||||
Package-level functions for session discovery:
|
||||
|
||||
\`\`\`go
|
||||
// List sessions for a specific directory
|
||||
sessions := kit.ListSessions("/home/user/project")
|
||||
|
||||
// List all sessions across all directories
|
||||
all := kit.ListAllSessions()
|
||||
|
||||
// Delete a session file
|
||||
kit.DeleteSession("/path/to/session.jsonl")
|
||||
\`\`\`
|
||||
|
||||
## Custom session manager
|
||||
|
||||
For advanced use cases (databases, cloud storage, multi-user apps), implement the \`SessionManager\` interface to replace the default JSONL file backend:
|
||||
|
||||
\`\`\`go
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
SessionManager: myCustomSession,
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
The interface requires methods for message storage, branching, compaction, extension data, and lifecycle management. See the [SDK skill reference](https://github.com/mark3labs/kit) for the complete interface definition.
|
||||
|
||||
When using a custom \`SessionManager\`, the \`SessionPath\`, \`Continue\`, and \`NoSession\` options are ignored — your manager handles its own storage and session selection.
|
||||
`};export{s as default};
|
||||
@@ -0,0 +1,315 @@
|
||||
const s={frontmatter:{title:"Subagents",description:"Multi-agent orchestration with Kit subagents.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="subagents"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#subagents"><span class="icon icon-link"></span></a>Subagents</h1>
|
||||
<p>Kit supports multi-agent orchestration through both subprocess spawning and in-process subagents.</p>
|
||||
<h2 id="subprocess-pattern"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#subprocess-pattern"><span class="icon icon-link"></span></a>Subprocess pattern</h2>
|
||||
<p>Spawn Kit as a subprocess for isolated agent execution:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Analyze codebase"</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> \\</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> --json</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> \\</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-session</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> \\</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> --no-extensions</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> \\</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> --quiet</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> \\</span></span>
|
||||
<span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF"> --model</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> anthropic/claude-haiku-latest</span></span></code></pre>
|
||||
<p>Key flags for subprocess usage:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Flag</th>
|
||||
<th>Purpose</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>--quiet</code></td>
|
||||
<td>Stdout only, no TUI</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--no-session</code></td>
|
||||
<td>Ephemeral, no persistence</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--no-extensions</code></td>
|
||||
<td>Prevent recursive extension loading</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--json</code></td>
|
||||
<td>Machine-readable output</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--system-prompt</code></td>
|
||||
<td>Custom system prompt (string or file path)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Positional arguments are the prompt. <code>@file</code> arguments attach file content as context.</p>
|
||||
<h2 id="built-in-subagent-tool"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#built-in-subagent-tool"><span class="icon icon-link"></span></a>Built-in subagent tool</h2>
|
||||
<p>Kit includes a built-in <code>subagent</code> tool that the LLM can use to delegate tasks to independent child agents:</p>
|
||||
<pre><code>subagent(
|
||||
task: "Analyze the test files and summarize coverage",
|
||||
model: "anthropic/claude-haiku-latest", // optional
|
||||
system_prompt: "You are a test analysis expert.", // optional
|
||||
timeout_seconds: 300 // optional, max 1800
|
||||
)
|
||||
</code></pre>
|
||||
<p>Subagents run as separate in-process Kit instances with full tool access (except spawning further subagents, to prevent infinite recursion). They can run in parallel.</p>
|
||||
<h2 id="extension-subagents"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#extension-subagents"><span class="icon icon-link"></span></a>Extension subagents</h2>
|
||||
<p>Extensions can spawn subagents programmatically:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">result </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SpawnSubagent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SubagentConfig</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Task: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Review this code for security issues"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Model: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"anthropic/claude-sonnet-latest"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> SystemPrompt: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"You are a security auditor."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
|
||||
<h3 id="monitoring-subagents-from-extensions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#monitoring-subagents-from-extensions"><span class="icon icon-link"></span></a>Monitoring subagents from extensions</h3>
|
||||
<p>When the LLM (not the extension itself) spawns a subagent using the <code>subagent</code> tool, extensions can monitor its activity in real-time using three lifecycle event handlers:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Track active subagents and display their output</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">var</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> subagentWidgets </span><span style="color:#D73A49;--shiki-dark:#F97583">map</span><span style="color:#24292E;--shiki-dark:#E1E4E8">[</span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#24292E;--shiki-dark:#E1E4E8">]</span><span style="color:#D73A49;--shiki-dark:#F97583">*</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SubagentWidget</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> Init</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">api</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">API</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Subagent started by the main agent</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> api.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnSubagentStart</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">e</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SubagentStartEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#E36209;--shiki-dark:#FFAB70">ctx</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // e.ToolCallID — unique ID for this subagent invocation</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // e.Task — the task/prompt sent to the subagent</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> NewWidget</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(e.ToolCallID, e.Task)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> subagentWidgets[e.ToolCallID] </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetWidget</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(widget.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Config</span><span style="color:#24292E;--shiki-dark:#E1E4E8">())</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Real-time streaming from subagent</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> api.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnSubagentChunk</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">e</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SubagentChunkEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#E36209;--shiki-dark:#FFAB70">ctx</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // e.ToolCallID — matches the start event</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // e.ChunkType — "text", "tool_call", "tool_execution_start", "tool_result"</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // e.Content — text content</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // e.ToolName — tool name (for tool chunks)</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // e.IsError — true if tool result failed</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> subagentWidgets[e.ToolCallID]</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget </span><span style="color:#D73A49;--shiki-dark:#F97583">!=</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AddOutput</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(e)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetWidget</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(widget.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Config</span><span style="color:#24292E;--shiki-dark:#E1E4E8">())</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Subagent completed</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> api.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnSubagentEnd</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">e</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SubagentEndEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#E36209;--shiki-dark:#FFAB70">ctx</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // e.Response — final response from subagent</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // e.ErrorMsg — error message if subagent failed</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> subagentWidgets[e.ToolCallID]</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget </span><span style="color:#D73A49;--shiki-dark:#F97583">!=</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">MarkComplete</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(e.Response, e.ErrorMsg)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetWidget</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(widget.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Config</span><span style="color:#24292E;--shiki-dark:#E1E4E8">())</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0"> delete</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(subagentWidgets, e.ToolCallID)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<p><strong>Event structs:</strong></p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">type</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> SubagentStartEvent</span><span style="color:#D73A49;--shiki-dark:#F97583"> struct</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ToolCallID </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // Unique ID for this subagent invocation</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Task </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // The task/prompt sent to subagent</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">type</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> SubagentChunkEvent</span><span style="color:#D73A49;--shiki-dark:#F97583"> struct</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ToolCallID </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // Matches SubagentStartEvent.ToolCallID</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Task </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // Task description</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ChunkType </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // "text", "tool_call", "tool_execution_start", "tool_result"</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Content </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // For text chunks</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ToolName </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // For tool-related chunks</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> IsError </span><span style="color:#D73A49;--shiki-dark:#F97583">bool</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // For tool_result chunks</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">type</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> SubagentEndEvent</span><span style="color:#D73A49;--shiki-dark:#F97583"> struct</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ToolCallID </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // Matches start event</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Task </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // Task description</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Response </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // Final response from subagent</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ErrorMsg </span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#6A737D;--shiki-dark:#6A737D"> // Error message if failed</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<p>This enables building monitoring widgets that display real-time activity from all subagents spawned by the main agent.</p>
|
||||
<h2 id="go-sdk-subagents"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#go-sdk-subagents"><span class="icon icon-link"></span></a>Go SDK subagents</h2>
|
||||
<p>The SDK provides in-process subagent spawning:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">result, err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Subagent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ctx, </span><span style="color:#6F42C1;--shiki-dark:#B392F0">kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SubagentConfig</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Task: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Summarize the changes in this PR"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Model: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"anthropic/claude-haiku-latest"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> SystemPrompt: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"You are a code reviewer."</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Timeout: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">5</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> time.Minute,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
|
||||
<h3 id="real-time-subagent-events"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#real-time-subagent-events"><span class="icon icon-link"></span></a>Real-time subagent events</h3>
|
||||
<p>Use <code>SubscribeSubagent</code> to receive real-time events from LLM-initiated subagents (i.e., when the model uses the <code>subagent</code> tool). Register inside an <code>OnToolCall</code> handler using the tool call ID:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnToolCall</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">e</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolCallEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> e.ToolName </span><span style="color:#D73A49;--shiki-dark:#F97583">==</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "subagent"</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> host.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SubscribeSubagent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(e.ToolCallID, </span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">event</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Event</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> switch</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ev </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> event.(</span><span style="color:#D73A49;--shiki-dark:#F97583">type</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> case</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">MessageUpdateEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Print</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(ev.Chunk) </span><span style="color:#6A737D;--shiki-dark:#6A737D">// streaming text from child</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> case</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolCallEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Printf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Child calling: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s\\n</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, ev.ToolName)</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> case</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> kit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolResultEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> fmt.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Printf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Child result: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s\\n</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, ev.ToolName)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
|
||||
<p>The listener receives the same event types as <code>Subscribe()</code> (<code>ToolCallEvent</code>, <code>MessageUpdateEvent</code>, <code>ReasoningDeltaEvent</code>, etc.) but scoped to the child agent's activity. Listeners are cleaned up automatically when the subagent completes.</p>
|
||||
<p>If no listeners are registered for a tool call, no event dispatching overhead is incurred.</p>`,headings:[{depth:2,text:"Subprocess pattern",id:"subprocess-pattern"},{depth:2,text:"Built-in subagent tool",id:"built-in-subagent-tool"},{depth:2,text:"Extension subagents",id:"extension-subagents"},{depth:3,text:"Monitoring subagents from extensions",id:"monitoring-subagents-from-extensions"},{depth:2,text:"Go SDK subagents",id:"go-sdk-subagents"},{depth:3,text:"Real-time subagent events",id:"real-time-subagent-events"}],raw:`
|
||||
# Subagents
|
||||
|
||||
Kit supports multi-agent orchestration through both subprocess spawning and in-process subagents.
|
||||
|
||||
## Subprocess pattern
|
||||
|
||||
Spawn Kit as a subprocess for isolated agent execution:
|
||||
|
||||
\`\`\`bash
|
||||
kit "Analyze codebase" \\
|
||||
--json \\
|
||||
--no-session \\
|
||||
--no-extensions \\
|
||||
--quiet \\
|
||||
--model anthropic/claude-haiku-latest
|
||||
\`\`\`
|
||||
|
||||
Key flags for subprocess usage:
|
||||
|
||||
| Flag | Purpose |
|
||||
|------|---------|
|
||||
| \`--quiet\` | Stdout only, no TUI |
|
||||
| \`--no-session\` | Ephemeral, no persistence |
|
||||
| \`--no-extensions\` | Prevent recursive extension loading |
|
||||
| \`--json\` | Machine-readable output |
|
||||
| \`--system-prompt\` | Custom system prompt (string or file path) |
|
||||
|
||||
Positional arguments are the prompt. \`@file\` arguments attach file content as context.
|
||||
|
||||
## Built-in subagent tool
|
||||
|
||||
Kit includes a built-in \`subagent\` tool that the LLM can use to delegate tasks to independent child agents:
|
||||
|
||||
\`\`\`
|
||||
subagent(
|
||||
task: "Analyze the test files and summarize coverage",
|
||||
model: "anthropic/claude-haiku-latest", // optional
|
||||
system_prompt: "You are a test analysis expert.", // optional
|
||||
timeout_seconds: 300 // optional, max 1800
|
||||
)
|
||||
\`\`\`
|
||||
|
||||
Subagents run as separate in-process Kit instances with full tool access (except spawning further subagents, to prevent infinite recursion). They can run in parallel.
|
||||
|
||||
## Extension subagents
|
||||
|
||||
Extensions can spawn subagents programmatically:
|
||||
|
||||
\`\`\`go
|
||||
result := ctx.SpawnSubagent(ext.SubagentConfig{
|
||||
Task: "Review this code for security issues",
|
||||
Model: "anthropic/claude-sonnet-latest",
|
||||
SystemPrompt: "You are a security auditor.",
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
### Monitoring subagents from extensions
|
||||
|
||||
When the LLM (not the extension itself) spawns a subagent using the \`subagent\` tool, extensions can monitor its activity in real-time using three lifecycle event handlers:
|
||||
|
||||
\`\`\`go
|
||||
// Track active subagents and display their output
|
||||
var subagentWidgets map[string]*SubagentWidget
|
||||
|
||||
func Init(api ext.API) {
|
||||
// Subagent started by the main agent
|
||||
api.OnSubagentStart(func(e ext.SubagentStartEvent, ctx ext.Context) {
|
||||
// e.ToolCallID — unique ID for this subagent invocation
|
||||
// e.Task — the task/prompt sent to the subagent
|
||||
widget := NewWidget(e.ToolCallID, e.Task)
|
||||
subagentWidgets[e.ToolCallID] = widget
|
||||
ctx.SetWidget(widget.Config())
|
||||
})
|
||||
|
||||
// Real-time streaming from subagent
|
||||
api.OnSubagentChunk(func(e ext.SubagentChunkEvent, ctx ext.Context) {
|
||||
// e.ToolCallID — matches the start event
|
||||
// e.ChunkType — "text", "tool_call", "tool_execution_start", "tool_result"
|
||||
// e.Content — text content
|
||||
// e.ToolName — tool name (for tool chunks)
|
||||
// e.IsError — true if tool result failed
|
||||
widget := subagentWidgets[e.ToolCallID]
|
||||
if widget != nil {
|
||||
widget.AddOutput(e)
|
||||
ctx.SetWidget(widget.Config())
|
||||
}
|
||||
})
|
||||
|
||||
// Subagent completed
|
||||
api.OnSubagentEnd(func(e ext.SubagentEndEvent, ctx ext.Context) {
|
||||
// e.Response — final response from subagent
|
||||
// e.ErrorMsg — error message if subagent failed
|
||||
widget := subagentWidgets[e.ToolCallID]
|
||||
if widget != nil {
|
||||
widget.MarkComplete(e.Response, e.ErrorMsg)
|
||||
ctx.SetWidget(widget.Config())
|
||||
delete(subagentWidgets, e.ToolCallID)
|
||||
}
|
||||
})
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**Event structs:**
|
||||
|
||||
\`\`\`go
|
||||
type SubagentStartEvent struct {
|
||||
ToolCallID string // Unique ID for this subagent invocation
|
||||
Task string // The task/prompt sent to subagent
|
||||
}
|
||||
|
||||
type SubagentChunkEvent struct {
|
||||
ToolCallID string // Matches SubagentStartEvent.ToolCallID
|
||||
Task string // Task description
|
||||
ChunkType string // "text", "tool_call", "tool_execution_start", "tool_result"
|
||||
Content string // For text chunks
|
||||
ToolName string // For tool-related chunks
|
||||
IsError bool // For tool_result chunks
|
||||
}
|
||||
|
||||
type SubagentEndEvent struct {
|
||||
ToolCallID string // Matches start event
|
||||
Task string // Task description
|
||||
Response string // Final response from subagent
|
||||
ErrorMsg string // Error message if failed
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
This enables building monitoring widgets that display real-time activity from all subagents spawned by the main agent.
|
||||
|
||||
## Go SDK subagents
|
||||
|
||||
The SDK provides in-process subagent spawning:
|
||||
|
||||
\`\`\`go
|
||||
result, err := host.Subagent(ctx, kit.SubagentConfig{
|
||||
Task: "Summarize the changes in this PR",
|
||||
Model: "anthropic/claude-haiku-latest",
|
||||
SystemPrompt: "You are a code reviewer.",
|
||||
Timeout: 5 * time.Minute,
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
### Real-time subagent events
|
||||
|
||||
Use \`SubscribeSubagent\` to receive real-time events from LLM-initiated subagents (i.e., when the model uses the \`subagent\` tool). Register inside an \`OnToolCall\` handler using the tool call ID:
|
||||
|
||||
\`\`\`go
|
||||
host.OnToolCall(func(e kit.ToolCallEvent) {
|
||||
if e.ToolName == "subagent" {
|
||||
host.SubscribeSubagent(e.ToolCallID, func(event kit.Event) {
|
||||
switch ev := event.(type) {
|
||||
case kit.MessageUpdateEvent:
|
||||
fmt.Print(ev.Chunk) // streaming text from child
|
||||
case kit.ToolCallEvent:
|
||||
fmt.Printf("Child calling: %s\\n", ev.ToolName)
|
||||
case kit.ToolResultEvent:
|
||||
fmt.Printf("Child result: %s\\n", ev.ToolName)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
The listener receives the same event types as \`Subscribe()\` (\`ToolCallEvent\`, \`MessageUpdateEvent\`, \`ReasoningDeltaEvent\`, etc.) but scoped to the child agent's activity. Listeners are cleaned up automatically when the subagent completes.
|
||||
|
||||
If no listeners are registered for a tool call, no event dispatching overhead is incurred.
|
||||
`};export{s as default};
|
||||
@@ -0,0 +1,882 @@
|
||||
const s={frontmatter:{title:"Testing Extensions",description:"Write unit tests for your Kit extensions using the test package.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="testing-extensions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-extensions"><span class="icon icon-link"></span></a>Testing Extensions</h1>
|
||||
<p>Kit provides a testing package (<code>github.com/mark3labs/kit/pkg/extensions/test</code>) that enables you to write unit tests for your extensions. Tests run outside the Yaegi interpreter but load your extension code into an isolated interpreter instance, allowing you to verify behavior without running the full Kit TUI.</p>
|
||||
<h2 id="overview"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#overview"><span class="icon icon-link"></span></a>Overview</h2>
|
||||
<p>Extension tests allow you to:</p>
|
||||
<ul>
|
||||
<li>Test event handlers without running the interactive TUI</li>
|
||||
<li>Verify tool/command registration</li>
|
||||
<li>Assert that context methods (Print, SetWidget, etc.) are called correctly</li>
|
||||
<li>Test blocking and non-blocking event handling</li>
|
||||
<li>Simulate user input and tool calls</li>
|
||||
<li>Verify widget, header, footer, and status bar updates</li>
|
||||
</ul>
|
||||
<h2 id="installation"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#installation"><span class="icon icon-link"></span></a>Installation</h2>
|
||||
<p>The test package is part of the Kit codebase. Import it in your extension tests:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">import</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">github.com/mark3labs/kit/pkg/extensions/test</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">github.com/mark3labs/kit/internal/extensions</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
|
||||
<h2 id="basic-usage"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#basic-usage"><span class="icon icon-link"></span></a>Basic Usage</h2>
|
||||
<h3 id="testing-an-extension-file"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-an-extension-file"><span class="icon icon-link"></span></a>Testing an Extension File</h3>
|
||||
<p>Create a test file alongside your extension (e.g., <code>my-ext_test.go</code>):</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">package</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> main</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">import</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> (</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">github.com/mark3labs/kit/pkg/extensions/test</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "</span><span style="color:#6F42C1;--shiki-dark:#B392F0">github.com/mark3labs/kit/internal/extensions</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestMyExtension</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Create a test harness</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Load your extension</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Emit events and check results</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> result, err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolCallEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ToolName: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my_tool"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Input: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">\`{"key": "value"}\`</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> err </span><span style="color:#D73A49;--shiki-dark:#F97583">!=</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> t.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Fatalf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"unexpected error: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%v</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, err)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Use assertion helpers</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertNotBlocked</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, result)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertPrinted</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"expected output"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-inline-extension-code"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-inline-extension-code"><span class="icon icon-link"></span></a>Testing Inline Extension Code</h3>
|
||||
<p>For quick tests or edge cases, you can load extension source directly:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestToolBlocking</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> src </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> \`package main</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF">import "kit/ext"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF">func Init(api ext.API) {</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> api.OnToolCall(func(tc ext.ToolCallEvent, ctx ext.Context) *ext.ToolCallResult {</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> if tc.ToolName == "dangerous" {</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> return &ext.ToolCallResult{Block: true, Reason: "not allowed"}</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> }</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> return nil</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> })</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF">}</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF">\`</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadString</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(src, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"test-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Test the tool is blocked</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> result, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolCallEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ToolName: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"dangerous"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Input: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"{}"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertBlocked</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, result, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"not allowed"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h2 id="common-testing-patterns"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#common-testing-patterns"><span class="icon icon-link"></span></a>Common Testing Patterns</h2>
|
||||
<h3 id="testing-handler-registration"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-handler-registration"><span class="icon icon-link"></span></a>Testing Handler Registration</h3>
|
||||
<p>Verify your extension registers the expected handlers:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestHandlers</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertHasHandlers</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, extensions.ToolCall)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertHasHandlers</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, extensions.SessionStart)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertNoHandlers</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, extensions.AgentEnd) </span><span style="color:#6A737D;--shiki-dark:#6A737D">// Verify no unexpected handlers</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-tool-registration"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-tool-registration"><span class="icon icon-link"></span></a>Testing Tool Registration</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestTools</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Verify a specific tool is registered</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertToolRegistered</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my_tool"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Or inspect all tools</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> tools </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">RegisteredTools</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> for</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, tool </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#D73A49;--shiki-dark:#F97583"> range</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> tools {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> t.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Logf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Tool: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> - </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, tool.Name, tool.Description)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-commands"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-commands"><span class="icon icon-link"></span></a>Testing Commands</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestCommands</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertCommandRegistered</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"mycommand"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-widgets"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-widgets"><span class="icon icon-link"></span></a>Testing Widgets</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestWidgets</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Trigger event that creates the widget</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SessionStartEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{SessionID: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"test"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Verify widget was set</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertWidgetSet</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-widget"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertWidgetText</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-widget"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Expected Text"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertWidgetTextContains</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-widget"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"partial"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Check widget properties directly</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget, ok </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">().</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetWidget</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-widget"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ok {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> t.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Logf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Border color: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, widget.Style.BorderColor)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-input-handling"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-input-handling"><span class="icon icon-link"></span></a>Testing Input Handling</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestInput</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> result, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">InputEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Text: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"!mycommand"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Source: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"cli"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertInputHandled</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, result, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"handled"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-headers-and-footers"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-headers-and-footers"><span class="icon icon-link"></span></a>Testing Headers and Footers</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestHeaderFooter</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SessionStartEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{SessionID: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"test"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertHeaderSet</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertFooterSet</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Inspect content</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> header </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">().</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetHeader</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> header </span><span style="color:#D73A49;--shiki-dark:#F97583">!=</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> t.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Logf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Header text: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, header.Content.Text)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-status-bar"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-status-bar"><span class="icon icon-link"></span></a>Testing Status Bar</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestStatus</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AgentEndEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertStatusSet</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"myext:status"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertStatusText</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"myext:status"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Ready"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-print-output"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-print-output"><span class="icon icon-link"></span></a>Testing Print Output</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestOutput</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolCallEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{ToolName: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"test"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Exact match</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertPrinted</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"exact output"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Partial match</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertPrintedContains</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"partial"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Styled output</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertPrintInfo</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"info message"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertPrintError</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"error message"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-with-prompts"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-with-prompts"><span class="icon icon-link"></span></a>Testing with Prompts</h3>
|
||||
<p>Configure mock prompt results for testing interactive behavior:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestWithPrompts</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Configure what prompts should return</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">().</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetPromptSelectResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">PromptSelectResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Value: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"option1"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Index: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">0</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Cancelled: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">false</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">().</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetPromptConfirmResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">PromptConfirmResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Value: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">true</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Cancelled: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">false</span><span style="color:#24292E;--shiki-dark:#E1E4E8">,</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Now when your extension calls ctx.PromptSelect(), it gets this result</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SessionStartEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{SessionID: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"test"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h3 id="testing-complete-session-flow"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-complete-session-flow"><span class="icon icon-link"></span></a>Testing Complete Session Flow</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> TestFullSession</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">t</span><span style="color:#D73A49;--shiki-dark:#F97583"> *</span><span style="color:#6F42C1;--shiki-dark:#B392F0">testing</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">T</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-ext.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Simulate a complete session</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SessionStartEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{SessionID: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"test"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">BeforeAgentStartEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AgentStartEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Multiple tool calls</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> tools </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> []</span><span style="color:#D73A49;--shiki-dark:#F97583">string</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Read"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Grep"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Bash"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583"> for</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, tool </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#D73A49;--shiki-dark:#F97583"> range</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> tools {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolCallEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{ToolName: tool})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolResultEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{ToolName: tool})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> }</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AgentEndEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> _, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SessionShutdownEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> </span></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"> // Verify final state</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">AssertWidgetTextContains</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t, harness, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"status"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Complete"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
|
||||
<h2 id="available-assertions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#available-assertions"><span class="icon icon-link"></span></a>Available Assertions</h2>
|
||||
<p>The test package provides these assertion helpers:</p>
|
||||
<h3 id="event-results"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#event-results"><span class="icon icon-link"></span></a>Event Results</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>AssertNotBlocked(t, result)</code></td>
|
||||
<td>Verify tool was not blocked</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertBlocked(t, result, reason)</code></td>
|
||||
<td>Verify tool was blocked with reason</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertInputHandled(t, result, action)</code></td>
|
||||
<td>Verify input was handled</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertInputTransformed(t, result, text)</code></td>
|
||||
<td>Verify input was transformed</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="context-interactions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#context-interactions"><span class="icon icon-link"></span></a>Context Interactions</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>AssertPrinted(t, harness, text)</code></td>
|
||||
<td>Verify exact print output</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertPrintedContains(t, harness, substring)</code></td>
|
||||
<td>Verify partial print output</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertPrintInfo(t, harness, text)</code></td>
|
||||
<td>Verify PrintInfo was called</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertPrintError(t, harness, text)</code></td>
|
||||
<td>Verify PrintError was called</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertWidgetSet(t, harness, id)</code></td>
|
||||
<td>Verify widget was set</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertWidgetNotSet(t, harness, id)</code></td>
|
||||
<td>Verify widget was not set</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertWidgetText(t, harness, id, text)</code></td>
|
||||
<td>Verify widget content</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertWidgetTextContains(t, harness, id, substring)</code></td>
|
||||
<td>Verify widget contains text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertHeaderSet(t, harness)</code></td>
|
||||
<td>Verify header was set</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertFooterSet(t, harness)</code></td>
|
||||
<td>Verify footer was set</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertStatusSet(t, harness, key)</code></td>
|
||||
<td>Verify status was set</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertStatusText(t, harness, key, text)</code></td>
|
||||
<td>Verify status text</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="registration"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#registration"><span class="icon icon-link"></span></a>Registration</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>AssertToolRegistered(t, harness, name)</code></td>
|
||||
<td>Verify tool registration</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertCommandRegistered(t, harness, name)</code></td>
|
||||
<td>Verify command registration</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertHasHandlers(t, harness, eventType)</code></td>
|
||||
<td>Verify handlers exist</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertNoHandlers(t, harness, eventType)</code></td>
|
||||
<td>Verify no handlers</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="messaging"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#messaging"><span class="icon icon-link"></span></a>Messaging</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>AssertMessageSent(t, harness, text)</code></td>
|
||||
<td>Verify SendMessage was called</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>AssertCancelAndSend(t, harness, text)</code></td>
|
||||
<td>Verify CancelAndSend was called</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="helper-functions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#helper-functions"><span class="icon icon-link"></span></a>Helper Functions</h2>
|
||||
<p>For custom assertions, extract result details:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">result, _ </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Emit</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#6F42C1;--shiki-dark:#B392F0">extensions</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ToolCallEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span><span style="color:#D73A49;--shiki-dark:#F97583">...</span><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">tcr </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetToolCallResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(result)</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> tcr </span><span style="color:#D73A49;--shiki-dark:#F97583">!=</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> t.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Logf</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Block: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%v</span><span style="color:#032F62;--shiki-dark:#9ECBFF">, Reason: </span><span style="color:#005CC5;--shiki-dark:#79B8FF">%s</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, tcr.Block, tcr.Reason)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">ir </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetInputResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(result)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">trr </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetToolResultResult</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(result)</span></span></code></pre>
|
||||
<h2 id="advanced-usage"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#advanced-usage"><span class="icon icon-link"></span></a>Advanced Usage</h2>
|
||||
<h3 id="accessing-the-mock-context"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#accessing-the-mock-context"><span class="icon icon-link"></span></a>Accessing the Mock Context</h3>
|
||||
<p>For custom verification:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">ctx </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> harness.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Get all recorded prints</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">prints </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetPrints</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Check options</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">value </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetOption</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-option"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Verify widget properties</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">widget, ok </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetWidget</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"my-widget"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#D73A49;--shiki-dark:#F97583">if</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ok </span><span style="color:#D73A49;--shiki-dark:#F97583">&&</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> widget.Style.BorderColor </span><span style="color:#D73A49;--shiki-dark:#F97583">==</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "#ff0000"</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> t.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Log</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"Widget has red border"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">}</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Check status entries</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">status, ok </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">GetStatus</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"myext:status"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
|
||||
<h3 id="testing-multiple-extensions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-multiple-extensions"><span class="icon icon-link"></span></a>Testing Multiple Extensions</h3>
|
||||
<p>Each harness is isolated:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">harness1 </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">harness1.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"ext1.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">harness2 </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> test.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">New</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(t)</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">harness2.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">LoadFile</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"ext2.go"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D">// Events to one don't affect the other</span></span></code></pre>
|
||||
<h3 id="running-tests"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#running-tests"><span class="icon icon-link"></span></a>Running Tests</h3>
|
||||
<p>Run all tests in your extension directory:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#005CC5;--shiki-dark:#79B8FF">cd</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> examples/extensions</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> test</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -v</span></span></code></pre>
|
||||
<p>Run with race detector:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> test</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -race</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -v</span></span></code></pre>
|
||||
<p>Run a specific test:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> test</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -v</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -run</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> TestMyExtension</span></span></code></pre>
|
||||
<h2 id="best-practices"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#best-practices"><span class="icon icon-link"></span></a>Best Practices</h2>
|
||||
<ol>
|
||||
<li><strong>Test one behavior per test</strong> — Keep tests focused and readable</li>
|
||||
<li><strong>Use inline source for edge cases</strong> — <code>LoadString()</code> is great for testing specific scenarios</li>
|
||||
<li><strong>Use <code>LoadFile()</code> for integration tests</strong> — Tests the actual extension file</li>
|
||||
<li><strong>Assert on context calls</strong> — Verify your extension interacts with the context correctly</li>
|
||||
<li><strong>Test both positive and negative cases</strong> — Verify tools are blocked AND allowed appropriately</li>
|
||||
<li><strong>Test all event handlers</strong> — Make sure all registered handlers work correctly</li>
|
||||
<li><strong>Use descriptive test names</strong> — <code>TestExtension_BlocksDangerousTools</code> is clearer than <code>Test1</code></li>
|
||||
</ol>
|
||||
<h2 id="limitations"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#limitations"><span class="icon icon-link"></span></a>Limitations</h2>
|
||||
<p>The test harness has these intentional limitations:</p>
|
||||
<ul>
|
||||
<li><strong>No TUI rendering</strong> — Widgets are recorded but not rendered visually</li>
|
||||
<li><strong>Prompts return configured values</strong> — Pre-configure prompt results in tests</li>
|
||||
<li><strong>Subagents don't spawn real processes</strong> — <code>SpawnSubagent()</code> returns nil/empty results</li>
|
||||
<li><strong>LLM completions are mocked</strong> — <code>Complete()</code> returns empty responses</li>
|
||||
<li><strong>Some context methods are no-ops</strong> — <code>Exit()</code>, <code>SetActiveTools()</code>, etc. don't have side effects</li>
|
||||
</ul>
|
||||
<p>These limitations focus testing on extension logic rather than the full Kit runtime.</p>
|
||||
<h2 id="complete-example"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#complete-example"><span class="icon icon-link"></span></a>Complete Example</h2>
|
||||
<p>See <code>examples/extensions/tool-logger_test.go</code> for a complete example with 14 tests covering:</p>
|
||||
<ul>
|
||||
<li>Handler registration</li>
|
||||
<li>Tool call and result handling</li>
|
||||
<li>Session lifecycle events</li>
|
||||
<li>Input commands (<code>!time</code>, <code>!status</code>)</li>
|
||||
<li>Unknown command handling</li>
|
||||
<li>Concurrent operations (race condition check)</li>
|
||||
<li>Real file logging verification</li>
|
||||
</ul>`,headings:[{depth:2,text:"Overview",id:"overview"},{depth:2,text:"Installation",id:"installation"},{depth:2,text:"Basic Usage",id:"basic-usage"},{depth:3,text:"Testing an Extension File",id:"testing-an-extension-file"},{depth:3,text:"Testing Inline Extension Code",id:"testing-inline-extension-code"},{depth:2,text:"Common Testing Patterns",id:"common-testing-patterns"},{depth:3,text:"Testing Handler Registration",id:"testing-handler-registration"},{depth:3,text:"Testing Tool Registration",id:"testing-tool-registration"},{depth:3,text:"Testing Commands",id:"testing-commands"},{depth:3,text:"Testing Widgets",id:"testing-widgets"},{depth:3,text:"Testing Input Handling",id:"testing-input-handling"},{depth:3,text:"Testing Headers and Footers",id:"testing-headers-and-footers"},{depth:3,text:"Testing Status Bar",id:"testing-status-bar"},{depth:3,text:"Testing Print Output",id:"testing-print-output"},{depth:3,text:"Testing with Prompts",id:"testing-with-prompts"},{depth:3,text:"Testing Complete Session Flow",id:"testing-complete-session-flow"},{depth:2,text:"Available Assertions",id:"available-assertions"},{depth:3,text:"Event Results",id:"event-results"},{depth:3,text:"Context Interactions",id:"context-interactions"},{depth:3,text:"Registration",id:"registration"},{depth:3,text:"Messaging",id:"messaging"},{depth:2,text:"Helper Functions",id:"helper-functions"},{depth:2,text:"Advanced Usage",id:"advanced-usage"},{depth:3,text:"Accessing the Mock Context",id:"accessing-the-mock-context"},{depth:3,text:"Testing Multiple Extensions",id:"testing-multiple-extensions"},{depth:3,text:"Running Tests",id:"running-tests"},{depth:2,text:"Best Practices",id:"best-practices"},{depth:2,text:"Limitations",id:"limitations"},{depth:2,text:"Complete Example",id:"complete-example"}],raw:`
|
||||
# Testing Extensions
|
||||
|
||||
Kit provides a testing package (\`github.com/mark3labs/kit/pkg/extensions/test\`) that enables you to write unit tests for your extensions. Tests run outside the Yaegi interpreter but load your extension code into an isolated interpreter instance, allowing you to verify behavior without running the full Kit TUI.
|
||||
|
||||
## Overview
|
||||
|
||||
Extension tests allow you to:
|
||||
|
||||
- Test event handlers without running the interactive TUI
|
||||
- Verify tool/command registration
|
||||
- Assert that context methods (Print, SetWidget, etc.) are called correctly
|
||||
- Test blocking and non-blocking event handling
|
||||
- Simulate user input and tool calls
|
||||
- Verify widget, header, footer, and status bar updates
|
||||
|
||||
## Installation
|
||||
|
||||
The test package is part of the Kit codebase. Import it in your extension tests:
|
||||
|
||||
\`\`\`go
|
||||
import (
|
||||
"testing"
|
||||
"github.com/mark3labs/kit/pkg/extensions/test"
|
||||
"github.com/mark3labs/kit/internal/extensions"
|
||||
)
|
||||
\`\`\`
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Testing an Extension File
|
||||
|
||||
Create a test file alongside your extension (e.g., \`my-ext_test.go\`):
|
||||
|
||||
\`\`\`go
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"github.com/mark3labs/kit/pkg/extensions/test"
|
||||
"github.com/mark3labs/kit/internal/extensions"
|
||||
)
|
||||
|
||||
func TestMyExtension(t *testing.T) {
|
||||
// Create a test harness
|
||||
harness := test.New(t)
|
||||
|
||||
// Load your extension
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
// Emit events and check results
|
||||
result, err := harness.Emit(extensions.ToolCallEvent{
|
||||
ToolName: "my_tool",
|
||||
Input: \`{"key": "value"}\`,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Use assertion helpers
|
||||
test.AssertNotBlocked(t, result)
|
||||
test.AssertPrinted(t, harness, "expected output")
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing Inline Extension Code
|
||||
|
||||
For quick tests or edge cases, you can load extension source directly:
|
||||
|
||||
\`\`\`go
|
||||
func TestToolBlocking(t *testing.T) {
|
||||
src := \`package main
|
||||
|
||||
import "kit/ext"
|
||||
|
||||
func Init(api ext.API) {
|
||||
api.OnToolCall(func(tc ext.ToolCallEvent, ctx ext.Context) *ext.ToolCallResult {
|
||||
if tc.ToolName == "dangerous" {
|
||||
return &ext.ToolCallResult{Block: true, Reason: "not allowed"}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
\`
|
||||
harness := test.New(t)
|
||||
harness.LoadString(src, "test-ext.go")
|
||||
|
||||
// Test the tool is blocked
|
||||
result, _ := harness.Emit(extensions.ToolCallEvent{
|
||||
ToolName: "dangerous",
|
||||
Input: "{}",
|
||||
})
|
||||
|
||||
test.AssertBlocked(t, result, "not allowed")
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Common Testing Patterns
|
||||
|
||||
### Testing Handler Registration
|
||||
|
||||
Verify your extension registers the expected handlers:
|
||||
|
||||
\`\`\`go
|
||||
func TestHandlers(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
test.AssertHasHandlers(t, harness, extensions.ToolCall)
|
||||
test.AssertHasHandlers(t, harness, extensions.SessionStart)
|
||||
test.AssertNoHandlers(t, harness, extensions.AgentEnd) // Verify no unexpected handlers
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing Tool Registration
|
||||
|
||||
\`\`\`go
|
||||
func TestTools(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
// Verify a specific tool is registered
|
||||
test.AssertToolRegistered(t, harness, "my_tool")
|
||||
|
||||
// Or inspect all tools
|
||||
tools := harness.RegisteredTools()
|
||||
for _, tool := range tools {
|
||||
t.Logf("Tool: %s - %s", tool.Name, tool.Description)
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing Commands
|
||||
|
||||
\`\`\`go
|
||||
func TestCommands(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
test.AssertCommandRegistered(t, harness, "mycommand")
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing Widgets
|
||||
|
||||
\`\`\`go
|
||||
func TestWidgets(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
// Trigger event that creates the widget
|
||||
_, _ = harness.Emit(extensions.SessionStartEvent{SessionID: "test"})
|
||||
|
||||
// Verify widget was set
|
||||
test.AssertWidgetSet(t, harness, "my-widget")
|
||||
test.AssertWidgetText(t, harness, "my-widget", "Expected Text")
|
||||
test.AssertWidgetTextContains(t, harness, "my-widget", "partial")
|
||||
|
||||
// Check widget properties directly
|
||||
widget, ok := harness.Context().GetWidget("my-widget")
|
||||
if ok {
|
||||
t.Logf("Border color: %s", widget.Style.BorderColor)
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing Input Handling
|
||||
|
||||
\`\`\`go
|
||||
func TestInput(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
result, _ := harness.Emit(extensions.InputEvent{
|
||||
Text: "!mycommand",
|
||||
Source: "cli",
|
||||
})
|
||||
|
||||
test.AssertInputHandled(t, result, "handled")
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing Headers and Footers
|
||||
|
||||
\`\`\`go
|
||||
func TestHeaderFooter(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
_, _ = harness.Emit(extensions.SessionStartEvent{SessionID: "test"})
|
||||
|
||||
test.AssertHeaderSet(t, harness)
|
||||
test.AssertFooterSet(t, harness)
|
||||
|
||||
// Inspect content
|
||||
header := harness.Context().GetHeader()
|
||||
if header != nil {
|
||||
t.Logf("Header text: %s", header.Content.Text)
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing Status Bar
|
||||
|
||||
\`\`\`go
|
||||
func TestStatus(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
_, _ = harness.Emit(extensions.AgentEndEvent{})
|
||||
|
||||
test.AssertStatusSet(t, harness, "myext:status")
|
||||
test.AssertStatusText(t, harness, "myext:status", "Ready")
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing Print Output
|
||||
|
||||
\`\`\`go
|
||||
func TestOutput(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
_, _ = harness.Emit(extensions.ToolCallEvent{ToolName: "test"})
|
||||
|
||||
// Exact match
|
||||
test.AssertPrinted(t, harness, "exact output")
|
||||
|
||||
// Partial match
|
||||
test.AssertPrintedContains(t, harness, "partial")
|
||||
|
||||
// Styled output
|
||||
test.AssertPrintInfo(t, harness, "info message")
|
||||
test.AssertPrintError(t, harness, "error message")
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing with Prompts
|
||||
|
||||
Configure mock prompt results for testing interactive behavior:
|
||||
|
||||
\`\`\`go
|
||||
func TestWithPrompts(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
// Configure what prompts should return
|
||||
harness.Context().SetPromptSelectResult(extensions.PromptSelectResult{
|
||||
Value: "option1",
|
||||
Index: 0,
|
||||
Cancelled: false,
|
||||
})
|
||||
|
||||
harness.Context().SetPromptConfirmResult(extensions.PromptConfirmResult{
|
||||
Value: true,
|
||||
Cancelled: false,
|
||||
})
|
||||
|
||||
// Now when your extension calls ctx.PromptSelect(), it gets this result
|
||||
_, _ = harness.Emit(extensions.SessionStartEvent{SessionID: "test"})
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Testing Complete Session Flow
|
||||
|
||||
\`\`\`go
|
||||
func TestFullSession(t *testing.T) {
|
||||
harness := test.New(t)
|
||||
harness.LoadFile("my-ext.go")
|
||||
|
||||
// Simulate a complete session
|
||||
_, _ = harness.Emit(extensions.SessionStartEvent{SessionID: "test"})
|
||||
_, _ = harness.Emit(extensions.BeforeAgentStartEvent{})
|
||||
_, _ = harness.Emit(extensions.AgentStartEvent{})
|
||||
|
||||
// Multiple tool calls
|
||||
tools := []string{"Read", "Grep", "Bash"}
|
||||
for _, tool := range tools {
|
||||
_, _ = harness.Emit(extensions.ToolCallEvent{ToolName: tool})
|
||||
_, _ = harness.Emit(extensions.ToolResultEvent{ToolName: tool})
|
||||
}
|
||||
|
||||
_, _ = harness.Emit(extensions.AgentEndEvent{})
|
||||
_, _ = harness.Emit(extensions.SessionShutdownEvent{})
|
||||
|
||||
// Verify final state
|
||||
test.AssertWidgetTextContains(t, harness, "status", "Complete")
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Available Assertions
|
||||
|
||||
The test package provides these assertion helpers:
|
||||
|
||||
### Event Results
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| \`AssertNotBlocked(t, result)\` | Verify tool was not blocked |
|
||||
| \`AssertBlocked(t, result, reason)\` | Verify tool was blocked with reason |
|
||||
| \`AssertInputHandled(t, result, action)\` | Verify input was handled |
|
||||
| \`AssertInputTransformed(t, result, text)\` | Verify input was transformed |
|
||||
|
||||
### Context Interactions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| \`AssertPrinted(t, harness, text)\` | Verify exact print output |
|
||||
| \`AssertPrintedContains(t, harness, substring)\` | Verify partial print output |
|
||||
| \`AssertPrintInfo(t, harness, text)\` | Verify PrintInfo was called |
|
||||
| \`AssertPrintError(t, harness, text)\` | Verify PrintError was called |
|
||||
| \`AssertWidgetSet(t, harness, id)\` | Verify widget was set |
|
||||
| \`AssertWidgetNotSet(t, harness, id)\` | Verify widget was not set |
|
||||
| \`AssertWidgetText(t, harness, id, text)\` | Verify widget content |
|
||||
| \`AssertWidgetTextContains(t, harness, id, substring)\` | Verify widget contains text |
|
||||
| \`AssertHeaderSet(t, harness)\` | Verify header was set |
|
||||
| \`AssertFooterSet(t, harness)\` | Verify footer was set |
|
||||
| \`AssertStatusSet(t, harness, key)\` | Verify status was set |
|
||||
| \`AssertStatusText(t, harness, key, text)\` | Verify status text |
|
||||
|
||||
### Registration
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| \`AssertToolRegistered(t, harness, name)\` | Verify tool registration |
|
||||
| \`AssertCommandRegistered(t, harness, name)\` | Verify command registration |
|
||||
| \`AssertHasHandlers(t, harness, eventType)\` | Verify handlers exist |
|
||||
| \`AssertNoHandlers(t, harness, eventType)\` | Verify no handlers |
|
||||
|
||||
### Messaging
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| \`AssertMessageSent(t, harness, text)\` | Verify SendMessage was called |
|
||||
| \`AssertCancelAndSend(t, harness, text)\` | Verify CancelAndSend was called |
|
||||
|
||||
## Helper Functions
|
||||
|
||||
For custom assertions, extract result details:
|
||||
|
||||
\`\`\`go
|
||||
result, _ := harness.Emit(extensions.ToolCallEvent{...})
|
||||
tcr := test.GetToolCallResult(result)
|
||||
if tcr != nil {
|
||||
t.Logf("Block: %v, Reason: %s", tcr.Block, tcr.Reason)
|
||||
}
|
||||
|
||||
ir := test.GetInputResult(result)
|
||||
trr := test.GetToolResultResult(result)
|
||||
\`\`\`
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Accessing the Mock Context
|
||||
|
||||
For custom verification:
|
||||
|
||||
\`\`\`go
|
||||
ctx := harness.Context()
|
||||
|
||||
// Get all recorded prints
|
||||
prints := ctx.GetPrints()
|
||||
|
||||
// Check options
|
||||
value := ctx.GetOption("my-option")
|
||||
|
||||
// Verify widget properties
|
||||
widget, ok := ctx.GetWidget("my-widget")
|
||||
if ok && widget.Style.BorderColor == "#ff0000" {
|
||||
t.Log("Widget has red border")
|
||||
}
|
||||
|
||||
// Check status entries
|
||||
status, ok := ctx.GetStatus("myext:status")
|
||||
\`\`\`
|
||||
|
||||
### Testing Multiple Extensions
|
||||
|
||||
Each harness is isolated:
|
||||
|
||||
\`\`\`go
|
||||
harness1 := test.New(t)
|
||||
harness1.LoadFile("ext1.go")
|
||||
|
||||
harness2 := test.New(t)
|
||||
harness2.LoadFile("ext2.go")
|
||||
|
||||
// Events to one don't affect the other
|
||||
\`\`\`
|
||||
|
||||
### Running Tests
|
||||
|
||||
Run all tests in your extension directory:
|
||||
|
||||
\`\`\`bash
|
||||
cd examples/extensions
|
||||
go test -v
|
||||
\`\`\`
|
||||
|
||||
Run with race detector:
|
||||
|
||||
\`\`\`bash
|
||||
go test -race -v
|
||||
\`\`\`
|
||||
|
||||
Run a specific test:
|
||||
|
||||
\`\`\`bash
|
||||
go test -v -run TestMyExtension
|
||||
\`\`\`
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Test one behavior per test** — Keep tests focused and readable
|
||||
2. **Use inline source for edge cases** — \`LoadString()\` is great for testing specific scenarios
|
||||
3. **Use \`LoadFile()\` for integration tests** — Tests the actual extension file
|
||||
4. **Assert on context calls** — Verify your extension interacts with the context correctly
|
||||
5. **Test both positive and negative cases** — Verify tools are blocked AND allowed appropriately
|
||||
6. **Test all event handlers** — Make sure all registered handlers work correctly
|
||||
7. **Use descriptive test names** — \`TestExtension_BlocksDangerousTools\` is clearer than \`Test1\`
|
||||
|
||||
## Limitations
|
||||
|
||||
The test harness has these intentional limitations:
|
||||
|
||||
- **No TUI rendering** — Widgets are recorded but not rendered visually
|
||||
- **Prompts return configured values** — Pre-configure prompt results in tests
|
||||
- **Subagents don't spawn real processes** — \`SpawnSubagent()\` returns nil/empty results
|
||||
- **LLM completions are mocked** — \`Complete()\` returns empty responses
|
||||
- **Some context methods are no-ops** — \`Exit()\`, \`SetActiveTools()\`, etc. don't have side effects
|
||||
|
||||
These limitations focus testing on extension logic rather than the full Kit runtime.
|
||||
|
||||
## Complete Example
|
||||
|
||||
See \`examples/extensions/tool-logger_test.go\` for a complete example with 14 tests covering:
|
||||
|
||||
- Handler registration
|
||||
- Tool call and result handling
|
||||
- Session lifecycle events
|
||||
- Input commands (\`!time\`, \`!status\`)
|
||||
- Unknown command handling
|
||||
- Concurrent operations (race condition check)
|
||||
- Real file logging verification
|
||||
`};export{s as default};
|
||||
@@ -0,0 +1,130 @@
|
||||
const s={frontmatter:{title:"Testing with tmux",description:"Test Kit's TUI non-interactively using tmux.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="testing-with-tmux"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-with-tmux"><span class="icon icon-link"></span></a>Testing with tmux</h1>
|
||||
<p>Kit's interactive TUI can be tested non-interactively using tmux. This is useful for automated testing, CI pipelines, and extension development.</p>
|
||||
<h2 id="basic-pattern"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#basic-pattern"><span class="icon icon-link"></span></a>Basic pattern</h2>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Start Kit in a detached tmux session</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> new-session</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -d</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -x</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> 120</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -y</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> 40</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> \\</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "output/kit -e ext.go --no-session 2>kit_stderr.log"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Wait for startup</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">sleep</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> 3</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Capture the current screen</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> capture-pane</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -p</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Send input</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> send-keys</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> '/command'</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> Enter</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Wait for response</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">sleep</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> 2</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Capture updated screen</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> capture-pane</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -p</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Cleanup</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kill-session</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span></span></code></pre>
|
||||
<h2 id="testing-extensions"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#testing-extensions"><span class="icon icon-link"></span></a>Testing extensions</h2>
|
||||
<p>When testing extensions, the pattern is:</p>
|
||||
<ol>
|
||||
<li>Build Kit with your changes</li>
|
||||
<li>Start Kit in tmux with the extension loaded</li>
|
||||
<li>Send slash commands or prompts</li>
|
||||
<li>Capture and verify the screen output</li>
|
||||
<li>Check stderr logs for errors</li>
|
||||
</ol>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Build first</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">go</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> build</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -o</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> output/kit</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> ./cmd/kit</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Start with extension</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> new-session</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -d</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -s</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -x</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> 120</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -y</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> 40</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> \\</span></span>
|
||||
<span class="line"><span style="color:#032F62;--shiki-dark:#9ECBFF"> "output/kit -e examples/extensions/widget-status.go --no-session 2>kit_stderr.log"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">sleep</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> 3</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Verify widget appears in screen</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> capture-pane</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -p</span><span style="color:#D73A49;--shiki-dark:#F97583"> |</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> grep</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> "Status"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Send a slash command</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> send-keys</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> '/stats'</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> Enter</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">sleep</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> 1</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> capture-pane</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -p</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Cleanup</span></span>
|
||||
<span class="line"><span style="color:#6F42C1;--shiki-dark:#B392F0">tmux</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kill-session</span><span style="color:#005CC5;--shiki-dark:#79B8FF"> -t</span><span style="color:#032F62;--shiki-dark:#9ECBFF"> kittest</span></span></code></pre>
|
||||
<h2 id="tips"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#tips"><span class="icon icon-link"></span></a>Tips</h2>
|
||||
<ul>
|
||||
<li>Use <code>-x</code> and <code>-y</code> to set consistent terminal dimensions</li>
|
||||
<li>Redirect stderr to a log file (<code>2>kit.log</code>) for debugging</li>
|
||||
<li>Use <code>--no-session</code> to avoid creating session files during tests</li>
|
||||
<li>Add sufficient <code>sleep</code> between commands for the TUI to render</li>
|
||||
<li>Use <code>grep</code> on captured pane output to verify specific content</li>
|
||||
</ul>`,headings:[{depth:2,text:"Basic pattern",id:"basic-pattern"},{depth:2,text:"Testing extensions",id:"testing-extensions"},{depth:2,text:"Tips",id:"tips"}],raw:`
|
||||
# Testing with tmux
|
||||
|
||||
Kit's interactive TUI can be tested non-interactively using tmux. This is useful for automated testing, CI pipelines, and extension development.
|
||||
|
||||
## Basic pattern
|
||||
|
||||
\`\`\`bash
|
||||
# Start Kit in a detached tmux session
|
||||
tmux new-session -d -s kittest -x 120 -y 40 \\
|
||||
"output/kit -e ext.go --no-session 2>kit_stderr.log"
|
||||
|
||||
# Wait for startup
|
||||
sleep 3
|
||||
|
||||
# Capture the current screen
|
||||
tmux capture-pane -t kittest -p
|
||||
|
||||
# Send input
|
||||
tmux send-keys -t kittest '/command' Enter
|
||||
|
||||
# Wait for response
|
||||
sleep 2
|
||||
|
||||
# Capture updated screen
|
||||
tmux capture-pane -t kittest -p
|
||||
|
||||
# Cleanup
|
||||
tmux kill-session -t kittest
|
||||
\`\`\`
|
||||
|
||||
## Testing extensions
|
||||
|
||||
When testing extensions, the pattern is:
|
||||
|
||||
1. Build Kit with your changes
|
||||
2. Start Kit in tmux with the extension loaded
|
||||
3. Send slash commands or prompts
|
||||
4. Capture and verify the screen output
|
||||
5. Check stderr logs for errors
|
||||
|
||||
\`\`\`bash
|
||||
# Build first
|
||||
go build -o output/kit ./cmd/kit
|
||||
|
||||
# Start with extension
|
||||
tmux new-session -d -s kittest -x 120 -y 40 \\
|
||||
"output/kit -e examples/extensions/widget-status.go --no-session 2>kit_stderr.log"
|
||||
|
||||
sleep 3
|
||||
|
||||
# Verify widget appears in screen
|
||||
tmux capture-pane -t kittest -p | grep "Status"
|
||||
|
||||
# Send a slash command
|
||||
tmux send-keys -t kittest '/stats' Enter
|
||||
sleep 1
|
||||
tmux capture-pane -t kittest -p
|
||||
|
||||
# Cleanup
|
||||
tmux kill-session -t kittest
|
||||
\`\`\`
|
||||
|
||||
## Tips
|
||||
|
||||
- Use \`-x\` and \`-y\` to set consistent terminal dimensions
|
||||
- Redirect stderr to a log file (\`2>kit.log\`) for debugging
|
||||
- Use \`--no-session\` to avoid creating session files during tests
|
||||
- Add sufficient \`sleep\` between commands for the TUI to render
|
||||
- Use \`grep\` on captured pane output to verify specific content
|
||||
`};export{s as default};
|
||||
@@ -0,0 +1 @@
|
||||
const e={};export{e as default};
|
||||
@@ -0,0 +1,685 @@
|
||||
const s={frontmatter:{title:"Themes",description:"Customize Kit's appearance with built-in themes, custom theme files, and the extension theme API.",hidden:!1,toc:!0,draft:!1},html:`<h1 id="themes"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#themes"><span class="icon icon-link"></span></a>Themes</h1>
|
||||
<p>Kit ships with 22 built-in color themes and supports custom themes via YAML/JSON files or the extension API. Themes control all UI colors: input borders, popups, system messages, markdown rendering, syntax highlighting, and diff displays.</p>
|
||||
<h2 id="quick-start"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#quick-start"><span class="icon icon-link"></span></a>Quick start</h2>
|
||||
<p>Switch themes at runtime with the <code>/theme</code> command:</p>
|
||||
<pre><code>/theme dracula
|
||||
/theme catppuccin
|
||||
/theme kitt
|
||||
</code></pre>
|
||||
<p>Run <code>/theme</code> with no arguments to list all available themes.</p>
|
||||
<p><strong>Theme selections are automatically saved</strong> to <code>~/.config/kit/preferences.yml</code> and restored on next launch. You don't need to add anything to your config file — just <code>/theme <name></code> and it sticks. This persistence also applies to <strong>model</strong> and <strong>thinking level</strong> selections.</p>
|
||||
<h2 id="built-in-themes"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#built-in-themes"><span class="icon icon-link"></span></a>Built-in themes</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Theme</th>
|
||||
<th>Style</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>kitt</code></td>
|
||||
<td>KITT-inspired reds and ambers (default)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>catppuccin</code></td>
|
||||
<td>Soothing pastels (Mocha/Latte)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dracula</code></td>
|
||||
<td>Purple and cyan dark theme</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>tokyonight</code></td>
|
||||
<td>Cool blues with warm accents</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>nord</code></td>
|
||||
<td>Arctic, north-bluish palette</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>gruvbox</code></td>
|
||||
<td>Retro groove colors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>monokai</code></td>
|
||||
<td>Classic syntax theme</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>solarized</code></td>
|
||||
<td>Precision colors for machines and people</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>github</code></td>
|
||||
<td>GitHub's light and dark palettes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>one-dark</code></td>
|
||||
<td>Atom One Dark</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>rose-pine</code></td>
|
||||
<td>Soho vibes with muted tones</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>ayu</code></td>
|
||||
<td>Simple with bright colors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>material</code></td>
|
||||
<td>Material Design palette</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>everforest</code></td>
|
||||
<td>Green-focused comfortable theme</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>kanagawa</code></td>
|
||||
<td>Dark theme inspired by Katsushika Hokusai</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>amoled</code></td>
|
||||
<td>Pure black background, vivid accents</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>synthwave</code></td>
|
||||
<td>Retro neon glows</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vesper</code></td>
|
||||
<td>Warm minimalist dark theme</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>flexoki</code></td>
|
||||
<td>Inky reading palette</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>matrix</code></td>
|
||||
<td>Green-on-black terminal aesthetic</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vercel</code></td>
|
||||
<td>Clean monochrome with blue accents</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>zenburn</code></td>
|
||||
<td>Low-contrast, warm dark theme</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>All themes support both light and dark terminal modes via adaptive colors.</p>
|
||||
<h2 id="custom-theme-files"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#custom-theme-files"><span class="icon icon-link"></span></a>Custom theme files</h2>
|
||||
<p>Create a <code>.yml</code>, <code>.yaml</code>, or <code>.json</code> file with color definitions. Kit discovers themes from two directories:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Location</th>
|
||||
<th>Scope</th>
|
||||
<th>Precedence</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>~/.config/kit/themes/</code></td>
|
||||
<td>User (global)</td>
|
||||
<td>Overrides built-ins</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>.kit/themes/</code></td>
|
||||
<td>Project-local</td>
|
||||
<td>Overrides user and built-ins</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="theme-file-format"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#theme-file-format"><span class="icon icon-link"></span></a>Theme file format</h3>
|
||||
<p>A theme file defines adaptive color pairs with <code>light</code> and <code>dark</code> hex values. Any field left empty inherits from the default KITT theme.</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># ~/.config/kit/themes/my-theme.yml</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Core semantic colors</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">primary</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#8839ef"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#cba6f7"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">secondary</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#04a5e5"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#89dceb"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">success</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#40a02b"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#a6e3a1"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">warning</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#df8e1d"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#f9e2af"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">error</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#d20f39"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#f38ba8"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">info</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#1e66f5"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#89b4fa"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Text and chrome</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">text</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#4c4f69"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#cdd6f4"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">muted</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#6c6f85"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#a6adc8"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">very-muted</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#9ca0b0"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#6c7086"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">background</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#eff1f5"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#1e1e2e"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">border</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#acb0be"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#585b70"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">muted-border</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#ccd0da"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#313244"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Semantic roles</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">system</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#179299"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#94e2d5"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">tool</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#fe640b"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#fab387"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">accent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#ea76cb"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#f5c2e7"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">highlight</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#e6e9ef"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#181825"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Diff backgrounds</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">diff-insert-bg</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#d5f0d5"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#1a3a2a"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">diff-delete-bg</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#f5d5d5"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#3a1a2a"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">diff-equal-bg</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#eceef3"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#232336"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">diff-missing-bg</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#e4e6eb"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#1a1a2e"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Code block backgrounds</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">code-bg</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#eceef3"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#232336"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">gutter-bg</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#e4e6eb"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#1a1a2e"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">write-bg</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#d5f0d5"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#1a3a2a"</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Markdown and syntax highlighting</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">markdown</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> heading</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#1e66f5"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#89b4fa"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> link</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#1e66f5"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#89b4fa"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> keyword</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#8839ef"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#cba6f7"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> string</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#40a02b"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#a6e3a1"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> number</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#fe640b"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#fab387"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> comment</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#9ca0b0"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#6c7086"</span></span></code></pre>
|
||||
<h3 id="partial-themes"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#partial-themes"><span class="icon icon-link"></span></a>Partial themes</h3>
|
||||
<p>You only need to define the colors you want to change. Unspecified fields fall back to the default theme:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#6A737D;--shiki-dark:#6A737D"># Just override the primary and accent colors</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">primary</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#FF00FF"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">accent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#00FFFF"</span></span></code></pre>
|
||||
<h3 id="distributing-themes"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#distributing-themes"><span class="icon icon-link"></span></a>Distributing themes</h3>
|
||||
<ul>
|
||||
<li><strong>Personal</strong>: Drop a file in <code>~/.config/kit/themes/</code></li>
|
||||
<li><strong>Team/project</strong>: Drop a file in <code>.kit/themes/</code> and commit it to version control</li>
|
||||
<li><strong>Override built-in</strong>: Name your file the same as a built-in (e.g., <code>dracula.yml</code>) and it takes precedence</li>
|
||||
</ul>
|
||||
<h2 id="config-file-theme"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#config-file-theme"><span class="icon icon-link"></span></a>Config file theme</h2>
|
||||
<p>You can also set theme colors directly in <code>.kit.yml</code>:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">theme</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> primary</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> light</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#8839ef"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#cba6f7"</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> error</span><span style="color:#24292E;--shiki-dark:#E1E4E8">:</span></span>
|
||||
<span class="line"><span style="color:#22863A;--shiki-dark:#85E89D"> dark</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#FF0000"</span></span></code></pre>
|
||||
<p>Or reference an external theme file:</p>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#22863A;--shiki-dark:#85E89D">theme</span><span style="color:#24292E;--shiki-dark:#E1E4E8">: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"./themes/my-custom-theme.yml"</span></span></code></pre>
|
||||
<h2 id="extension-theme-api"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#extension-theme-api"><span class="icon icon-link"></span></a>Extension theme API</h2>
|
||||
<p>Extensions can register and switch themes programmatically at runtime.</p>
|
||||
<h3 id="registering-a-theme"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#registering-a-theme"><span class="icon icon-link"></span></a>Registering a theme</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">api.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">OnSessionStart</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#D73A49;--shiki-dark:#F97583">func</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#E36209;--shiki-dark:#FFAB70">_</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SessionStartEvent</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#E36209;--shiki-dark:#FFAB70">ctx</span><span style="color:#6F42C1;--shiki-dark:#B392F0"> ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">Context</span><span style="color:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">RegisterTheme</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"neon"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColorConfig</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Primary: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#CC00FF"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#FF00FF"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Secondary: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#0088CC"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#00FFFF"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Success: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#00CC44"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#00FF66"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Warning: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#CCAA00"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#FFFF00"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Error: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#CC0033"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#FF0055"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Info: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#0088CC"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#00CCFF"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Text: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#111111"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#F0F0F0"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> Background: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#F0F0F0"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#0A0A14"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> MdKeyword: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#CC00FF"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#FF00FF"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> MdString: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#00CC44"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#00FF66"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> MdComment: </span><span style="color:#6F42C1;--shiki-dark:#B392F0">ext</span><span style="color:#24292E;--shiki-dark:#E1E4E8">.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ThemeColor</span><span style="color:#24292E;--shiki-dark:#E1E4E8">{Light: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#888888"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">, Dark: </span><span style="color:#032F62;--shiki-dark:#9ECBFF">"#555555"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">},</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8"> })</span></span>
|
||||
<span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
|
||||
<h3 id="switching-themes"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#switching-themes"><span class="icon icon-link"></span></a>Switching themes</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">err </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">SetTheme</span><span style="color:#24292E;--shiki-dark:#E1E4E8">(</span><span style="color:#032F62;--shiki-dark:#9ECBFF">"dracula"</span><span style="color:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
|
||||
<h3 id="listing-available-themes"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#listing-available-themes"><span class="icon icon-link"></span></a>Listing available themes</h3>
|
||||
<pre class="shiki shiki-themes github-light github-dark" style="background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#24292E;--shiki-dark:#E1E4E8">names </span><span style="color:#D73A49;--shiki-dark:#F97583">:=</span><span style="color:#24292E;--shiki-dark:#E1E4E8"> ctx.</span><span style="color:#6F42C1;--shiki-dark:#B392F0">ListThemes</span><span style="color:#24292E;--shiki-dark:#E1E4E8">()</span></span></code></pre>
|
||||
<h3 id="themecolorconfig-fields"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#themecolorconfig-fields"><span class="icon icon-link"></span></a>ThemeColorConfig fields</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>Primary</code></td>
|
||||
<td>Main brand/accent color</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Secondary</code></td>
|
||||
<td>Secondary accent</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Success</code></td>
|
||||
<td>Success states</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Warning</code></td>
|
||||
<td>Warning states</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Error</code></td>
|
||||
<td>Error/critical states</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Info</code></td>
|
||||
<td>Informational states</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Text</code></td>
|
||||
<td>Primary text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Muted</code></td>
|
||||
<td>Dimmed text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>VeryMuted</code></td>
|
||||
<td>Very dimmed text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Background</code></td>
|
||||
<td>Base background</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Border</code></td>
|
||||
<td>Panel borders</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>MutedBorder</code></td>
|
||||
<td>Subtle dividers</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>System</code></td>
|
||||
<td>System messages</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Tool</code></td>
|
||||
<td>Tool-related elements</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Accent</code></td>
|
||||
<td>Secondary highlight</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Highlight</code></td>
|
||||
<td>Highlighted regions</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>MdHeading</code></td>
|
||||
<td>Markdown headings</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>MdLink</code></td>
|
||||
<td>Markdown links</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>MdKeyword</code></td>
|
||||
<td>Syntax: keywords</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>MdString</code></td>
|
||||
<td>Syntax: strings</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>MdNumber</code></td>
|
||||
<td>Syntax: numbers</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>MdComment</code></td>
|
||||
<td>Syntax: comments</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Each field is an <code>ext.ThemeColor</code> with <code>Light</code> and <code>Dark</code> hex strings. Empty fields inherit from the default theme.</p>
|
||||
<h2 id="precedence-order"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#precedence-order"><span class="icon icon-link"></span></a>Precedence order</h2>
|
||||
<p>When multiple sources define the same theme name, later sources win:</p>
|
||||
<ol>
|
||||
<li>Built-in presets (lowest)</li>
|
||||
<li>User themes (<code>~/.config/kit/themes/</code>)</li>
|
||||
<li>Project-local themes (<code>.kit/themes/</code>)</li>
|
||||
<li>Extension-registered themes (highest)</li>
|
||||
</ol>
|
||||
<h3 id="startup-theme-resolution"><a class="heading-anchor" aria-hidden="" tabindex="-1" href="#startup-theme-resolution"><span class="icon icon-link"></span></a>Startup theme resolution</h3>
|
||||
<p>At startup, Kit determines which theme to apply:</p>
|
||||
<ol>
|
||||
<li><strong><code>.kit.yml</code> <code>theme:</code> key</strong> — explicit config always wins (highest priority)</li>
|
||||
<li><strong><code>~/.config/kit/preferences.yml</code></strong> — persisted <code>/theme</code> selection</li>
|
||||
<li><strong>Default <code>kitt</code> theme</strong> — fallback</li>
|
||||
</ol>
|
||||
<p>The preferences file is updated automatically whenever you use <code>/theme</code> or <code>ctx.SetTheme()</code>. It is separate from <code>.kit.yml</code> so it never clobbers your config comments or formatting.</p>
|
||||
<p>Theme changes via <code>/theme</code> or <code>ctx.SetTheme()</code> take effect immediately on all UI elements, including previously rendered messages.</p>`,headings:[{depth:2,text:"Quick start",id:"quick-start"},{depth:2,text:"Built-in themes",id:"built-in-themes"},{depth:2,text:"Custom theme files",id:"custom-theme-files"},{depth:3,text:"Theme file format",id:"theme-file-format"},{depth:3,text:"Partial themes",id:"partial-themes"},{depth:3,text:"Distributing themes",id:"distributing-themes"},{depth:2,text:"Config file theme",id:"config-file-theme"},{depth:2,text:"Extension theme API",id:"extension-theme-api"},{depth:3,text:"Registering a theme",id:"registering-a-theme"},{depth:3,text:"Switching themes",id:"switching-themes"},{depth:3,text:"Listing available themes",id:"listing-available-themes"},{depth:3,text:"ThemeColorConfig fields",id:"themecolorconfig-fields"},{depth:2,text:"Precedence order",id:"precedence-order"},{depth:3,text:"Startup theme resolution",id:"startup-theme-resolution"}],raw:`
|
||||
# Themes
|
||||
|
||||
Kit ships with 22 built-in color themes and supports custom themes via YAML/JSON files or the extension API. Themes control all UI colors: input borders, popups, system messages, markdown rendering, syntax highlighting, and diff displays.
|
||||
|
||||
## Quick start
|
||||
|
||||
Switch themes at runtime with the \`/theme\` command:
|
||||
|
||||
\`\`\`
|
||||
/theme dracula
|
||||
/theme catppuccin
|
||||
/theme kitt
|
||||
\`\`\`
|
||||
|
||||
Run \`/theme\` with no arguments to list all available themes.
|
||||
|
||||
**Theme selections are automatically saved** to \`~/.config/kit/preferences.yml\` and restored on next launch. You don't need to add anything to your config file — just \`/theme <name>\` and it sticks. This persistence also applies to **model** and **thinking level** selections.
|
||||
|
||||
## Built-in themes
|
||||
|
||||
| Theme | Style |
|
||||
|-------|-------|
|
||||
| \`kitt\` | KITT-inspired reds and ambers (default) |
|
||||
| \`catppuccin\` | Soothing pastels (Mocha/Latte) |
|
||||
| \`dracula\` | Purple and cyan dark theme |
|
||||
| \`tokyonight\` | Cool blues with warm accents |
|
||||
| \`nord\` | Arctic, north-bluish palette |
|
||||
| \`gruvbox\` | Retro groove colors |
|
||||
| \`monokai\` | Classic syntax theme |
|
||||
| \`solarized\` | Precision colors for machines and people |
|
||||
| \`github\` | GitHub's light and dark palettes |
|
||||
| \`one-dark\` | Atom One Dark |
|
||||
| \`rose-pine\` | Soho vibes with muted tones |
|
||||
| \`ayu\` | Simple with bright colors |
|
||||
| \`material\` | Material Design palette |
|
||||
| \`everforest\` | Green-focused comfortable theme |
|
||||
| \`kanagawa\` | Dark theme inspired by Katsushika Hokusai |
|
||||
| \`amoled\` | Pure black background, vivid accents |
|
||||
| \`synthwave\` | Retro neon glows |
|
||||
| \`vesper\` | Warm minimalist dark theme |
|
||||
| \`flexoki\` | Inky reading palette |
|
||||
| \`matrix\` | Green-on-black terminal aesthetic |
|
||||
| \`vercel\` | Clean monochrome with blue accents |
|
||||
| \`zenburn\` | Low-contrast, warm dark theme |
|
||||
|
||||
All themes support both light and dark terminal modes via adaptive colors.
|
||||
|
||||
## Custom theme files
|
||||
|
||||
Create a \`.yml\`, \`.yaml\`, or \`.json\` file with color definitions. Kit discovers themes from two directories:
|
||||
|
||||
| Location | Scope | Precedence |
|
||||
|----------|-------|------------|
|
||||
| \`~/.config/kit/themes/\` | User (global) | Overrides built-ins |
|
||||
| \`.kit/themes/\` | Project-local | Overrides user and built-ins |
|
||||
|
||||
### Theme file format
|
||||
|
||||
A theme file defines adaptive color pairs with \`light\` and \`dark\` hex values. Any field left empty inherits from the default KITT theme.
|
||||
|
||||
\`\`\`yaml
|
||||
# ~/.config/kit/themes/my-theme.yml
|
||||
|
||||
# Core semantic colors
|
||||
primary:
|
||||
light: "#8839ef"
|
||||
dark: "#cba6f7"
|
||||
secondary:
|
||||
light: "#04a5e5"
|
||||
dark: "#89dceb"
|
||||
success:
|
||||
light: "#40a02b"
|
||||
dark: "#a6e3a1"
|
||||
warning:
|
||||
light: "#df8e1d"
|
||||
dark: "#f9e2af"
|
||||
error:
|
||||
light: "#d20f39"
|
||||
dark: "#f38ba8"
|
||||
info:
|
||||
light: "#1e66f5"
|
||||
dark: "#89b4fa"
|
||||
|
||||
# Text and chrome
|
||||
text:
|
||||
light: "#4c4f69"
|
||||
dark: "#cdd6f4"
|
||||
muted:
|
||||
light: "#6c6f85"
|
||||
dark: "#a6adc8"
|
||||
very-muted:
|
||||
light: "#9ca0b0"
|
||||
dark: "#6c7086"
|
||||
background:
|
||||
light: "#eff1f5"
|
||||
dark: "#1e1e2e"
|
||||
border:
|
||||
light: "#acb0be"
|
||||
dark: "#585b70"
|
||||
muted-border:
|
||||
light: "#ccd0da"
|
||||
dark: "#313244"
|
||||
|
||||
# Semantic roles
|
||||
system:
|
||||
light: "#179299"
|
||||
dark: "#94e2d5"
|
||||
tool:
|
||||
light: "#fe640b"
|
||||
dark: "#fab387"
|
||||
accent:
|
||||
light: "#ea76cb"
|
||||
dark: "#f5c2e7"
|
||||
highlight:
|
||||
light: "#e6e9ef"
|
||||
dark: "#181825"
|
||||
|
||||
# Diff backgrounds
|
||||
diff-insert-bg:
|
||||
light: "#d5f0d5"
|
||||
dark: "#1a3a2a"
|
||||
diff-delete-bg:
|
||||
light: "#f5d5d5"
|
||||
dark: "#3a1a2a"
|
||||
diff-equal-bg:
|
||||
light: "#eceef3"
|
||||
dark: "#232336"
|
||||
diff-missing-bg:
|
||||
light: "#e4e6eb"
|
||||
dark: "#1a1a2e"
|
||||
|
||||
# Code block backgrounds
|
||||
code-bg:
|
||||
light: "#eceef3"
|
||||
dark: "#232336"
|
||||
gutter-bg:
|
||||
light: "#e4e6eb"
|
||||
dark: "#1a1a2e"
|
||||
write-bg:
|
||||
light: "#d5f0d5"
|
||||
dark: "#1a3a2a"
|
||||
|
||||
# Markdown and syntax highlighting
|
||||
markdown:
|
||||
heading:
|
||||
light: "#1e66f5"
|
||||
dark: "#89b4fa"
|
||||
link:
|
||||
light: "#1e66f5"
|
||||
dark: "#89b4fa"
|
||||
keyword:
|
||||
light: "#8839ef"
|
||||
dark: "#cba6f7"
|
||||
string:
|
||||
light: "#40a02b"
|
||||
dark: "#a6e3a1"
|
||||
number:
|
||||
light: "#fe640b"
|
||||
dark: "#fab387"
|
||||
comment:
|
||||
light: "#9ca0b0"
|
||||
dark: "#6c7086"
|
||||
\`\`\`
|
||||
|
||||
### Partial themes
|
||||
|
||||
You only need to define the colors you want to change. Unspecified fields fall back to the default theme:
|
||||
|
||||
\`\`\`yaml
|
||||
# Just override the primary and accent colors
|
||||
primary:
|
||||
dark: "#FF00FF"
|
||||
accent:
|
||||
dark: "#00FFFF"
|
||||
\`\`\`
|
||||
|
||||
### Distributing themes
|
||||
|
||||
- **Personal**: Drop a file in \`~/.config/kit/themes/\`
|
||||
- **Team/project**: Drop a file in \`.kit/themes/\` and commit it to version control
|
||||
- **Override built-in**: Name your file the same as a built-in (e.g., \`dracula.yml\`) and it takes precedence
|
||||
|
||||
## Config file theme
|
||||
|
||||
You can also set theme colors directly in \`.kit.yml\`:
|
||||
|
||||
\`\`\`yaml
|
||||
theme:
|
||||
primary:
|
||||
light: "#8839ef"
|
||||
dark: "#cba6f7"
|
||||
error:
|
||||
dark: "#FF0000"
|
||||
\`\`\`
|
||||
|
||||
Or reference an external theme file:
|
||||
|
||||
\`\`\`yaml
|
||||
theme: "./themes/my-custom-theme.yml"
|
||||
\`\`\`
|
||||
|
||||
## Extension theme API
|
||||
|
||||
Extensions can register and switch themes programmatically at runtime.
|
||||
|
||||
### Registering a theme
|
||||
|
||||
\`\`\`go
|
||||
api.OnSessionStart(func(_ ext.SessionStartEvent, ctx ext.Context) {
|
||||
ctx.RegisterTheme("neon", ext.ThemeColorConfig{
|
||||
Primary: ext.ThemeColor{Light: "#CC00FF", Dark: "#FF00FF"},
|
||||
Secondary: ext.ThemeColor{Light: "#0088CC", Dark: "#00FFFF"},
|
||||
Success: ext.ThemeColor{Light: "#00CC44", Dark: "#00FF66"},
|
||||
Warning: ext.ThemeColor{Light: "#CCAA00", Dark: "#FFFF00"},
|
||||
Error: ext.ThemeColor{Light: "#CC0033", Dark: "#FF0055"},
|
||||
Info: ext.ThemeColor{Light: "#0088CC", Dark: "#00CCFF"},
|
||||
Text: ext.ThemeColor{Light: "#111111", Dark: "#F0F0F0"},
|
||||
Background: ext.ThemeColor{Light: "#F0F0F0", Dark: "#0A0A14"},
|
||||
MdKeyword: ext.ThemeColor{Light: "#CC00FF", Dark: "#FF00FF"},
|
||||
MdString: ext.ThemeColor{Light: "#00CC44", Dark: "#00FF66"},
|
||||
MdComment: ext.ThemeColor{Light: "#888888", Dark: "#555555"},
|
||||
})
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
### Switching themes
|
||||
|
||||
\`\`\`go
|
||||
err := ctx.SetTheme("dracula")
|
||||
\`\`\`
|
||||
|
||||
### Listing available themes
|
||||
|
||||
\`\`\`go
|
||||
names := ctx.ListThemes()
|
||||
\`\`\`
|
||||
|
||||
### ThemeColorConfig fields
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| \`Primary\` | Main brand/accent color |
|
||||
| \`Secondary\` | Secondary accent |
|
||||
| \`Success\` | Success states |
|
||||
| \`Warning\` | Warning states |
|
||||
| \`Error\` | Error/critical states |
|
||||
| \`Info\` | Informational states |
|
||||
| \`Text\` | Primary text |
|
||||
| \`Muted\` | Dimmed text |
|
||||
| \`VeryMuted\` | Very dimmed text |
|
||||
| \`Background\` | Base background |
|
||||
| \`Border\` | Panel borders |
|
||||
| \`MutedBorder\` | Subtle dividers |
|
||||
| \`System\` | System messages |
|
||||
| \`Tool\` | Tool-related elements |
|
||||
| \`Accent\` | Secondary highlight |
|
||||
| \`Highlight\` | Highlighted regions |
|
||||
| \`MdHeading\` | Markdown headings |
|
||||
| \`MdLink\` | Markdown links |
|
||||
| \`MdKeyword\` | Syntax: keywords |
|
||||
| \`MdString\` | Syntax: strings |
|
||||
| \`MdNumber\` | Syntax: numbers |
|
||||
| \`MdComment\` | Syntax: comments |
|
||||
|
||||
Each field is an \`ext.ThemeColor\` with \`Light\` and \`Dark\` hex strings. Empty fields inherit from the default theme.
|
||||
|
||||
## Precedence order
|
||||
|
||||
When multiple sources define the same theme name, later sources win:
|
||||
|
||||
1. Built-in presets (lowest)
|
||||
2. User themes (\`~/.config/kit/themes/\`)
|
||||
3. Project-local themes (\`.kit/themes/\`)
|
||||
4. Extension-registered themes (highest)
|
||||
|
||||
### Startup theme resolution
|
||||
|
||||
At startup, Kit determines which theme to apply:
|
||||
|
||||
1. **\`.kit.yml\` \`theme:\` key** — explicit config always wins (highest priority)
|
||||
2. **\`~/.config/kit/preferences.yml\`** — persisted \`/theme\` selection
|
||||
3. **Default \`kitt\` theme** — fallback
|
||||
|
||||
The preferences file is updated automatically whenever you use \`/theme\` or \`ctx.SetTheme()\`. It is separate from \`.kit.yml\` so it never clobbers your config comments or formatting.
|
||||
|
||||
Theme changes via \`/theme\` or \`ctx.SetTheme()\` take effect immediately on all UI elements, including previously rendered messages.
|
||||
`};export{s as default};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user