Files
kit/www/pages/extensions/examples.md
T
Ed Zynda 49f8b485be feat(extensions): add OnLLMUsage, SetState, enriched AgentEndEvent (#53) (#54)
* feat(extensions): add OnLLMUsage, SetState, enriched AgentEndEvent (#53)

Three additive primitives to the extension API:

- OnLLMUsage event: per-LLM-call token + cost deltas attributed to the
  specific model/provider used for each round-trip. Derived from the SDK
  StepFinishEvent in the extension bridge. Enables accurate budget
  enforcement between calls instead of only at turn boundaries.

- ctx.SetState / GetState / DeleteState / ListState: session-scoped,
  last-write-wins key-value store backed by a sidecar file
  (<session>.ext-state.json) outside the conversation tree. Reads are
  O(1), writes don't grow the JSONL, and the store is not duplicated on
  fork. State is preserved across hot-reloads.

- Enriched AgentEndEvent: ToolCallCount, ToolNames, LLMCallCount, token
  deltas (input/output/cache-read/cache-write), CostDelta, and
  DurationMs populated by a per-turn aggregator. Existing handlers
  reading only Response/StopReason are unaffected.

Includes unit tests for the state store, LLMUsage registration,
enriched AgentEndEvent, turn aggregator, llmUsageMeta, and sidecar path
derivation. Adds examples/extensions/usage-budget.go demoing all three
primitives together. Documents the additions in README, the docs site
(extensions overview, capabilities, examples), and the kit-extensions
and kit-sdk skill guides.

Fixes #53

* fix(extensions): address review feedback on state store and llmUsageMeta

- Serialize SetState/DeleteState saver invocations through a new saverMu
  so overlapping atomic-rename writes can no longer race on the shared
  .tmp file and persist an older snapshot after a newer one.
- LoadStateFromFile now clears the in-memory store when the sidecar is
  missing or empty, matching the documented "replace … with its
  contents" contract. This makes session-switching safe by preventing
  keys from a prior session leaking into a new one. Tests updated to
  cover both the missing-file and empty-file cases.
- llmUsageMeta now detects Anthropic OAuth credentials and returns
  Cost=0, matching the comment and the existing usage_tracker behavior
  for OAuth users. Mirrors the OAuth detection already used in
  cmd/extension_context.go.
- Document the single-in-flight-turn assumption baked into the
  per-turn aggregator with a clear migration path (per-turn ID) for if
  concurrent turns ever become a supported use case.

* fix(extensions): release saverMu on panic in state store

Extract a runSaver helper that locks saverMu and defers Unlock before
invoking the persistence callback. Without the deferred Unlock, a panic
inside the saver (e.g. disk full mid-write) would leave saverMu held
forever and deadlock the next SetState/DeleteState. Both SetState and
DeleteState now route through the helper. New TestRunner_State_Saver
PanicReleasesSaverMu reproduces the deadlock window with a 2s deadline
and proves the mutex is released after a panic.
2026-06-09 16:18:10 +03:00

7.0 KiB

title, description
title description
Examples Catalog of example extensions included with Kit.

Extension Examples

Kit ships with a rich set of example extensions in the examples/extensions/ directory. These serve as both documentation and starting points for your own extensions.

UI and display

Extension Description
minimal.go Clean UI with custom footer
branded-output.go Branded output rendering
header-footer-demo.go Custom headers and footers
widget-status.go Persistent status widgets
overlay-demo.go Modal dialogs
tool-renderer-demo.go Custom tool call rendering
custom-editor-demo.go Vim-like modal editor
pirate.go Pirate-themed personality

Workflow and automation

Extension Description
auto-commit.go Auto-commit changes on shutdown
plan-mode.go Read-only planning mode
permission-gate.go Permission gating for destructive tools
confirm-destructive.go Confirm destructive operations
protected-paths.go Path protection for sensitive files
project-rules.go Project-specific rules injection
compact-notify.go Notification on conversation compaction

Interactive features

Extension Description
prompt-demo.go Interactive prompts (select/confirm/input)
bookmark.go Bookmark conversations
inline-bash.go Inline bash execution
interactive-shell.go Interactive shell integration
notify.go Desktop notifications

Agent and context

Extension Description
tool-logger.go Log all tool calls
context-inject.go Inject context into conversations
summarize.go Conversation summarization
lsp-diagnostics.go LSP diagnostic integration
usage-budget.go Per-call usage callback (OnLLMUsage), session state (SetState/GetState), and enriched OnAgentEnd per-turn report

Bridged SDK APIs

These examples demonstrate the new bridged SDK APIs that give extensions access to internal Kit capabilities:

Extension Description
bridge-demo.go Comprehensive demo of all bridged APIs — tree navigation, skill loading, template parsing, and model resolution
conversation-manager.go Tree navigation (GetTreeNode, GetCurrentBranch, NavigateTo), branch summarization (SummarizeBranch), and fresh context loops (CollapseBranch)
prompt-templates.go Frontmatter-driven templates with model fallback chains (ResolveModelChain), skill injection (InjectSkillAsContext), and template parsing (ParseTemplate, RenderTemplate)

Themes

Extension Description
neon-theme.go Custom theme registration and switching

Multi-agent

Extension Description
kit-kit.go Kit-in-Kit sub-agent spawning
subagent-widget.go Multi-agent orchestration with status widget
subagent-test.go Subagent testing utilities

Development

Extension Description
dev-reload.go Development live-reload
tool-logger_test.go Example extension tests (see Testing)
extension_test_template.go Copy-and-paste test template for your extensions

Subdirectory extensions

Directory Description
kit-kit-agents/ Multi-agent orchestration example
kit-telegram/ Telegram bot integration
status-tools/ Status bar tool examples

Project-local example

The Kit repository also includes a project-local extension at .kit/extensions/go-edit-lint.go that demonstrates running gopls and golangci-lint on Go file edits. This serves as an example of how to create extensions specific to a project by placing them in the .kit/extensions/ directory.