kward 0.70.0 → 0.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/pages.yml +1 -1
  3. data/CHANGELOG.md +89 -3
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +90 -2
  6. data/README.md +34 -6
  7. data/Rakefile +96 -0
  8. data/doc/agent-tools.md +52 -0
  9. data/doc/api.md +92 -0
  10. data/doc/authentication.md +58 -23
  11. data/doc/code-search.md +42 -2
  12. data/doc/configuration.md +102 -13
  13. data/doc/context-budgeting.md +136 -0
  14. data/doc/context-tools.md +83 -0
  15. data/doc/editor.md +394 -0
  16. data/doc/extensibility.md +16 -7
  17. data/doc/files.md +100 -0
  18. data/doc/getting-started.md +25 -18
  19. data/doc/git.md +122 -0
  20. data/doc/memory.md +24 -4
  21. data/doc/personas.md +34 -5
  22. data/doc/plugins.md +74 -3
  23. data/doc/releasing.md +45 -8
  24. data/doc/rpc.md +77 -15
  25. data/doc/session-management.md +254 -0
  26. data/doc/shell.md +286 -0
  27. data/doc/tabs.md +122 -0
  28. data/doc/troubleshooting.md +77 -1
  29. data/doc/usage.md +60 -15
  30. data/doc/web-search.md +12 -4
  31. data/doc/workspace-tools.md +144 -0
  32. data/examples/plugins/space_invaders.rb +377 -0
  33. data/lib/kward/agent.rb +1 -1
  34. data/lib/kward/cli/commands.rb +41 -2
  35. data/lib/kward/cli/git.rb +150 -0
  36. data/lib/kward/cli/interactive_turn.rb +73 -9
  37. data/lib/kward/cli/openrouter_commands.rb +55 -0
  38. data/lib/kward/cli/plugins.rb +54 -4
  39. data/lib/kward/cli/prompt_interface.rb +111 -6
  40. data/lib/kward/cli/rendering.rb +11 -6
  41. data/lib/kward/cli/runtime_helpers.rb +133 -3
  42. data/lib/kward/cli/sessions.rb +262 -13
  43. data/lib/kward/cli/settings.rb +216 -37
  44. data/lib/kward/cli/slash_commands.rb +439 -8
  45. data/lib/kward/cli/tabs.rb +695 -0
  46. data/lib/kward/cli.rb +171 -26
  47. data/lib/kward/compactor.rb +4 -1
  48. data/lib/kward/config_files.rb +125 -5
  49. data/lib/kward/context_budget_meter.rb +44 -0
  50. data/lib/kward/conversation.rb +59 -22
  51. data/lib/kward/editor_mode.rb +25 -0
  52. data/lib/kward/ekwsh.rb +362 -0
  53. data/lib/kward/model/client.rb +37 -50
  54. data/lib/kward/model/context_usage.rb +13 -6
  55. data/lib/kward/model/model_info.rb +92 -16
  56. data/lib/kward/model/payloads.rb +2 -0
  57. data/lib/kward/openrouter_model_cache.rb +120 -0
  58. data/lib/kward/plugin_registry.rb +108 -1
  59. data/lib/kward/project_files.rb +52 -0
  60. data/lib/kward/prompt_history.rb +82 -0
  61. data/lib/kward/prompt_interface/banner.rb +16 -51
  62. data/lib/kward/prompt_interface/composer_controller.rb +124 -83
  63. data/lib/kward/prompt_interface/composer_renderer.rb +116 -14
  64. data/lib/kward/prompt_interface/composer_state.rb +96 -27
  65. data/lib/kward/prompt_interface/editor/auto_close_pairs.rb +123 -0
  66. data/lib/kward/prompt_interface/editor/auto_indent.rb +509 -0
  67. data/lib/kward/prompt_interface/editor/buffer.rb +109 -0
  68. data/lib/kward/prompt_interface/editor/controller.rb +1018 -0
  69. data/lib/kward/prompt_interface/editor/endwise.rb +321 -0
  70. data/lib/kward/prompt_interface/editor/file_marker.rb +40 -0
  71. data/lib/kward/prompt_interface/editor/indent_navigation.rb +61 -0
  72. data/lib/kward/prompt_interface/editor/kill_ring.rb +78 -0
  73. data/lib/kward/prompt_interface/editor/modes/emacs.rb +259 -0
  74. data/lib/kward/prompt_interface/editor/modes/modern.rb +353 -0
  75. data/lib/kward/prompt_interface/editor/modes/vibe.rb +1962 -0
  76. data/lib/kward/prompt_interface/editor/renderer.rb +243 -0
  77. data/lib/kward/prompt_interface/editor/search.rb +76 -0
  78. data/lib/kward/prompt_interface/editor/selections.rb +120 -0
  79. data/lib/kward/prompt_interface/editor/state.rb +1249 -0
  80. data/lib/kward/prompt_interface/editor/status_text.rb +23 -0
  81. data/lib/kward/prompt_interface/editor/syntax_highlighter.rb +420 -0
  82. data/lib/kward/prompt_interface/editor/undo_history.rb +46 -0
  83. data/lib/kward/prompt_interface/editor/vibe_state.rb +44 -0
  84. data/lib/kward/prompt_interface/file_overlay.rb +211 -0
  85. data/lib/kward/prompt_interface/git_prompt.rb +299 -0
  86. data/lib/kward/prompt_interface/interactive/controller.rb +186 -0
  87. data/lib/kward/prompt_interface/interactive/renderer.rb +71 -0
  88. data/lib/kward/prompt_interface/interactive/state.rb +62 -0
  89. data/lib/kward/prompt_interface/key_handler.rb +416 -43
  90. data/lib/kward/prompt_interface/layout.rb +2 -2
  91. data/lib/kward/prompt_interface/overlay_renderer.rb +21 -2
  92. data/lib/kward/prompt_interface/project_browser.rb +524 -0
  93. data/lib/kward/prompt_interface/prompt_renderer.rb +32 -13
  94. data/lib/kward/prompt_interface/question_prompt.rb +122 -82
  95. data/lib/kward/prompt_interface/runtime_state.rb +49 -1
  96. data/lib/kward/prompt_interface/screen.rb +17 -0
  97. data/lib/kward/prompt_interface/selection_prompt.rb +511 -58
  98. data/lib/kward/prompt_interface/stream_state.rb +7 -0
  99. data/lib/kward/prompt_interface/transcript_buffer.rb +13 -16
  100. data/lib/kward/prompt_interface/transcript_renderer.rb +3 -3
  101. data/lib/kward/prompt_interface.rb +307 -35
  102. data/lib/kward/prompts/commands.rb +7 -1
  103. data/lib/kward/prompts.rb +4 -2
  104. data/lib/kward/rpc/server.rb +45 -11
  105. data/lib/kward/rpc/session_manager.rb +52 -53
  106. data/lib/kward/rpc/session_tree_rows.rb +9 -115
  107. data/lib/kward/rpc/tool_event_normalizer.rb +1 -1
  108. data/lib/kward/session_store.rb +67 -4
  109. data/lib/kward/session_tree_nodes.rb +136 -0
  110. data/lib/kward/session_tree_renderer.rb +9 -131
  111. data/lib/kward/tab_store.rb +47 -0
  112. data/lib/kward/telemetry/logger.rb +5 -3
  113. data/lib/kward/text_boundary.rb +25 -0
  114. data/lib/kward/tool_output_compactor.rb +127 -0
  115. data/lib/kward/tools/base.rb +8 -2
  116. data/lib/kward/tools/context_budget_stats.rb +54 -0
  117. data/lib/kward/tools/context_for_task.rb +202 -0
  118. data/lib/kward/tools/read_file.rb +8 -4
  119. data/lib/kward/tools/registry.rb +92 -15
  120. data/lib/kward/tools/retrieve_tool_output.rb +71 -0
  121. data/lib/kward/tools/search/web.rb +2 -2
  122. data/lib/kward/tools/summarize_file_structure.rb +29 -0
  123. data/lib/kward/tools/tool_call.rb +12 -0
  124. data/lib/kward/version.rb +1 -1
  125. data/lib/kward/workers/git_guard.rb +68 -0
  126. data/lib/kward/workers/live_view.rb +49 -0
  127. data/lib/kward/workers/manager.rb +288 -0
  128. data/lib/kward/workers/store.rb +72 -0
  129. data/lib/kward/workers/tool_policy.rb +23 -0
  130. data/lib/kward/workers/worker.rb +82 -0
  131. data/lib/kward/workers/write_lock.rb +38 -0
  132. data/lib/kward/workers.rb +7 -0
  133. data/lib/kward/workspace.rb +154 -12
  134. data/templates/default/fulldoc/html/css/kward.css +362 -42
  135. data/templates/default/fulldoc/html/full_list.erb +107 -0
  136. data/templates/default/fulldoc/html/js/kward.js +161 -2
  137. data/templates/default/fulldoc/html/setup.rb +8 -0
  138. data/templates/default/kward_navigation.rb +102 -0
  139. data/templates/default/layout/html/layout.erb +43 -10
  140. data/templates/default/layout/html/setup.rb +39 -38
  141. metadata +65 -3
  142. data/lib/kward/resources/avatar_kward_logo.rb +0 -50
  143. data/lib/kward/resources/pixel_logo.rb +0 -232
