InkdownInkdown
Start writing

Claude-Code

62 files·4 subfolders

Shared Workspace

Claude-Code
codex

17-vim-mode

Shared from "Claude-Code" on Inkdown

Vim Mode

Full vim-style editing in the terminal input.


Overview

A complete vim-mode state machine for the REPL input, supporting INSERT and NORMAL modes with operators, motions, text objects, count prefixes, and dot-repeat.


State Machine

Plain text
                    ┌─────────────────────────────────────┐
                    │           INSERT MODE               │
                    │                                     │
                    │  - Tracks inserted text (dot-repeat) │
                    │  - Normal typing                    │
                    │  - Press Escape → NORMAL MODE       │
                    └──────────────┬──────────────────────┘
                                   │ Escape
                                   ▼
                    ┌─────────────────────────────────────┐
                    │           NORMAL MODE               │
                    │                                     │
                    │  idle → operator → motion           │
                    │       → text object                 │
                    │       → find motion                 │
                    └─────────────────────────────────────┘
0000_start_here_index_and_recommended_reading_order.md
0100_project_overview_tech_stack_runtime_modes_and_folder_map.md
0200_startup_flow_entry_points_and_cold_start_sequence.md
0300_codebase_modules_layers_state_models_and_schemas.md
0400_system_architecture_and_design_rationale.md
0500_interactive_repl_request_flow_end_to_end.md
0600_headless_sdk_and_print_mode_request_flow_end_to_end.md
0700_mcp_integration_connection_and_tool_call_flow.md
0800_external_services_sdks_storage_and_local_dependencies.md
0900_environment_variables_settings_feature_flags_and_failure_modes.md
1000_non_obvious_patterns_gotchas_and_debugging_traps.md
1100_full_codebase_file_inventory_grouped_by_directory.md
kimi
00-overview.md
01-entrypoints.md
02-state-management.md
03-query-system.md
04-tools-system.md
05-tasks-system.md
06-ui-components.md
07-bridge-remote.md
08-services.md
09-skills-plugins.md
10-commands.md
11-testing-architecture.md
12-permission-system.md
13-build-system.md
14-ink-internals.md
15-git-internals.md
16-context-compaction.md
17-vim-mode.md
18-mailbox-notifications.md
19-session-persistence.md
20-hooks-system.md
21-error-recovery.md
README.md
qwen
00-overview.md
01-entry-points.md
02-query-engine.md
03-tools-and-tasks.md
04-commands-and-skills.md
05-state-management.md
06-ink-rendering.md
07-bridge-remote.md
08-mcp-services.md
09-services-overview.md
10-multi-agent.md
11-system-prompt-constants.md
12-tool-interface.md
13-memory-system.md
14-buddy-companion.md
15-keybindings.md
16-stop-hooks.md
17-vim-mode.md
18-upstreamproxy.md
19-cost-tracking-history.md
20-contexts-styles-onboarding.md
21-hooks.md
22-screens.md
tweets-explain
claude-code-memory-analysis.md
compact
memory-system
agentic-architecture

Modes

INSERT Mode
  • Tracks all inserted text for dot-repeat (.)
  • Normal typing behavior
  • Pressing Escape switches to NORMAL mode
NORMAL Mode

A command state machine:

Plain text
idle ──[d/c/y]──▶ operator ──[motion]──▶ execute
  │                    │
  │                    └──[f/F/t/T]──▶ find motion
  │                    │
  │                    └──[i/a]──▶ text object
  │
  ├──[count]──▶ count prefix
  │
  ├──[f/F/t/T]──▶ find motion
  │
  ├──[r]──▶ replace mode
  │
  └──[>]──▶ indent operator

Operators

OperatorAction
dDelete
cChange (delete + enter INSERT)
yYank (copy)
>Indent
<Dedent

Motions

Simple Motions
MotionAction
hLeft
jDown
kUp
lRight
wNext word
bPrevious word
eEnd of word
0Start of line
^First non-blank
$End of line
GEnd of buffer
Find Motions
MotionAction
f<char>Find char forward
F<char>Find char backward
t<char>Till char forward
T<char>Till char backward
;Repeat last find
,Reverse last find
Text Objects
ObjectInnerAround
Quotesi' / i"a' / a"
Parensi(a(
Bracketsi[a[
Bracesi{a{
Angle bracketsi<a<

Count Prefixes

Numbers before a command multiply its effect:

Plain text
3w    → move 3 words forward
2dd   → delete 2 lines
5j    → move 5 lines down

Persistent State

TypeScript
interface VimState {
  mode: 'insert' | 'normal'

  // For dot-repeat (.)
  lastChange: Change | null

  // For find repeat (;/,)
  lastFind: FindMotion | null

  // Register (for yank/put)
  register: string | null
}

Motion Resolution

resolveMotion() computes cursor positions without side effects:

TypeScript
function resolveMotion(state: VimState, motion: Motion, text: string): {
  start: number
  end: number
}

This pure function approach allows:

  • Preview before applying
  • Easy testing
  • No side effects during planning

Types (types.ts)

TypeScript
type Motion =
  | { type: 'simple'; key: string }
  | { type: 'find'; char: string; direction: 'forward' | 'backward' }
  | { type: 'textObject'; inner: boolean; object: string }

type Operator = 'delete' | 'change' | 'yank' | 'indent' | 'dedent'

type Command =
  | { type: 'motion'; motion: Motion }
  | { type: 'operator'; operator: Operator; motion: Motion }
  | { type: 'replace'; char: string }

Transitions (transitions.ts)

Handles state transitions:

TypeScript
function handleKey(key: string, state: VimState): VimState {
  switch (state.phase) {
    case 'idle':
      if (isOperator(key)) return { ...state, phase: 'operator', operator: key }
      if (isMotion(key)) return executeMotion(state, key)
      if (isCount(key)) return { ...state, phase: 'count', count: key }
      return state

    case 'operator':
      if (isMotion(key)) return executeOperator(state, key)
      if (isFind(key)) return { ...state, phase: 'find' }
      return state

    // ... etc
  }
}

Files

FilePurpose
src/vim/types.tsType definitions
src/vim/motions.tsMotion implementations
src/vim/operators.tsOperator implementations
src/vim/textObjects.tsText object definitions
src/vim/transitions.tsState machine transitions