mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-22 07:34:26 +00:00
* feat(cli): unify TUI dialog interaction and visuals Align every list dialog and selector to a single spec: shared selection pointer and current-item marker, single-border header with a (type to search) title suffix, consistent search line, and a uniform keyboard-hint vocabulary. Replace ad-hoc exit wording (close/back/exit/dismiss) with cancel, hardcoded pointers with the shared constant, and ▲▼ with ↑↓. Also add fuzzy search to /provider, restyle the /model provider tabs, and require a token with multi-field navigation in the custom-registry import. Introduce the write-tui skill (carrying the DESIGN.md spec) and refresh the apps/kimi-code development guide to match the current TUI architecture. * feat(cli): drop arrow-key navigation in the plugins selector The plugins overview and its marketplace/MCP sub-views used Left/Right to enter and exit details. Remove that hierarchy navigation: Enter opens a detail, Esc returns, and the arrow keys no longer jump between levels. Update the sub-view hints from `←/Esc cancel` to `Esc cancel`. * feat(cli): install marketplace plugins on Enter only The marketplace install action also fired on Space, which collides with the Space-toggle convention used elsewhere. Bind install to Enter only and update the hint to `Enter install/update`. * feat(cli): reword the plugin inline change hint The inline badge shown on a changed plugin row read `pending /new`, which was cryptic. Reword it to `require run /new to apply`. Also switch the marketplace-install message-flow tests to Enter, matching the Enter-only install binding. * fix(cli): stop the editor flash when toggling a plugin Each plugin picker's onSelect unconditionally restored the editor before the handler re-mounted the refreshed picker, so an in-place action like Space-toggling a plugin flashed: picker → editor → picker. Drop the pre-restore from the overview/marketplace/MCP onSelect callbacks and let each handler branch mount its next view; the two branches that close to the editor (show-list, info) restore it themselves. * feat(cli): drop /provider search and delete with D Remove the fuzzy filter from the provider manager: no query state, search line, or type-to-search title suffix, and Esc closes directly. With no type-to-search to clash with, bind delete to the D key (matching /plugins) instead of Del/Ctrl+D. Update the write-tui spec to specify D as the delete shortcut. * fix(cli): default thinking-capable models to thinking on The model selector seeded a single thinking draft from the global thinking flag, so highlighting a thinking-capable model showed Off whenever the active model had thinking off (e.g. a non-thinking current model). Compute the draft per model instead: the active model keeps its live state, any other thinking-capable model defaults to On, and a ←/→ toggle is remembered per model.
7 KiB
7 KiB
apps/kimi-code Development Guide
This file only contains rules local to apps/kimi-code. For cross-repo rules, see the root AGENTS.md.
Writing or modifying the TUI? Use the
write-tuiskill (.agents/skills/write-tui/SKILL.md). It covers the architecture orientation, where new features go, test placement, theme mechanics, and the dialog interaction/visual spec (DESIGN.md). This file keeps only the map, boundaries, and hard constraints.
TUI File Layout
apps/kimi-code is the terminal UI / CLI app. The entry chain is:
src/main.ts -> src/cli/commands.ts -> src/cli/run-shell.ts -> SDK KimiHarness -> src/tui/kimi-tui.ts
Main directories:
src/constant/: non-copy constants shared by CLI/TUI — product, protocol, paths, terminal control, updates, and so on.src/cli/: command-line arguments, subcommands, and CLI startup.src/tui/: the interactive terminal UI.src/tui/kimi-tui.ts: theKimiTUIcoordinator — wires state, layout, editor, session, SDK events, and dialogs together, and dispatches slash-command handlers. Heavy logic is delegated tocontrollers/, not accumulated here.src/tui/tui-state.ts:TUIState,createTUIState,createInitialAppState— the single global UI-state shape.src/tui/controllers/: independently-testable responsibilities —session-event-handler(SDK event routing),streaming-ui(streaming render),session-replay(resume/replay),tasks-browser,editor-keyboard,auth-flow.src/tui/commands/: slash command definitions, parsing, ordering, and dynamic skill command generation.src/tui/components/: pi-tui components, organized by UI type.src/tui/constant/: non-copy constants reused across TUI modules — symbols, terminal sequences, render sizing, streaming-arg match rules, and so on.src/tui/components/chrome/: persistent UI chrome — footer, todo panel, welcome, loader, device code.src/tui/components/dialogs/: selectors, approval panels, question popups, and settings popups that temporarily replace the editor.src/tui/components/editor/: the custom input box and the file mention provider.src/tui/components/media/: image, diff, code highlight, and other media displays.src/tui/components/messages/: message blocks in the transcript — assistant, user, tool call, thinking, usage, subagent, and so on.src/tui/components/panes/: right-side / activity-area panes such as the activity pane and queue pane.src/tui/reverse-rpc/: the adapter layer that bridges SDK approval/question callbacks to the UI.src/tui/theme/: themes, color tokens, style helpers, terminal-background detection, and the pi-tui markdown theme.src/tui/utils/: TUI-only utility functions.src/utils/: app-wide utilities — clipboard, git, history, image, process, usage, and so on.
Module Responsibilities
clionly interprets command-line input, assembles startup arguments, and invokes the TUI. Do not put TUI interaction logic into the CLI.KimiTUIcoordinates; it does not accumulate complex business rules. New logic that can be tested independently should be split intocontrollers,commands,components,reverse-rpc, orutilsfirst.controllersown the heavy, independently-testable slices (event routing, streaming render, session replay, tasks browser, editor keyboard, auth). Event-routing and rendering logic belong here, not on theKimiTUIclass.commandsonly owns slash-command declaration, parsing, and the parsed-result types. The actual execution can be dispatched fromKimiTUI, but complex logic should continue to sink downward.componentsonly handle presentation and local interaction; they must not call the SDK directly, and must not read or write session state directly.reverse-rpcconverts SDK approval/question requests into the data shape a UI panel/dialog needs, and converts the user's choice back into an SDK response.themeis the single source of truth for colors and styles. Components must not bypass the theme system and use chalk named colors directly.utilsholds utility functions with no UI-state dependency. Logic that needsTUIStateor a component instance must not live under app-levelsrc/utils.apps/kimi-codemay only use core capabilities through@moonshot-ai/kimi-code-sdk. Do not import@moonshot-ai/agent-coredirectly in app code.
TUI Coding Conventions
- Do not over-encapsulate, especially for one- or two-line functions — do not introduce a two-layer wrapper, just inline.
- Functions with no state / UI side effects do not belong as private methods on the
KimiTUIclass; put them in external utils. - Constants must live in the corresponding
constantdirectory; they must not be scattered through component or logic code. - Inside
handleInput(data), when comparing a printable character (letter, digit, space, punctuation), it is forbidden to write literal comparisons such asdata === 'q'. With the Kitty keyboard protocol enabled in terminals like VSCode, these keys are sent as CSI-u sequences (e.g.\x1b[113u), and a bare comparison will never match. Decode withprintableChar(data)fromsrc/tui/utils/printable-key.tsfirst, then compare; function keys continue to usematchesKey(data, Key.*); control characters (codepoint < 32) may still be compared against the rawdata.test/tui/printable-key-guard.test.tsenforces this in CI.
Color Rules (normative)
The theme apply/switch mechanics live in the write-tui skill. The following rules are hard and guard-enforced:
- Do not use chalk named colors such as
chalk.red,chalk.cyan,chalk.white,chalk.gray,chalk.dim, orchalk.yellowdirectly. - If a component already has
colors, usechalk.hex(colors.<token>)(text). - If a component already has
state.theme.stylesor styles passed in, prefer helpers such asstyles.error(text),styles.dim(text). - When new visual semantics have no token, first add a semantic field to
ColorPalette, and fill in bothdarkColorsandlightColors. - In light themes, text tokens against a white background must be at least 4.5:1; borders and large chrome must be at least 3:1.
- Do not cache styled chalk functions at module top level. Theme switching must take effect within a single render, so styles must be generated on the render path from the current palette.
- Non-comment code must not contain chalk named colors such as
chalk.white,chalk.cyan,chalk.red,chalk.green,chalk.gray,chalk.yellow,chalk.blue,chalk.magenta,chalk.whiteBright, orchalk.blackBright.test/tui/chalk-named-color-guard.test.tsenforces this in CI.
General Coding Requirements
- For optional object properties, pass
undefineddirectly — do not use conditional spread. - Optional object properties do not need to additionally allow
undefinedin the type. - Internal methods with only a single parameter should not be turned into options objects just for stylistic uniformity.
- Except for a package's own
index.ts, otherindex.tsfiles should preferexport * from './module'.