@@ -12,7 +12,9 @@ Or inside interactive Kward:
12
12
  /login
13
13
  ```
14
14
 
15
- Use the provider you already have access to. You can change providers later.
15
+ `/login` opens a provider picker; `kward login` accepts the provider as an argument.
16
+
17
+ Use the provider you already have access to. You can change the active model later with `/model`.
16
18
 
17
19
  ## Choose a provider
18
20
 
@@ -34,8 +36,6 @@ kward login openrouter # OpenRouter API key
34
36
  kward login github # GitHub OAuth for experimental Copilot support
35
37
  ```
36
38
 
37
- From source, replace `kward` with `ruby lib/main.rb`.
38
-
39
39
  ## OpenAI / ChatGPT
40
40
 
41
41
  ```bash
@@ -58,6 +58,14 @@ If Kward asks for an OAuth client ID, add it to `~/.kward/config.json`:
58
58
  }
59
59
  ```
60
60
 
61
+ Kward ships with a built-in client ID, so this is only needed if login fails or you want to use your own.
62
+
63
+ For a single shell session without OAuth, you can set an access token directly:
64
+
65
+ ```bash
66
+ OPENAI_ACCESS_TOKEN=... kward
67
+ ```
68
+
61
69
  ## Anthropic Claude Pro/Max
