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.
- checksums.yaml +4 -4
- data/.github/workflows/pages.yml +1 -1
- data/CHANGELOG.md +89 -3
- data/Gemfile +2 -0
- data/Gemfile.lock +90 -2
- data/README.md +34 -6
- data/Rakefile +96 -0
- data/doc/agent-tools.md +52 -0
- data/doc/api.md +92 -0
- data/doc/authentication.md +58 -23
- data/doc/code-search.md +42 -2
- data/doc/configuration.md +102 -13
- data/doc/context-budgeting.md +136 -0
- data/doc/context-tools.md +83 -0
- data/doc/editor.md +394 -0
- data/doc/extensibility.md +16 -7
- data/doc/files.md +100 -0
- data/doc/getting-started.md +25 -18
- data/doc/git.md +122 -0
- data/doc/memory.md +24 -4
- data/doc/personas.md +34 -5
- data/doc/plugins.md +74 -3
- data/doc/releasing.md +45 -8
- data/doc/rpc.md +77 -15
- data/doc/session-management.md +254 -0
- data/doc/shell.md +286 -0
- data/doc/tabs.md +122 -0
- data/doc/troubleshooting.md +77 -1
- data/doc/usage.md +60 -15
- data/doc/web-search.md +12 -4
- data/doc/workspace-tools.md +144 -0
- data/examples/plugins/space_invaders.rb +377 -0
- data/lib/kward/agent.rb +1 -1
- data/lib/kward/cli/commands.rb +41 -2
- data/lib/kward/cli/git.rb +150 -0
- data/lib/kward/cli/interactive_turn.rb +73 -9
- data/lib/kward/cli/openrouter_commands.rb +55 -0
- data/lib/kward/cli/plugins.rb +54 -4
- data/lib/kward/cli/prompt_interface.rb +111 -6
- data/lib/kward/cli/rendering.rb +11 -6
- data/lib/kward/cli/runtime_helpers.rb +133 -3
- data/lib/kward/cli/sessions.rb +262 -13
- data/lib/kward/cli/settings.rb +216 -37
- data/lib/kward/cli/slash_commands.rb +439 -8
- data/lib/kward/cli/tabs.rb +695 -0
- data/lib/kward/cli.rb +171 -26
- data/lib/kward/compactor.rb +4 -1
- data/lib/kward/config_files.rb +125 -5
- data/lib/kward/context_budget_meter.rb +44 -0
- data/lib/kward/conversation.rb +59 -22
- data/lib/kward/editor_mode.rb +25 -0
- data/lib/kward/ekwsh.rb +362 -0
- data/lib/kward/model/client.rb +37 -50
- data/lib/kward/model/context_usage.rb +13 -6
- data/lib/kward/model/model_info.rb +92 -16
- data/lib/kward/model/payloads.rb +2 -0
- data/lib/kward/openrouter_model_cache.rb +120 -0
- data/lib/kward/plugin_registry.rb +108 -1
- data/lib/kward/project_files.rb +52 -0
- data/lib/kward/prompt_history.rb +82 -0
- data/lib/kward/prompt_interface/banner.rb +16 -51
- data/lib/kward/prompt_interface/composer_controller.rb +124 -83
- data/lib/kward/prompt_interface/composer_renderer.rb +116 -14
- data/lib/kward/prompt_interface/composer_state.rb +96 -27
- data/lib/kward/prompt_interface/editor/auto_close_pairs.rb +123 -0
- data/lib/kward/prompt_interface/editor/auto_indent.rb +509 -0
- data/lib/kward/prompt_interface/editor/buffer.rb +109 -0
- data/lib/kward/prompt_interface/editor/controller.rb +1018 -0
- data/lib/kward/prompt_interface/editor/endwise.rb +321 -0
- data/lib/kward/prompt_interface/editor/file_marker.rb +40 -0
- data/lib/kward/prompt_interface/editor/indent_navigation.rb +61 -0
- data/lib/kward/prompt_interface/editor/kill_ring.rb +78 -0
- data/lib/kward/prompt_interface/editor/modes/emacs.rb +259 -0
- data/lib/kward/prompt_interface/editor/modes/modern.rb +353 -0
- data/lib/kward/prompt_interface/editor/modes/vibe.rb +1962 -0
- data/lib/kward/prompt_interface/editor/renderer.rb +243 -0
- data/lib/kward/prompt_interface/editor/search.rb +76 -0
- data/lib/kward/prompt_interface/editor/selections.rb +120 -0
- data/lib/kward/prompt_interface/editor/state.rb +1249 -0
- data/lib/kward/prompt_interface/editor/status_text.rb +23 -0
- data/lib/kward/prompt_interface/editor/syntax_highlighter.rb +420 -0
- data/lib/kward/prompt_interface/editor/undo_history.rb +46 -0
- data/lib/kward/prompt_interface/editor/vibe_state.rb +44 -0
- data/lib/kward/prompt_interface/file_overlay.rb +211 -0
- data/lib/kward/prompt_interface/git_prompt.rb +299 -0
- data/lib/kward/prompt_interface/interactive/controller.rb +186 -0
- data/lib/kward/prompt_interface/interactive/renderer.rb +71 -0
- data/lib/kward/prompt_interface/interactive/state.rb +62 -0
- data/lib/kward/prompt_interface/key_handler.rb +416 -43
- data/lib/kward/prompt_interface/layout.rb +2 -2
- data/lib/kward/prompt_interface/overlay_renderer.rb +21 -2
- data/lib/kward/prompt_interface/project_browser.rb +524 -0
- data/lib/kward/prompt_interface/prompt_renderer.rb +32 -13
- data/lib/kward/prompt_interface/question_prompt.rb +122 -82
- data/lib/kward/prompt_interface/runtime_state.rb +49 -1
- data/lib/kward/prompt_interface/screen.rb +17 -0
- data/lib/kward/prompt_interface/selection_prompt.rb +511 -58
- data/lib/kward/prompt_interface/stream_state.rb +7 -0
- data/lib/kward/prompt_interface/transcript_buffer.rb +13 -16
- data/lib/kward/prompt_interface/transcript_renderer.rb +3 -3
- data/lib/kward/prompt_interface.rb +307 -35
- data/lib/kward/prompts/commands.rb +7 -1
- data/lib/kward/prompts.rb +4 -2
- data/lib/kward/rpc/server.rb +45 -11
- data/lib/kward/rpc/session_manager.rb +52 -53
- data/lib/kward/rpc/session_tree_rows.rb +9 -115
- data/lib/kward/rpc/tool_event_normalizer.rb +1 -1
- data/lib/kward/session_store.rb +67 -4
- data/lib/kward/session_tree_nodes.rb +136 -0
- data/lib/kward/session_tree_renderer.rb +9 -131
- data/lib/kward/tab_store.rb +47 -0
- data/lib/kward/telemetry/logger.rb +5 -3
- data/lib/kward/text_boundary.rb +25 -0
- data/lib/kward/tool_output_compactor.rb +127 -0
- data/lib/kward/tools/base.rb +8 -2
- data/lib/kward/tools/context_budget_stats.rb +54 -0
- data/lib/kward/tools/context_for_task.rb +202 -0
- data/lib/kward/tools/read_file.rb +8 -4
- data/lib/kward/tools/registry.rb +92 -15
- data/lib/kward/tools/retrieve_tool_output.rb +71 -0
- data/lib/kward/tools/search/web.rb +2 -2
- data/lib/kward/tools/summarize_file_structure.rb +29 -0
- data/lib/kward/tools/tool_call.rb +12 -0
- data/lib/kward/version.rb +1 -1
- data/lib/kward/workers/git_guard.rb +68 -0
- data/lib/kward/workers/live_view.rb +49 -0
- data/lib/kward/workers/manager.rb +288 -0
- data/lib/kward/workers/store.rb +72 -0
- data/lib/kward/workers/tool_policy.rb +23 -0
- data/lib/kward/workers/worker.rb +82 -0
- data/lib/kward/workers/write_lock.rb +38 -0
- data/lib/kward/workers.rb +7 -0
- data/lib/kward/workspace.rb +154 -12
- data/templates/default/fulldoc/html/css/kward.css +362 -42
- data/templates/default/fulldoc/html/full_list.erb +107 -0
- data/templates/default/fulldoc/html/js/kward.js +161 -2
- data/templates/default/fulldoc/html/setup.rb +8 -0
- data/templates/default/kward_navigation.rb +102 -0
- data/templates/default/layout/html/layout.erb +43 -10
- data/templates/default/layout/html/setup.rb +39 -38
- metadata +65 -3
- data/lib/kward/resources/avatar_kward_logo.rb +0 -50
- data/lib/kward/resources/pixel_logo.rb +0 -232
data/doc/authentication.md
CHANGED
|
@@ -12,7 +12,9 @@ Or inside interactive Kward:
|
|
|
12
12
|
/login
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
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
|
-
##
|
|
150
|
+
## Choose the active model
|
|
112
151
|
|
|
113
|
-
|
|
152
|
+
Authentication makes providers available. The active model is selected separately.
|
|
114
153
|
|
|
115
|
-
|
|
154
|
+
Inside Kward, use:
|
|
116
155
|
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
"provider": "anthropic"
|
|
120
|
-
}
|
|
156
|
+
```text
|
|
157
|
+
/model
|
|
121
158
|
```
|
|
122
159
|
|
|
123
|
-
|
|
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
|
-
|
|
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
|
-
|
|
164
|
+
## Custom auth file locations
|
|
130
165
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
##
|
|
175
|
+
## Composer settings
|
|
152
176
|
|
|
153
|
-
The
|
|
177
|
+
The busy composer shows a short Ctrl+C cancellation hint by default. To hide it:
|
|
154
178
|
|
|
155
179
|
```json
|
|
156
180
|
{
|
|
157
|
-
"
|
|
158
|
-
"
|
|
181
|
+
"composer": {
|
|
182
|
+
"busy_help": false
|
|
159
183
|
}
|
|
160
184
|
}
|
|
161
185
|
```
|
|
162
186
|
|
|
163
|
-
This only
|
|
187
|
+
This only hides the hint text; Ctrl+C still stops the current running response.
|
|
164
188
|
|
|
165
|
-
|
|
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
|
-
|
|
191
|
+
`tab_keybindings` controls how the composer handles tab navigation shortcuts:
|
|
168
192
|
|
|
169
193
|
```json
|
|
170
194
|
{
|
|
171
195
|
"composer": {
|
|
172
|
-
"
|
|
196
|
+
"tab_keybindings": "auto"
|
|
173
197
|
}
|
|
174
198
|
}
|
|
175
199
|
```
|
|
176
200
|
|
|
177
|
-
|
|
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.
|