Removes ~600 lines of unreferenced code surfaced by deadcode + manual
audit (none of it reachable from production code paths or test setup):
- internal/models/pool.go: ProviderPool was never wired into kitsetup
or the agent; the global pool singleton had zero callers.
- internal/ui/debug_logger.go: CLIDebugLogger was unreachable; debug
routing goes through internal/tools/buffered_logger.go instead.
- internal/ui/tool_approval_input.go: tea.Model never instantiated;
approvals are handled inline in model.go.
- internal/ui/cli.go: DisplayAssistantMessage / DisplayCancellation /
GetDebugLogger had zero callers (the *WithModel variant is what
event_handler.go uses).
- internal/ui/style/enhanced.go: Style{Card,Header,Subheader,Muted,
Success,Error,Warning,Info} + Create{Separator,ProgressBar} — none
used. CreateBadge stays (used by model.go).
- internal/ui/style/themes.go: RefreshThemeRegistry — never called.
- internal/ui/block_renderer.go: With{FullWidth,MarginTop,Padding{Left,
Right},Background,Foreground,Width} — option helpers nobody calls.
- internal/ui/render/blocks.go: UserBlock, ToolBlock — replaced by
inline rendering elsewhere; the test for UserBlock was rewritten to
directly exercise HighlightFileTokens (which is what the test really
cared about).
- internal/ui/commands/commands.go: GetAllCommandNames — no callers.
- internal/ui/message_items.go: NewTextMessageItem,
NewSystemMessageItem + the entire SystemMessageItem type — model.go
uses NewStyledMessageItem instead.
- internal/prompts/loader.go: Deduplicate — the loader does dedup
internally; standalone helper was unused.
- internal/models/cache_options.go: mergeProviderOptions + its
test-only consumer.
- internal/extensions/installer.go: Installer.GetInstalledPackages —
intended for a 'kit ext list' command that was never built.
- internal/extensions/manifest.go: saveManifestToScope,
saveManifestToPath, GetGlobalManifest, GetProjectManifest,
addEntryToManifest, removeEntryFromManifest — package-level
duplicates of *Installer methods. Tests rewritten to exercise the
live Installer methods instead, which fixes a latent path-resolution
inconsistency between manifestPathForScope and Installer.manifestPath
(the former hard-coded paths, the latter respects projectGitRoot).
- internal/extensions/subagent.go: SpawnSubagent + helpers
(generateSubagentID, findKitBinary, subagentJSONOutput). The
subprocess-spawn implementation is unreachable; production code
routes through kit.Kit.Subagent (in-process). Types
(SubagentConfig/Result/Handle/etc.) and the SubagentHandle methods
remain because they are exposed to extensions via Yaegi symbols and
the Context.SpawnSubagent field.
- cmd/root.go: LoadConfigWithEnvSubstitution — one-line wrapper around
kit.LoadConfigWithEnvSubstitution with zero callers.
go test -race ./... passes.
- Add ToolOutput struct, TextResult/ErrorResult helpers, and
ToolCallIDFromContext so SDK consumers can create custom tools
without importing charm.land/fantasy
- Add NewTool (sequential) and NewParallelTool (concurrent) generic
constructors with automatic JSON schema generation from struct tags
- Remove dead UpdateUsageFromResponse method and fantasy import from
internal/ui/cli.go
- Update SDK skill, README, and www/ docs with custom tool examples
and corrected hook signatures
The compact display mode was purely a UI concern that added complexity
without providing unique value. Anyone wanting compact-style formatting
can implement it as an extension using the Renderer interface.
- Delete internal/ui/compact_renderer.go
- Remove renderToolBodyCompact and all compact tool body renderers from
tool_renderers.go
- Simplify NewCLI(debug bool) — drop compact parameter
- Simplify NewStreamComponent(width, modelName) — drop compactMode parameter
- Remove CompactMode from AppModelOptions, app.Options, CLISetupOptions
- Remove Compact from internal/config/config.go
- Remove --compact flag, var, and viper binding from cmd/root.go
- Update format.go: remove CompactRenderer interface compile-time check
and clean up comments
- /new command now properly resets usageTracker stats when starting fresh session
- Remove EstimateAndUpdateUsage fallback in updateUsageFromTurnResult()
- Remove EstimateAndUpdateUsage fallback in UpdateUsageFromResponse()
- Only use actual API-reported tokens for cost tracking (following opencode pattern)
- Estimation is inaccurate and should never be used for billing
Fixes issues with kimi-k2.5 and opencode token tracking where:
1. /new didn't reset token count/cost
2. Tokens never updated correctly due to estimation fallback
Implements OAuth authentication for OpenAI ChatGPT Plus/Pro (Codex) similar to pi:
- Add OpenAICredentials type with OAuth and API key support
- Add OpenAI OAuth client with correct endpoints (auth.openai.com)
- Implement PKCE-based OAuth flow with local callback server on :1455
- Add login/logout/status commands for openai provider
- Support both ChatGPT/Codex OAuth tokens (chatgpt.com/backend-api) and
regular OpenAI API keys (api.openai.com)
- Extract and store ChatGPT account ID from JWT token
- Add custom HTTP transport with required Codex headers:
- chatgpt-account-id, originator, OpenAI-Beta: responses=experimental
- Update provider selection to use correct endpoint based on auth type
Usage:
kit auth login openai # OAuth with ChatGPT account
kit auth logout openai
kit auth status
The implementation follows the same patterns as the existing Anthropic OAuth
support, with automatic token refresh and secure credential storage in
~/.config/.kit/credentials.json
Replace the Catppuccin color palette with a Knight Rider KITT-inspired
theme — scanner reds, amber dashboard glows, and dark cockpit tones.
No blues or bright greens; the entire palette stays in the warm
red/amber/gray family.
Unify the theme system by folding the standalone MarkdownTheme config
into the main Theme struct, eliminating the separate config path.
Replace all hardcoded lipgloss.Color() calls across input, overlay,
and CLI components with semantic theme references so every color
responds to theme customization.
Core tools previously rendered two separate blocks: an 'Executing tool'
header block on ToolCallStartedEvent, then a separate result block on
ToolResultEvent. This merges them into a single unified block that
renders only when the result arrives.
The unified block shows a status icon (checkmark/cross), a friendly
tool display name, inline parameters, and the output body. Border
color indicates success (green) or error (red).
- Fix context percentage: use FinalResponse.Usage (last API call) instead of
TotalUsage (sum of all tool-calling steps) which overstated context fill level
- Fix token count: display current context window tokens, not cumulative session
total, so the number and percentage tell a consistent story
- Fix script mode double-counting: app.updateUsage already updates the shared
tracker before sending StepCompleteEvent, so remove redundant
UpdateUsageFromResponse call
- Add sticky usage display in TUI: render in View() layout between stream and
separator instead of tea.Println so it updates in place
- Add usage display for non-interactive --prompt mode (non-quiet)
- Add SetContextTokens to UsageUpdater interface for separating billing tokens
(TotalUsage) from context utilization (FinalResponse.Usage)
Script mode had a duplicated agentic loop (runAgenticLoop/runAgenticStep)
that was copied from root.go during the Bubble Tea refactor but left with
broken streaming display and missing hooks integration. The streaming
callback silently accumulated chunks without rendering, and the final
response was skipped because it assumed streaming had already shown it.
- Refactor app.executeStep to accept a generic eventFn callback instead
of a *tea.Program, decoupling the agent step from Bubble Tea
- Add app.RunOnceWithDisplay for non-TUI callers that need intermediate
display events (spinner, tool calls, streaming chunks)
- Replace ~300 lines of duplicated code in script.go with a lightweight
scriptEventHandler that routes app events to CLI display methods
- Fix agent.GenerateWithLoopAndStreaming to use the streaming path when
any callbacks are provided (fantasy only exposes callbacks on Stream)
- Fix CLI displayContainer to match TUI output (remove extra padding)
- Remove premature usage display during CLI setup
Spinner now uses theme.Primary/Muted/VeryMuted/MutedBorder instead of
hardcoded red. Removed 'Thinking...' label and message parameter from
NewSpinner/ShowSpinner/SpinnerFunc. Spinner keeps running alongside
streaming text and only hides on step complete via Reset().
Remove methods that belonged to the old interactive loop and have no
external callers: HandleSlashCommand, SlashCommandResult, IsSlashCommand,
DisplayHelp, DisplayTools, DisplayServers, ClearMessages, UpdateUsage,
DisplayUsageStats, ResetUsageStats. Slash command dispatch is now owned
by InputComponent in the Bubble Tea TUI; usage tracking is handled
directly by the app layer.
Retain all display methods still needed by non-interactive paths
(cmd/root.go session replay, cmd/script.go, factory.go). Also drop the
now-unused "strings" import. cli.go shrinks from 509 to 329 lines.
Delete GetPrompt, StartStreamingMessage, UpdateStreamingMessage,
GetToolApproval, and finishStreaming from CLI — these each spun up
their own tea.NewProgram and are superseded by the unified AppModel
TUI. Also remove the streamProgram/streamDone fields they relied on.
Update dead-code stubs in cmd/root.go to keep the build clean until
the legacy agentic-loop functions are deleted in TAS-28.
Add UsageUpdater interface to app/options.go to avoid circular imports,
wire *ui.UsageTracker via Options.UsageTracker in cmd/root.go, and call
updateUsage() after each successful step in both runPrompt() and RunOnce().
Streaming text was flickering because displayContainer() used raw escape
sequences (\033[%dF) to move the cursor and fmt.Println to repaint on
every token. This bypassed Bubble Tea's synchronized output, cursor
hiding, and atomic flush.
Replace the manual approach with a dedicated tea.Program that runs for
the lifetime of each streaming response. BT's renderer now handles all
in-place updates flicker-free. One-shot messages (user, tool, system,
error) continue to use simple fmt.Println since they are never redrawn.
Replace catwalk dependency with direct models.dev integration (97 providers,
3039 models vs catwalk's 22/679). Auto-route @ai-sdk/openai-compatible
providers through fantasy's openaicompat using the api URL from models.dev,
eliminating the need for --provider-url. Add --all flag to 'mcphost models'
to show all providers vs just fantasy-compatible ones.
Fix all 74 golangci-lint issues: errcheck (53), staticcheck SA4006 (24),
SA9003 (2), ST1005 (5), ineffassign (3). Restructure styles.go color
handling into a colorScheme struct to eliminate SA4006 false positives
from new(x) syntax.
Each spinner created a new tea.NewProgram which sent DECRQM queries for
synchronized output mode 2026. When the program exited and restored
cooked terminal mode, the terminal's DECRPM response leaked as visible
^[[?2026;2$y characters. Replace Bubble Tea spinner with a simple
goroutine animation loop writing directly to stderr via lipgloss.
Adds a new CLI option, `--approve-tool-run` (or via config setting),
that when enabled, prompts the user to approve a tool's execution
before it runs.
This option is disabled by default to maintain existing behavior.
* draft: rewrite single message when streaming (not full terminal)
* having the spinner align better with dots in compact mode
* fix user messages
* handle usage display
* fix formatting
* bash highlighting
---------
Co-authored-by: Nate Woods <big.nate.w@gmail.com>
* Model generation params
* Standardize model URL
* standardize more flags and update max steps check
* fix system prompt handling
* standardize api key handling
* update readme