62
70
 
63
71
  ```bash
@@ -88,6 +96,37 @@ OPENROUTER_API_KEY=sk-or-v1-... kward
88
96
 
89
97
  Choose OpenRouter when you want access to its model catalog or want provider/model selection through an API key.
90
98
 
99
+ ### Refresh the OpenRouter model cache
100
+
101
+ Kward's `/model` picker can show OpenRouter models that are available to your API key. Refresh the local cache after logging in:
102
+
103
+ ```bash
104
+ kward openrouter refresh
105
+ ```
106
+
107
+ This fetches text-capable OpenRouter models for the configured key and writes them to:
108
+
109
+ ```text
110
+ ~/.kward/cache/openrouter_models.json
111
+ ```
112
+
113
+ If `KWARD_CONFIG_PATH` points at a custom config file, the cache is written beside that config file under `cache/openrouter_models.json`.
114
+
115
+ Inspect the cached model ids with:
116
+
117
+ ```bash
118
+ kward openrouter list
119
+ ```
120
+
121
+ Use this when:
122
+
123
+ - you added or changed your OpenRouter API key,
124
+ - OpenRouter added new models,
125
+ - your model picker does not show the model you expect,
126
+ - you want Kward to use current context-window metadata from OpenRouter.
127
+
128
+ After refreshing, start Kward and choose the model with `/model`.
129
+
91
130
  ## Experimental Copilot support
92
131
 
93
132
  ```bash
@@ -108,34 +147,29 @@ COPILOT_GITHUB_TOKEN=... kward
108
147
 
109
148
  Copilot support is experimental and uses direct HTTPS calls to the Copilot proxy API. It does not use the official Copilot CLI or SDK runtime.
110
149
 
111
- ## Which credential wins?
150
+ ## Choose the active model
112
151
 
113
- If multiple credentials are available, Kward uses the configured provider.
152
+ Authentication makes providers available. The active model is selected separately.
114
153
 
115
- Set it in `~/.kward/config.json`:
154
+ Inside Kward, use:
116
155
 
117
- ```json
118
- {
119
- "provider": "anthropic"
120
- }
156
+ ```text
157
+ /model
121
158
  ```
122
159
 
123
- Or for one command:
160
+ The model picker is the normal way to switch between configured providers and models. You can keep credentials for multiple providers and choose the model you want for the current work.
124
161
 
125
- ```bash
126
- KWARD_PROVIDER=openrouter kward
127
- ```
162
+ For one-off shell runs, `KWARD_PROVIDER` and provider-specific model environment variables remain available. See [Configuration](configuration.md) for the full list.
128
163
 
129
- Supported provider values:
164
+ ## Custom auth file locations
130
165
 
131
- ```text
132
- codex
133
- anthropic
134
- openrouter
135
- copilot
136
- ```
166
+ Each auth file has an environment variable override, useful for isolated or multi-account setups. When unset, they default to the paths shown above under `~/.kward/`.
167
+
168
+ - `KWARD_AUTH_PATH` — OpenAI OAuth credentials (`auth.json`)
169
+ - `KWARD_ANTHROPIC_AUTH_PATH` — Anthropic OAuth credentials (`anthropic_auth.json`)
170
+ - `KWARD_GITHUB_AUTH_PATH` — GitHub OAuth credentials (`github_auth.json`)
137
171
 
138
- Without an explicit provider, OpenAI/ChatGPT credentials are preferred when present.
172
+ When `KWARD_CONFIG_PATH` points at a custom config file, the OpenRouter API key is stored in that file instead of `~/.kward/config.json`.
139
173
 
140
174
  ## Security notes
141
175
 
@@ -143,4 +177,5 @@ Without an explicit provider, OpenAI/ChatGPT credentials are preferred when pres
143
177
  - Do not commit `~/.kward/config.json` or auth files.
144
178
  - Prefer environment variables for temporary credentials.
145
179
  - `kward auth status` shows credential status without printing secrets.
146
- - `kward auth logout` removes saved credentials.
180
+ - `kward auth logout` removes **all** saved credentials at once: every OAuth file (OpenAI, Anthropic, GitHub) and the stored OpenRouter API key. There is no per-provider logout; to remove a single provider, delete its auth file by hand.
181
+ - `kward doctor` reports which credentials are currently configured alongside other local checks.
data/doc/code-search.md CHANGED
@@ -31,6 +31,18 @@ The `code_search` tool can:
31
31
 
32
32
  Kward should use this when the best answer depends on how another project actually implemented something.
33
33
 
34
+ ## Supported ecosystems
35
+
36
+ `package_search` and `github_search` accept an `ecosystem` parameter to narrow results:
37
+
38
+ - `rubygems` — RubyGems
39
+ - `npm` — npm registry
40
+ - `pypi` — Python Package Index
41
+ - `crates` — crates.io (Rust)
42
+ - `go` — Go module documentation
43
+
44
+ When omitted, `package_search` requires a `package` name and infers the registry from the ecosystem. `github_search` uses the ecosystem as an optional hint alongside the search query.
45
+
34
46
  ## Cache location
35
47
 
36
48
  Repositories are cached outside your workspace:
@@ -63,7 +75,7 @@ or:
63
75
  GH_TOKEN=...
64
76
  ```
65
77
 
66
- Tokens are used for GitHub API requests and are not included in tool output.
78
+ Tokens are used for GitHub API requests and are not included in tool output. See [Configuration](configuration.md) for the full environment variable reference.
67
79
 
68
80
  ## Tool actions
69
81
 
@@ -80,4 +92,32 @@ The tool uses an `action` parameter:
80
92
  | `refresh_cache` | fetch updates for a cached repository. |
81
93
  | `clear_cache` | remove a cached repository. |
82
94
 
83
- Search and read results are bounded so Kward does not load large external repositories into context by accident. Oversized and binary files are skipped.
95
+ ### Action arguments
96
+
97
+ | Action | Required arguments | Optional arguments |
98
+ | --- | --- | --- |
99
+ | `package_search` | `ecosystem`, `package` | — |
100
+ | `github_search` | `query` | `ecosystem`, `max_results` |
101
+ | `repo_clone` | `repo` | — |
102
+ | `repo_search` | `repo`, `query` | `max_results`, `context_lines` |
103
+ | `repo_read` | `repo`, `path` | `start_line`, `line_count` |
104
+ | `list_cache` | — | — |
105
+ | `refresh_cache` | `repo` | — |
106
+ | `clear_cache` | `repo` | — |
107
+
108
+ - `repo` is a GitHub URL or `owner/name`.
109
+ - `query` is a plain-text search string (not regex). Matching is case-sensitive substring.
110
+ - `start_line` is 1-indexed.
111
+ - `context_lines` controls how many lines before and after a match are included in search snippets.
112
+
113
+ ## Limits
114
+
115
+ Search and read results are bounded so Kward does not load large external repositories into context by accident:
116
+
117
+ - Search results: default 10 per query, max 50.
118
+ - Context lines in search snippets: default 2, max 5.
119
+ - Lines returned by `repo_read`: default 200, max 400.
120
+ - File size limit: 512 KB. Files larger than this are skipped during search and rejected on read.
121
+ - Scanned files in `repo_search`: max 5,000 files per scan. Files in `.git` directories, symlinks, files outside the repo root, and oversized files are skipped. Binary files fail gracefully via encoding detection and are skipped.
122
+ - Output truncation: 16 KB total per tool result.
123
+ - HTTP timeout: 10 seconds for all network requests.
data/doc/configuration.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Kward reads user configuration from `~/.kward/config.json` by default. Most users do not need to edit this file by hand at first: use `/login`, `/model`, `/reasoning`, and `/settings` from inside Kward when possible.
4
4
 
5
- On first start, if the file does not exist, Kward creates a starter config with an active Kward persona, explicit disabled memory settings, and the default composer busy-help setting so you can inspect and edit them. Provider-specific model defaults are added only when you choose a provider/model. If `KWARD_CONFIG_PATH` is set, Kward uses that file instead and treats that file's directory as the config directory for prompts, skills, memory, logs, and caches.
5
+ On first start, if the file does not exist, Kward creates a starter config with an active Kward persona, explicit disabled memory settings, and the default composer busy-help setting so you can inspect and edit them. Provider-specific model defaults are added only when you choose a provider/model. See [Personas](personas.md) for configuring persona selection by workspace, model, or reasoning effort. If `KWARD_CONFIG_PATH` is set, Kward uses that file instead and treats that file's directory as the config directory for prompts, skills, memory, logs, and caches.
6
6
 
7
7
  Small examples:
8
8
 
@@ -34,9 +34,31 @@ By default, Kward stores user data under `~/.kward`:
34
34
  ~/.kward/memory/
35
35
  ~/.kward/logs/
36
36
  ~/.kward/cache/
37
+ ~/.kward/plugins/
37
38
  ```
38
39
 
39
- When `KWARD_CONFIG_PATH=/path/to/config.json` is set, most config-related files live beside that file instead. User plugins are the exception: they are loaded only from `~/.kward/plugins`.
40
+ When `KWARD_CONFIG_PATH=/path/to/config.json` is set, most config-related files live beside that file instead. User plugins are the exception: they are loaded only from `~/.kward/plugins`. See [Plugins](plugins.md) for writing and loading user plugins.
41
+
42
+ ## Embedded shell config
43
+
44
+ The embedded Kward shell (`/shell`, internally `ekwsh`) reads optional global settings from `~/.kward/ekwsh.yml` or, when `KWARD_CONFIG_PATH` is set, from `ekwsh.yml` beside that config file.
45
+
46
+ Example:
47
+
48
+ ```yaml
49
+ env:
50
+ FORCE_COLOR: "1"
51
+ CLICOLOR_FORCE: "1"
52
+
53
+ aliases:
54
+ ll: "ls -la"
55
+ gs: "git status --short"
56
+ gd: "git diff --color=always"
57
+ ```
58
+
59
+ `env` values are applied when shell mode starts, after Kward's conservative color defaults. Keys must look like environment variable names (`A_Z`, digits after the first character, and underscores); invalid keys are ignored. Values are converted to strings.
60
+
61
+ `aliases` expand the first word of a command once. For example, `ll lib` runs `ls -la lib`. Built-in `ekwsh` commands such as `cd`, `pwd`, `export`, `unset`, `alias`, `clear`, and `exit` take precedence over aliases. Run `alias` inside `ekwsh` to list configured aliases. Aliases are also included in command-name Tab completion.
40
62
 
41
63
  ## Provider and model settings
42
64
 
@@ -48,6 +70,8 @@ Set `provider` to choose the active backend:
48
70
  }
49
71
  ```
50
72
 
73
+ When `provider` is unset, Kward infers the backend from available credentials, defaulting to OpenAI/Codex when OAuth credentials are present. Set `provider` or `KWARD_PROVIDER` to select another backend explicitly.
74
+
51
75
  Supported values are:
52
76
 
53
77
  - `codex` for the OpenAI/ChatGPT Codex backend.
@@ -73,7 +97,7 @@ Model settings:
73
97
  }
74
98
  ```
75
99
 
76
- `model` is a generic setting for the active provider. Provider-specific values such as `openai_model`, `anthropic_model`, `openrouter_model`, and `copilot_model` take precedence for their provider. `reasoning_effort` and `thinking_level` are generic reasoning settings. `openai_reasoning_effort`, `anthropic_reasoning_effort`, `openrouter_reasoning_effort`, and `copilot_reasoning_effort` are provider-specific forms.
100
+ `model` is a generic setting for the active provider. Provider-specific values such as `openai_model`, `anthropic_model`, `openrouter_model`, and `copilot_model` take precedence for their provider. `reasoning_effort` and `thinking_level` are generic reasoning settings. `thinking_level` is an alias for `reasoning_effort` honored by all providers. For each provider, Kward resolves reasoning in this order: the provider-specific key (for example `openai_reasoning_effort`), then the generic `reasoning_effort`, then `thinking_level`, then the default `medium`. `openai_reasoning_effort`, `anthropic_reasoning_effort`, `openrouter_reasoning_effort`, and `copilot_reasoning_effort` are provider-specific forms.
77
101
 
78
102
  Defaults:
79
103
 
@@ -83,7 +107,7 @@ Defaults:
83
107
  - Copilot: `gpt-5-mini`
84
108
  - Reasoning effort: `medium`
85
109
 
86
- The interactive `/model` picker prefers OpenRouter models available to the configured API key when Kward can fetch them. `/openrouter/catalog` and RPC `openrouter/catalog` list the full OpenRouter catalog separately.
110
+ The interactive `/model` picker reads cached OpenRouter models when available. Run `kward openrouter refresh` to fetch text-capable models available to the configured OpenRouter API key and cache them under `~/.kward/cache/openrouter_models.json`. Run `kward openrouter list` to inspect the cached model ids.
87
111
 
88
112
  ## Environment overrides
89
113
 
@@ -148,33 +172,98 @@ Overlay settings control terminal picker/card layout:
148
172
 
149
173
  You can change these interactively with `/settings`.
150
174
 
151
- ## Banner settings
175
+ ## Composer settings
152
176
 
153
- The interactive terminal banner shows the avatar Kward logo and the “State your business.” message by default. To hide the full banner:
177
+ The busy composer shows a short Ctrl+C cancellation hint by default. To hide it:
154
178
 
155
179
  ```json
156
180
  {
157
- "banner": {
158
- "enabled": false
181
+ "composer": {
182
+ "busy_help": false
159
183
  }
160
184
  }
161
185
  ```
162
186
 
163
- This only affects the interactive terminal UI.
187
+ This only hides the hint text; Ctrl+C still stops the current running response.
164
188
 
165
- ## Composer settings
189
+ In the normal composer prompt, `Tab` cycles forward through the current model's reasoning efforts and `Shift+Tab` cycles backward. The shortcuts wrap around and update the persisted reasoning setting; file and slash-command completion overlays keep their existing `Tab` completion behavior.
166
190
 
167
- The busy composer shows a short Ctrl+C cancellation hint by default. To hide it:
191
+ `tab_keybindings` controls how the composer handles tab navigation shortcuts:
168
192
 
169
193
  ```json
170
194
  {
171
195
  "composer": {
172
- "busy_help": false
196
+ "tab_keybindings": "auto"
173
197
  }
174
198
  }
175
199
  ```
176
200
 
177
- This only hides the hint text; Ctrl+C still stops the current running response.
201
+ `auto` (default) detects terminal support, `ctrl` uses `Ctrl+Tab`/`Shift+Tab` to cycle suggestions and indent, `alt` uses `Alt+Tab` for terminals where `Ctrl+Tab` is swallowed.
202
+
203
+ ## Editor settings
204
+
205
+ The built-in TUI file editor supports three keybinding modes. Modern is the default:
206
+
207
+ ```json
208
+ {
209
+ "editor": {
210
+ "mode": "modern"
211
+ }
212
+ }
213
+ ```
214
+
215
+ `mode` can be `modern`, `emacs`, or `vibe`. The old `default` value is still accepted as an alias for `modern`. You can change this from `/settings` > Interface > Editor mode; newly opened editor buffers pick up the setting immediately.
216
+
217
+ The editor automatically highlights Ruby, Crystal, Elixir, Julia, JavaScript, TypeScript, JSON, Markdown, YAML, Shell, Makefile, HTML, CSS, SCSS, Python, Go, Rust, Java, C#, C, C++, Swift, Kotlin, Lua, and SQL files when terminal color is enabled. Unknown file types and color-disabled terminals render plain text.
218
+
219
+ Auto-indent is enabled by default. Pressing Enter copies the current line indentation, detects the file's indentation unit when possible, and applies lightweight syntax-based indentation for recognized file types. For Ruby, Crystal, Elixir, Julia, Lua, Makefiles, and shell scripts, Enter after a block opener inserts the matching closing keyword, and Ctrl+Enter can force that behavior from the middle of the line in terminals that report modified Enter keys. When auto-indent is enabled, typing obvious closing tokens such as `}`, Ruby/Lua `end`, and shell `fi`/`done`/`esac` re-indents the current line, and Backspace in leading indentation removes one detected indentation unit. To disable it:
220
+
221
+ ```json
222
+ {
223
+ "editor": {
224
+ "auto_indent": false,
225
+ "auto_close_pairs": false
226
+ }
227
+ }
228
+ ```
229
+
230
+ `auto_indent` and `auto_close_pairs` both default to `true`. Set `auto_close_pairs` to `false` to disable automatic insertion of matching `()`, `[]`, `{}`, quotes, and backticks.
231
+
232
+ Line numbers are absolute by default. Set `line_numbers` to `relative` to show distances from the cursor line in editable buffers while keeping the current cursor line absolute:
233
+
234
+ ```json
235
+ {
236
+ "editor": {
237
+ "line_numbers": "relative"
238
+ }
239
+ }
240
+ ```
241
+
242
+ Soft-wrap is enabled by default so long lines wrap within the editor width instead of scrolling. To disable it:
243
+
244
+ ```json
245
+ {
246
+ "editor": {
247
+ "soft_wrap": false
248
+ }
249
+ }
250
+ ```
251
+
252
+ Editable editor buffers request a vertical bar cursor by default. Terminals that do not support cursor-shape escape sequences ignore this. To keep the terminal's normal cursor shape while editing:
253
+
254
+ ```json
255
+ {
256
+ "editor": {
257
+ "bar_cursor": false
258
+ }
259
+ }
260
+ ```
261
+
262
+ Modern mode uses composer-style keys: `Ctrl+S` saves, `Ctrl+Q` quits, `Ctrl+F` searches, Shift+Arrow selects text, `Ctrl+C` copies, `Ctrl+X` cuts, `Ctrl+V` pastes the editor kill buffer, `Ctrl+A`/`Ctrl+E` move to the start/end of the line, `Ctrl+B` moves left, `Ctrl+K` kills to end of line, `Ctrl+U` kills to start of line, and `Alt+B`/`Alt+F` move by word.
263
+
264
+ Emacs mode uses Emacs-style non-modal keys: `Ctrl+X Ctrl+S` saves, `Ctrl+X Ctrl+C` quits, `Ctrl+S` searches forward, `Ctrl+R` searches backward, `Ctrl+Space` sets the mark, `Ctrl+W` kills the region or previous word, `Alt+W` copies the region, `Ctrl+K` kills to end of line, `Ctrl+Y` yanks, and `Alt+Y` cycles the per-buffer kill ring after a yank.
265
+
266
+ Vibe mode opens files in normal mode and supports a compact classic-vibe subset: normal/insert/command modes, character and line visual modes with `v`/`V`, `h/j/k/l`, word and line movement, counts, simple `d`/`y` operator motions, `dd`, `yy`, `p`, `/` search, `u` undo, and `:w`, `:q`, `:q!`, `:wq`, `:x`, and `:number` commands. Yanks also copy to the terminal clipboard when OSC 52 is supported.
178
267
 
179
268
  ## Session settings
180
269
 
@@ -0,0 +1,136 @@
1
+ # Context budgeting and token savings
2
+
3
+ Kward tries to keep the model's context focused. Instead of reading whole files and pasting every byte of command output back into the conversation, it gathers evidence in small steps, compacts noisy output, and keeps the original data available when needed.
4
+
5
+ This page summarizes the token-saving work in Kward: what existed before, what the newer focused-context tools add, and how those pieces fit together during normal agent work.
6
+
7
+ ## Why this matters
8
+
9
+ Coding agents spend a lot of tokens just finding the right code. A single broad file read, failed test run, or web fetch can add thousands of tokens to the next model call. That makes sessions slower, more expensive, and more likely to lose the useful details in noise.
10
+
11
+ Kward's goal is not to build a heavyweight semantic index. It is to stay lightweight and local while giving the agent a disciplined path:
12
+
13
+ ```text
14
+ find likely files -> inspect outlines/previews -> read exact ranges -> read full files only when needed
15
+ ```
16
+
17
+ ## The current workflow
18
+
19
+ When Kward needs code context, it should usually start with one of these tools:
20
+
21
+ - `context_for_task` for a compact task-shaped bundle.
22
+ - `summarize_file_structure` for a source outline of one file.
23
+ - `read_file` with `mode: "outline"` or `mode: "preview"`.
24
+
25
+ Then it can escalate only as needed:
26
+
27
+ - `read_file` with `mode: "range"`, `offset`, and `limit` for exact sections.
28
+ - `read_file` with `mode: "full"` only when focused context is not enough.
29
+
30
+ The built-in system prompt tells Kward to follow that escalation path, so these tools are part of normal agent behavior rather than hidden manual features.
31
+
32
+ ## Focused task context
33
+
34
+ `context_for_task` is the highest-level context-budgeting tool. Give it a task and, optionally, focused paths and a byte budget. It returns a compact text bundle with:
35
+
36
+ - ranked candidate files (by term-matching score),
37
+ - source outlines for each file,
38
+ - matching excerpts around task terms (2 lines of context),
39
+ - a header with the task, budget, and search terms used.
40
+
41
+ Tool arguments:
42
+
43
+ ```json
44
+ {
45
+ "task": "debug token validation failure",
46
+ "paths": ["lib"],
47
+ "budget": 4000
48
+ }
49
+ ```
50
+
51
+ - `task` is required.
52
+ - `paths` is optional; defaults to the workspace root. Each entry is a file or directory.
53
+ - `budget` is optional; defaults to 4,000 bytes, max 20,000.
54
+
55
+ Limits: at most 8 ranked files are returned, with up to 8 matching excerpts per file. Up to 64 files are scanned. Skipped directories include `.git`, `node_modules`, `vendor`, `tmp`, `log`, `coverage`, `dist`, `build`, `.bundle`, `.yardoc`, and `_yardoc`. Only files with known extensions (`.rb`, `.js`, `.ts`, `.py`, `.go`, `.rs`, `.java`, `.cs`, `.md`, `.yml`, `.json`, etc.) plus `Gemfile` are considered.
56
+
57
+ This is useful when Kward needs orientation before choosing exact files or line ranges. It is intentionally lightweight: no daemon, no database, no persistent graph, and no semantic/vector index.
58
+
59
+ ## Budgeted file reads
60
+
61
+ `read_file` supports explicit context modes:
62
+
63
+ | Mode | Use it when |
64
+ | --- | --- |
65
+ | `outline` | You need a source declaration outline (classes, modules, methods, functions) with line numbers before reading code. Capped at 80 entries. |
66
+ | `preview` | You want a short first look. Defaults to 120 lines when no `limit` is given. Respects `offset` and `limit` if provided. |
67
+ | `range` | You know the relevant line range. Uses `offset` and `limit` to read a specific section. |
68
+ | `full` | You need the full file content up to Kward's read caps. Functionally identical to `range` but signals full-read intent. |
69
+
70
+ `range` and `full` behave the same: both read a bounded slice using `offset`, `limit`, and `max_bytes`. The difference is semantic — use `full` when you want everything up to the cap, use `range` when you are targeting a section.
71
+
72
+ `read_file` also accepts `max_bytes`, which lets Kward request a smaller per-call byte budget. This can only reduce the output below the workspace default (50 KB); it cannot increase it.
73
+
74
+ Large source files still get special handling when read without a mode: Kward returns an outline plus the first 120 lines instead of blindly flooding context. See [Workspace tools](workspace-tools.md) for the full `read_file` argument reference and read limits.
75
+
76
+ ## Source outlines
77
+
78
+ `summarize_file_structure` and `read_file` with `mode: "outline"` return compact source outlines. These include recognizable declarations, declaration kind, indentation, and approximate line ranges.
79
+
80
+ The outline recognizer is deliberately simple. It uses lightweight patterns for common Ruby, JavaScript/TypeScript, Go, Rust, Java, and C#-style declarations. It is not a compiler or LSP replacement, but it is fast and dependency-free. See [Workspace tools](workspace-tools.md) for argument details.
81
+
82
+ ## Output compaction
83
+
84
+ Kward also saves tokens after tools run.
85
+
86
+ When a tool output is large enough, Kward compacts it before sending it back into model context. The original output is kept in the session record and can be reopened with `retrieve_tool_output`, including after resuming a saved session that contains the original tool execution record.
87
+
88
+ The compactor preserves:
89
+
90
+ - the first 40 lines,
91
+ - the last 40 lines,
92
+ - error, failure, test, search-result, URL, and heading context,
93
+ - separate STDOUT/STDERR sections for shell commands.
94
+
95
+ This is especially useful for commands like test runs, linters, package installs, and large fetches. The model sees the useful parts first, but the full output is not lost. See [Agent tools](agent-tools.md) for the full compaction strategy and artifact retrieval details.
96
+
97
+ ## Duplicate output reuse
98
+
99
+ If the same tool output appears again, Kward does not repeat it in model context. Instead, it inserts a short reference to the already-stored artifact.
100
+
101
+ That helps when commands or searches are retried and return the same large result.
102
+
103
+ ## Session compaction
104
+
105
+ Kward also supports conversation/session compaction. This is separate from tool-output compaction: instead of trimming one tool result, it summarizes older conversation state so a long session can continue with less context pressure.
106
+
107
+ Session compaction keeps the working conversation manageable while preserving the session history on disk. Run `/compact` manually, or enable auto-compaction in config — see [Session management](session-management.md) and [Configuration](configuration.md).
108
+
109
+ ## Measuring savings
110
+
111
+ Use `context_budget_stats` to see approximate savings for the current active conversation since it was opened in this process. These runtime stats are not reconstructed when a saved session is resumed.
112
+
113
+ It reports:
114
+
115
+ - tool calls counted,
116
+ - original bytes,
117
+ - model-facing returned bytes,
118
+ - saved bytes,
119
+ - estimated tokens saved,
120
+ - per-tool breakdown with `calls`, `savedBytes`, `returnedBytes`, and `originalBytes` for each tool.
121
+
122
+ The token estimate is intentionally rough, using about four bytes per token. It is meant to show whether context budgeting is helping, not to match provider billing exactly. See [Workspace tools](workspace-tools.md) for the tool reference.
123
+
124
+ ## Practical example
125
+
126
+ A good debugging flow looks like this:
127
+
128
+ ```text
129
+ User: Debug why auth token validation fails.
130
+ Kward: context_for_task(task: "debug auth token validation", paths: ["lib", "test"], budget: 5000)
131
+ Kward: read_file(path: "lib/auth.rb", mode: "range", offset: 40, limit: 80)
132
+ Kward: run_shell_command(command: "ruby -Itest test/test_auth.rb")
133
+ Kward: retrieve_tool_output(...) only if the compacted test output omitted something important.
134
+ ```
135
+
136
+ That gives the model enough evidence to work without reading the whole repository or stuffing every command byte into the next request.
@@ -0,0 +1,83 @@
1
+ # Context tools
2
+
3
+ Context tools help Kward load reusable instructions, recover compacted tool output, and ask structured clarification questions. These tools usually run in the background as part of a turn rather than as commands you type directly.
4
+
5
+ ## `read_skill`
6
+
7
+ `read_skill` loads configured skill instructions when a task matches a known skill.
8
+
9
+ Arguments:
10
+
11
+ - `name`: skill name.
12
+ - `path`: optional path inside the skill, default `SKILL.md`.
13
+
14
+ Skill file paths must be relative and stay inside the skill folder. Absolute paths and path traversal are rejected. Files larger than 100 KB are also rejected.
15
+
16
+ Skills are reusable instruction bundles stored in the Kward config directory. Kward advertises available skills by name and description, then reads the full skill only when it becomes relevant. That saves tokens because every skill does not need to be injected into every request.
17
+
18
+ Typical uses:
19
+
20
+ - loading test-writing guidance before changing tests,
21
+ - loading security guidance before editing auth, secrets, cookies, uploads, or personal data handling,
22
+ - loading language-specific style guidance before refactoring code.
23
+
24
+ See [Extensibility](extensibility.md) for how skills fit with prompts, personas, and project instructions.
25
+
26
+ ## `retrieve_tool_output`
27
+
28
+ `retrieve_tool_output` reopens original output that was compacted out of the model-facing context.
29
+
30
+ Arguments:
31
+
32
+ - `id`: tool output artifact id, such as `toolout_abc123`.
33
+ - `offset`: optional 1-indexed line offset.
34
+ - `limit`: optional maximum lines to return, default 120.
35
+ - `query`: optional case-insensitive text search within the original output.
36
+
37
+ Kward may compact large shell, search, fetch, or file outputs before sending them back to the model. The compacted result includes enough summary to continue, plus an artifact id when the original output is worth preserving. If later work needs details, Kward can retrieve a focused slice of the original output instead of asking the tool to repeat the whole operation, including after resuming a saved session that contains the original tool execution record.
38
+
39
+ This saves tokens in two ways:
40
+
41
+ - repeated large outputs are not resent to the model,
42
+ - follow-up reads can target only matching lines or a bounded line range.
43
+
44
+ When a `query` is provided, matching lines are returned with 1-indexed line numbers prefixed. The result includes a header with the artifact id, query, and line range. When there are more results than the limit, a continuation notice with the next `offset` is included.
45
+
46
+ For details on how tool outputs are compacted and when artifacts are created, see [Agent tools](agent-tools.md).
47
+
48
+ ## `ask_user_question`
49
+
50
+ `ask_user_question` asks one to four structured clarification questions through an interactive frontend.
51
+
52
+ Arguments:
53
+
54
+ - `questions`: array of one to four questions.
55
+ - each question has:
56
+ - `header`: short label shown in the overlay,
57
+ - `question`: the question text,
58
+ - `options`: two to four selectable answers with `label` and `description`.
59
+
60
+ Constraints:
61
+
62
+ - `multiSelect` is unsupported; questions are single-select.
63
+ - `preview` on options is unsupported.
64
+ - Each option requires both `label` and `description`.
65
+ - In terminal use, the picker also accepts custom typed answers beyond the provided options, so the user is not limited to the listed choices.
66
+
67
+ This tool is advertised only when the active frontend supports structured questions. In terminal use, it lets Kward ask concise multiple-choice questions instead of guessing requirements. In RPC clients, the same question flow is bridged through UI events — see the [RPC question bridge](rpc.md) for notification and response details.
68
+
69
+ Good uses:
70
+
71
+ - choosing between safe implementation approaches,
72
+ - confirming an ambiguous scope,
73
+ - selecting a provider, model, or behavior when no default is obvious.
74
+
75
+ Kward should not use this tool for every small uncertainty. It is best when an answer materially changes the implementation or avoids a risky assumption.
76
+
77
+ ## Availability
78
+
79
+ `Kward::ToolRegistry` only advertises context tools when they are usable:
80
+
81
+ - `read_skill` requires configured skills,
82
+ - `ask_user_question` requires frontend support,
83
+ - `retrieve_tool_output` is available in normal sessions so compacted artifacts can be inspected later.