kward 0.78.0 → 0.80.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 (137) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +13 -2
  3. data/.github/workflows/pages.yml +1 -1
  4. data/CHANGELOG.md +82 -1
  5. data/Gemfile.lock +2 -2
  6. data/README.md +33 -38
  7. data/doc/agent-tools.md +10 -11
  8. data/doc/api.md +3 -3
  9. data/doc/authentication.md +79 -110
  10. data/doc/code-search.md +1 -1
  11. data/doc/composer.md +1 -1
  12. data/doc/configuration.md +136 -27
  13. data/doc/context-budgeting.md +6 -6
  14. data/doc/context-tools.md +2 -2
  15. data/doc/editor.md +7 -7
  16. data/doc/extensibility.md +9 -29
  17. data/doc/files.md +6 -6
  18. data/doc/getting-started.md +3 -3
  19. data/doc/git.md +8 -2
  20. data/doc/lifecycle-hooks.md +5 -4
  21. data/doc/local-models.md +130 -0
  22. data/doc/mcp.md +5 -5
  23. data/doc/permissions.md +15 -5
  24. data/doc/plugins.md +39 -4
  25. data/doc/prompt-templates.md +105 -0
  26. data/doc/providers.md +140 -0
  27. data/doc/releasing.md +11 -3
  28. data/doc/rpc.md +65 -31
  29. data/doc/sandboxing.md +142 -0
  30. data/doc/security.md +31 -10
  31. data/doc/session-management.md +2 -4
  32. data/doc/skills.md +10 -0
  33. data/doc/tabs.md +37 -0
  34. data/doc/telegram.md +138 -0
  35. data/doc/transports.md +209 -0
  36. data/doc/usage.md +11 -3
  37. data/doc/web-search.md +3 -3
  38. data/doc/workspace-tools.md +4 -4
  39. data/examples/plugins/stardate_footer.rb +10 -0
  40. data/examples/plugins/telegram/plugin.rb +39 -0
  41. data/examples/plugins/telegram/telegram_api.rb +136 -0
  42. data/examples/plugins/telegram/telegram_transport.rb +304 -0
  43. data/kward.gemspec +1 -1
  44. data/lib/kward/ansi.rb +1 -0
  45. data/lib/kward/auth/api_key_store.rb +99 -0
  46. data/lib/kward/cli/auth_commands.rb +72 -13
  47. data/lib/kward/cli/commands.rb +7 -0
  48. data/lib/kward/cli/doctor.rb +21 -0
  49. data/lib/kward/cli/git.rb +31 -8
  50. data/lib/kward/cli/plugins.rb +1 -0
  51. data/lib/kward/cli/prompt_interface.rb +7 -0
  52. data/lib/kward/cli/rendering.rb +6 -2
  53. data/lib/kward/cli/runtime_helpers.rb +4 -2
  54. data/lib/kward/cli/sessions.rb +1 -1
  55. data/lib/kward/cli/settings.rb +162 -36
  56. data/lib/kward/cli/slash_commands.rb +109 -1
  57. data/lib/kward/cli/tabs.rb +102 -37
  58. data/lib/kward/cli/transports.rb +67 -0
  59. data/lib/kward/cli/worktrees.rb +360 -0
  60. data/lib/kward/cli.rb +22 -1
  61. data/lib/kward/config_files.rb +106 -4
  62. data/lib/kward/conversation.rb +27 -8
  63. data/lib/kward/git_worktree_manager.rb +291 -0
  64. data/lib/kward/local_command_runner.rb +2 -2
  65. data/lib/kward/model/azure_openai_config.rb +54 -0
  66. data/lib/kward/model/catalog.rb +113 -0
  67. data/lib/kward/model/client.rb +364 -23
  68. data/lib/kward/model/model_info.rb +60 -1
  69. data/lib/kward/model/payloads.rb +64 -4
  70. data/lib/kward/model/provider_catalog.rb +114 -0
  71. data/lib/kward/model/sources.rb +70 -0
  72. data/lib/kward/model/stream_parser.rb +141 -39
  73. data/lib/kward/pan/index.html.erb +50 -0
  74. data/lib/kward/pan/server.rb +49 -2
  75. data/lib/kward/permissions/policy.rb +18 -4
  76. data/lib/kward/plugin_chat_runtime.rb +374 -0
  77. data/lib/kward/plugin_registry.rb +81 -8
  78. data/lib/kward/private_file.rb +9 -3
  79. data/lib/kward/prompt_interface/approval_prompt.rb +2 -0
  80. data/lib/kward/prompt_interface/composer_renderer.rb +1 -5
  81. data/lib/kward/prompt_interface/editor/auto_indent.rb +46 -0
  82. data/lib/kward/prompt_interface/editor/buffer.rb +18 -4
  83. data/lib/kward/prompt_interface/editor/controller.rb +43 -10
  84. data/lib/kward/prompt_interface/editor/modes/vibe.rb +2 -2
  85. data/lib/kward/prompt_interface/editor/renderer.rb +8 -8
  86. data/lib/kward/prompt_interface/editor/state.rb +3 -9
  87. data/lib/kward/prompt_interface/editor/syntax_highlighter.rb +184 -9
  88. data/lib/kward/prompt_interface/file_overlay.rb +2 -2
  89. data/lib/kward/prompt_interface/git_prompt.rb +7 -3
  90. data/lib/kward/prompt_interface/interactive/controller.rb +4 -4
  91. data/lib/kward/prompt_interface/interactive/renderer.rb +4 -1
  92. data/lib/kward/prompt_interface/interactive/state.rb +2 -2
  93. data/lib/kward/prompt_interface/project_browser.rb +25 -6
  94. data/lib/kward/prompt_interface/runtime_state.rb +22 -6
  95. data/lib/kward/prompt_interface/screen.rb +3 -0
  96. data/lib/kward/prompt_interface/selection_prompt.rb +7 -1
  97. data/lib/kward/prompt_interface/transcript_buffer.rb +24 -2
  98. data/lib/kward/prompt_interface.rb +71 -12
  99. data/lib/kward/prompts/commands.rb +3 -1
  100. data/lib/kward/prompts.rb +22 -10
  101. data/lib/kward/rpc/auth_manager.rb +112 -152
  102. data/lib/kward/rpc/config_manager.rb +46 -6
  103. data/lib/kward/rpc/plugin_chat_manager.rb +56 -194
  104. data/lib/kward/rpc/prompt_bridge.rb +8 -4
  105. data/lib/kward/rpc/redactor.rb +1 -1
  106. data/lib/kward/rpc/server.rb +102 -14
  107. data/lib/kward/rpc/session_manager.rb +151 -38
  108. data/lib/kward/sandbox/capabilities.rb +39 -0
  109. data/lib/kward/sandbox/command_runner.rb +28 -0
  110. data/lib/kward/sandbox/environment.rb +24 -0
  111. data/lib/kward/sandbox/linux_bubblewrap_runner.rb +71 -0
  112. data/lib/kward/sandbox/macos_seatbelt_runner.rb +96 -0
  113. data/lib/kward/sandbox/passthrough_runner.rb +13 -0
  114. data/lib/kward/sandbox/policy.rb +74 -0
  115. data/lib/kward/sandbox/runner_factory.rb +55 -0
  116. data/lib/kward/sandbox/unavailable_runner.rb +21 -0
  117. data/lib/kward/sandbox.rb +9 -0
  118. data/lib/kward/session_store.rb +110 -24
  119. data/lib/kward/skills/capture.rb +144 -0
  120. data/lib/kward/tab_driver.rb +6 -3
  121. data/lib/kward/tools/git_commit.rb +39 -0
  122. data/lib/kward/tools/registry.rb +26 -6
  123. data/lib/kward/tools/tool_call.rb +1 -0
  124. data/lib/kward/transport/gateway.rb +253 -0
  125. data/lib/kward/transport/host.rb +343 -0
  126. data/lib/kward/transport/manager.rb +179 -0
  127. data/lib/kward/transport/plugin_chat_gateway.rb +186 -0
  128. data/lib/kward/transport/runtime.rb +41 -0
  129. data/lib/kward/transport/store.rb +101 -0
  130. data/lib/kward/transport.rb +204 -0
  131. data/lib/kward/version.rb +1 -1
  132. data/lib/kward/workspace.rb +18 -3
  133. data/lib/kward/workspace_factory.rb +34 -0
  134. data/templates/default/fulldoc/html/js/kward.js +3 -0
  135. data/templates/default/kward_navigation.rb +8 -1
  136. data/templates/default/layout/html/setup.rb +5 -0
  137. metadata +41 -2
@@ -1,181 +1,150 @@
1
1
  # Authentication
2
2
 
3
- Kward needs access to a model provider before it can answer prompts. The fastest path is:
3
+ Kward can keep credentials for several model providers at once. First connect an account or API key, then use `/model` to choose the provider and model for your work. See [Model providers](providers.md) to compare providers and find their configuration names and environment variables.
4
4
 
5
- ```bash
6
- kward login
7
- ```
8
-
9
- Or inside interactive Kward:
5
+ The easiest setup is inside interactive Kward:
10
6
 
11
7
  ```text
12
8
  /login
13
9
  ```
14
10
 
15
- `/login` opens a provider picker; `kward login` accepts the provider as an argument.
11
+ Choose **API key** or **Subscription / OAuth**, then choose a provider. After login, open:
16
12
 
17
- Use the provider you already have access to. You can change the active model later with `/model`.
18
-
19
- ## Choose a provider
20
-
21
- | Provider | Use it when... |
22
- | --- | --- |
23
- | OpenAI/ChatGPT | You want the default Codex backend with a ChatGPT account. |
24
- | Anthropic | You have Claude Pro/Max and want to use Claude through Kward. |
25
- | OpenRouter | You want to use an OpenRouter API key and choose from its model catalog. |
26
- | Copilot | You want to try experimental Copilot provider support. |
13
+ ```text
14
+ /model
15
+ ```
27
16
 
28
- If you are unsure, start with `kward login` and choose OpenAI.
17
+ ## Supported authentication
29
18
 
30
- ## Login commands
19
+ | Provider | API key | Subscription / OAuth |
20
+ | --- | --- | --- |
21
+ | OpenAI | Yes, direct OpenAI API | Yes, ChatGPT/Codex |
22
+ | Anthropic | Yes, direct Anthropic API | Yes, Claude Pro/Max |
23
+ | Azure OpenAI | Yes; endpoint, deployment, and API version are also required | No |
24
+ | Google Gemini | Yes | No |
25
+ | Cerebras, DeepSeek, Fireworks AI, Groq, Mistral, NVIDIA NIM, Together AI | Yes | No |
26
+ | OpenRouter | Yes | Not yet in Kward |
27
+ | xAI | Yes | No supported third-party flow |
28
+ | GitHub Copilot | No API-key mode | Yes |
31
29
 
32
- ```bash
33
- kward login # OpenAI/ChatGPT OAuth
34
- kward login anthropic # Anthropic Claude Pro/Max OAuth
35
- kward login openrouter # OpenRouter API key
36
- kward login github # GitHub OAuth for experimental Copilot support
37
- ```
30
+ Direct OpenAI API credentials and ChatGPT/Codex OAuth are independent. You can keep both and switch between **OpenAI** and **Codex** in `/model`.
38
31
 
39
- ## OpenAI / ChatGPT
32
+ ## API-key workflow
40
33
 
41
- ```bash
42
- kward login
43
- ```
44
-
45
- This opens a browser login and saves credentials to:
34
+ From `/login`, choose **API key** and the provider. Kward validates providers with live model discovery before saving the key, then stores it in:
46
35
 
47
36
  ```text
48
- ~/.kward/auth.json
37
+ ~/.kward/api_keys.json
49
38
  ```
50
39
 
51
- Kward uses the ChatGPT/Codex backend, not the OpenAI Platform API key flow.
40
+ The file is private (`0600` when supported). It is separate from `config.json`, so normal config reads and RPC responses do not return keys.
52
41
 
53
- If Kward asks for an OAuth client ID, add it to `~/.kward/config.json`:
42
+ For providers that do not also offer subscription login, the shell command is convenient:
54
43
 
55
- ```json
56
- {
57
- "openai_oauth_client_id": "your-client-id"
58
- }
44
+ ```bash
45
+ kward login groq
46
+ kward login gemini
47
+ kward login openrouter
48
+ kward login azure_openai
59
49
  ```
60
50
 
61
- Kward ships with a built-in client ID, so this is only needed if login fails or you want to use your own.
51
+ Use the interactive `/login` method picker for direct OpenAI or Anthropic API keys because `kward login openai` and `kward login anthropic` retain their subscription-login behavior.
62
52
 
63
- For a single shell session without OAuth, you can set an access token directly:
53
+ Environment variables override a stored key for that provider:
64
54
 
65
55
  ```bash
66
- OPENAI_ACCESS_TOKEN=... kward
56
+ OPENAI_API_KEY=... kward
57
+ GEMINI_API_KEY=... kward
58
+ GROQ_API_KEY=... kward
67
59
  ```
68
60
 
69
- ## Anthropic Claude Pro/Max
61
+ Other supported variables are listed in [Configuration](configuration.md#Environment_overrides).
70
62
 
71
- ```bash
72
- kward login anthropic
73
- ```
63
+ ### Azure OpenAI
74
64
 
75
- This saves credentials to:
65
+ Azure setup asks for three non-secret values after the key:
76
66
 
77
- ```text
78
- ~/.kward/anthropic_auth.json
79
- ```
67
+ - an HTTPS endpoint, such as `https://example.openai.azure.com`;
68
+ - a deployment name;
69
+ - an API version, such as `2025-04-01-preview`.
80
70
 
81
- Use this when you want Kward to use your Claude Pro/Max subscription. Kward refreshes the access token when a refresh token is available.
71
+ Kward rejects endpoint credentials, query strings, fragments, and unsafe deployment/version characters. The deployment is the model shown in `/model`; Kward does not claim to discover Azure deployments from an inference key.
82
72
 
83
- ## OpenRouter
73
+ ## ChatGPT / Codex OAuth
84
74
 
85
75
  ```bash
86
- kward login openrouter
76
+ kward login
87
77
  ```
88
78
 
89
- This stores your API key in `~/.kward/config.json`.
79
+ Credentials are saved to `~/.kward/auth.json`. This uses the ChatGPT/Codex backend, not `OPENAI_API_KEY` or the public OpenAI API endpoint.
90
80
 
91
- For a single shell session, you can avoid saving the key:
81
+ For one shell session, you can provide the Codex access token directly:
92
82
 
93
83
  ```bash
94
- OPENROUTER_API_KEY=sk-or-v1-... kward
84
+ OPENAI_ACCESS_TOKEN=... kward
95
85
  ```
96
86
 
97
- Choose OpenRouter when you want access to its model catalog or want provider/model selection through an API key.
98
-
99
- ### Refresh the OpenRouter model cache
87
+ `OPENAI_ACCESS_TOKEN` continues to mean Codex OAuth. `OPENAI_API_KEY` means direct OpenAI API access; neither replaces the other.
100
88
 
101
- Kward's `/model` picker can show OpenRouter models that are available to your API key. Refresh the local cache after logging in:
89
+ ## Anthropic Claude Pro/Max
102
90
 
103
91
  ```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
92
+ kward login anthropic
111
93
  ```
112
94
 
113
- If `KWARD_CONFIG_PATH` points at a custom config file, the cache is written beside that config file under `cache/openrouter_models.json`.
95
+ OAuth credentials are saved to `~/.kward/anthropic_auth.json`. Kward refreshes the access token when a refresh token is available. Choose **API key** in `/login` instead when you want direct Anthropic API billing.
114
96
 
115
- Inspect the cached model ids with:
97
+ ## GitHub Copilot
116
98
 
117
99
  ```bash
118
- kward openrouter list
100
+ kward login github
119
101
  ```
120
102
 
121
- Use this when:
103
+ Credentials are saved to `~/.kward/github_auth.json`. For one run, use `COPILOT_GITHUB_TOKEN`. General `GH_TOKEN` and `GITHUB_TOKEN` values are not treated as Copilot credentials.
122
104
 
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`.
105
+ ## OpenRouter
129
106
 
130
- ## Experimental Copilot support
107
+ API-key login is supported, including model refresh:
131
108
 
132
109
  ```bash
133
- kward login github
110
+ kward login openrouter
111
+ kward openrouter refresh
112
+ kward openrouter list
134
113
  ```
135
114
 
136
- This saves GitHub OAuth credentials to:
115
+ The cache lives at `<config-dir>/cache/openrouter_models.json`. `/model` can also refresh the active provider directly.
137
116
 
138
- ```text
139
- ~/.kward/github_auth.json
140
- ```
117
+ OpenRouter documents an official [OAuth PKCE flow](https://openrouter.ai/docs/guides/overview/auth/oauth), but Kward does not implement that flow yet. It remains unavailable in CLI and RPC capabilities rather than exposing an unverified partial login.
141
118
 
142
- You can also use a token for one run:
119
+ xAI's public inference documentation currently directs clients to API keys (see the [xAI quickstart](https://docs.x.ai/developers/quickstart)); Kward does not expose an xAI subscription OAuth flow.
143
120
 
144
- ```bash
145
- COPILOT_GITHUB_TOKEN=... kward
146
- ```
121
+ ## Model selection
147
122
 
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.
123
+ The provider-aware `/model` picker offers:
149
124
 
150
- ## Choose the active model
125
+ - **Refresh model list**;
126
+ - **Enter model ID manually**;
127
+ - **Show all models**;
128
+ - **Change provider**.
151
129
 
152
- Authentication makes providers available. The active model is selected separately.
130
+ By default, Kward hides entries when provider metadata proves they are not generation/tool models. It keeps entries whose metadata is incomplete. **Show all models** and manual IDs remain available for previews, private deployments, and incomplete catalogs.
153
131
 
154
- Inside Kward, use:
132
+ ## Status and logout
155
133
 
156
- ```text
157
- /model
134
+ ```bash
135
+ kward auth status
136
+ kward auth logout
158
137
  ```
159
138
 
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.
161
-
162
- For one-off shell runs, `KWARD_PROVIDER` and provider-specific model environment variables remain available. See [Configuration](configuration.md) for the full list.
163
-
164
- ## Custom auth file locations
165
-
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/`.
139
+ Status reports only whether credentials exist and where they came from; it never prints credential values. CLI logout removes all saved OAuth and API-key credentials. Environment variables remain active until you unset them.
167
140
 
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`)
141
+ RPC clients can list catalog providers, inspect sanitized method availability, save/remove individual API keys, and remove a specific provider/auth method. See [RPC](rpc.md#Config_and_auth_methods).
171
142
 
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`.
143
+ ## Custom locations
173
144
 
174
- ## Security notes
145
+ - `KWARD_CONFIG_PATH` moves `config.json`, `api_keys.json`, caches, and most other Kward state to that file's directory.
146
+ - `KWARD_AUTH_PATH` overrides ChatGPT/Codex OAuth storage.
147
+ - `KWARD_ANTHROPIC_AUTH_PATH` overrides Anthropic OAuth storage.
148
+ - `KWARD_GITHUB_AUTH_PATH` overrides GitHub Copilot OAuth storage.
175
149
 
176
- - Auth files are written with file mode `0600` when possible.
177
- - Do not commit `~/.kward/config.json` or auth files.
178
- - Prefer environment variables for temporary credentials.
179
- - `kward auth status` shows credential status without printing secrets.
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.
150
+ Never commit credential files. For temporary credentials, prefer environment variables and unset them when finished.
data/doc/code-search.md CHANGED
@@ -29,7 +29,7 @@ The `code_search` tool can:
29
29
  4. search cached files,
30
30
  5. read bounded line ranges from cached files.
31
31
 
32
- Kward should use this when the best answer depends on how another project actually implemented something.
32
+ Kward uses code search when the best answer depends on how another project actually implemented something.
33
33
 
34
34
  ## Supported ecosystems
35
35
 
data/doc/composer.md CHANGED
@@ -99,7 +99,7 @@ The `$` token must begin at the first character of the composer. Use Up/Down to
99
99
 
100
100
  A successful `$path` open is saved in prompt history using the resolved workspace-relative path. It opens the editor instead of sending a model prompt.
101
101
 
102
- See [Integrated Editor](editor.md) for editing modes, save and quit keys, scratchpads, and conflict handling.
102
+ See [Integrated editor](editor.md) for editing modes, save and quit keys, scratchpads, and conflict handling.
103
103
 
104
104
  ## Reuse prompt history
105
105
 
data/doc/configuration.md CHANGED
@@ -6,7 +6,9 @@ On first start, Kward creates the file when it does not exist. The starter confi
6
6
 
7
7
  If `KWARD_CONFIG_PATH` is set, Kward uses that file and treats its directory as the config directory for prompts, skills, memory, logs, and caches.
8
8
 
9
- ## Common changes
9
+ ## Choose a configuration path
10
+
11
+ Use the interactive controls for ordinary changes. Edit `config.json` when you need a setting that is not exposed there or when you want to share a reproducible setup.
10
12
 
11
13
  | Goal | Recommended path |
12
14
  | --- | --- |
@@ -15,10 +17,13 @@ If `KWARD_CONFIG_PATH` is set, Kward uses that file and treats its directory as
15
17
  | Change editor, diff, overlay, or session UI behavior | `/settings` → Interface |
16
18
  | Enable memory | `/settings` → Memory |
17
19
  | Configure web search or trust project skills | `/settings` → Tools & Search |
20
+ | Contain model-requested shell commands | `/sandbox` for mode and child-network access; edit config for additional writable roots |
18
21
  | Tune compaction | `/settings` → Context & Compaction |
19
22
  | Configure personas | `/settings` → Personalization; see [Personas](personas.md) |
20
23
  | Add MCP servers, lifecycle hooks, or environment-specific paths | Edit `config.json` directly |
21
24
 
25
+ For the complete reference, jump to [provider and model settings](#Provider_and_model_settings), [terminal interface settings](#Overlay_settings), [sessions and memory](#Session_settings), [web search](#Web_search), [workspace safety](#Tool_workspace_guardrails), or [logging](#Logging_and_stats). See [Model providers](providers.md) to compare providers and find their configuration names.
26
+
22
27
  Here is a minimal direct provider configuration:
23
28
 
24
29
  ```json
@@ -45,6 +50,35 @@ Add trusted local Model Context Protocol servers under `mcpServers`:
45
50
 
46
51
  See [MCP servers](mcp.md) for setup, supported fields, and security notes.
47
52
 
53
+ ### Transport plugins
54
+
55
+ Transport plugin settings live under `transports` and are scoped by the
56
+ transport's stable ID:
57
+
58
+ ```json
59
+ {
60
+ "transports": {
61
+ "com.kward.telegram": {
62
+ "workspace": "/Users/me/src/project",
63
+ "allowed_user_ids": [123456789],
64
+ "allowed_chat_ids": [123456789],
65
+ "poll_timeout_seconds": 25
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ Transport plugins are trusted local Ruby code. Keep credentials in environment
72
+ variables or another private secret mechanism provided by the plugin rather
73
+ than committing them to `config.json`. Transport state, including external
74
+ conversation bindings and idempotency keys, is stored privately under the
75
+ transport's namespace in `~/.kward/transports/`.
76
+
77
+ Run `kward transport list` to inspect registrations, `kward transport status`
78
+ to inspect runtime state, and `kward transport run NAME` to run a transport in
79
+ the foreground. See [Telegram transport](telegram.md) for the first-party
80
+ long-polling adapter and setup instructions.
81
+
48
82
  ### Project skills
49
83
 
50
84
  Kward loads user-level skills but skips project-level skills by default. Enable them only for repositories you trust, either through `/settings` → Tools & Search → Trust project skills or with:
@@ -79,6 +113,7 @@ By default, Kward stores user data under `~/.kward`. Common files and directorie
79
113
 
80
114
  ```text
81
115
  ~/.kward/config.json
116
+ ~/.kward/api_keys.json
82
117
  ~/.kward/auth.json
83
118
  ~/.kward/anthropic_auth.json
84
119
  ~/.kward/github_auth.json
@@ -145,6 +180,8 @@ aliases:
145
180
 
146
181
  ## Provider and model settings
147
182
 
183
+ The [Model providers](providers.md) guide lists every provider ID, model key, credential variable, catalog source, and request API. This section explains the underlying config pattern.
184
+
148
185
  Set `provider` to choose the active backend:
149
186
 
150
187
  ```json
@@ -155,12 +192,15 @@ Set `provider` to choose the active backend:
155
192
 
156
193
  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.
157
194
 
158
- Supported values are:
195
+ Common values are:
159
196
 
160
- - `codex` for the OpenAI/ChatGPT Codex backend.
161
- - `anthropic` for Anthropic Claude Pro/Max subscription support.
162
- - `openrouter` for OpenRouter.
163
- - `copilot` for experimental Copilot provider support.
197
+ - `codex` for the ChatGPT/Codex OAuth backend;
198
+ - `openai_api` for direct OpenAI API access;
199
+ - `anthropic`, `openrouter`, and `copilot` for those providers;
200
+ - `gemini` for Google Gemini;
201
+ - `azure_openai` for a configured Azure deployment;
202
+ - `cerebras`, `deepseek`, `fireworks`, `groq`, `mistral`, `nvidia`, `together`, or `xai` for API-key providers;
203
+ - `local` for an OpenAI-compatible Ollama, LM Studio, or llama.cpp server. See [Local models](local-models.md).
164
204
 
165
205
  Model settings:
166
206
 
@@ -168,9 +208,13 @@ Model settings:
168
208
  {
169
209
  "model": "gpt-5.6-sol",
170
210
  "openai_model": "gpt-5.6-sol",
211
+ "openai_api_model": "gpt-5.4-mini",
171
212
  "openrouter_model": "openai/gpt-5.6-sol",
213
+ "gemini_model": "gemini-2.5-flash",
214
+ "groq_model": "provider-model-id",
172
215
  "anthropic_model": "claude-sonnet-5",
173
216
  "copilot_model": "gpt-5-mini",
217
+ "local_model": "qwen2.5-coder:7b",
174
218
  "reasoning_effort": "medium",
175
219
  "openai_reasoning_effort": "medium",
176
220
  "openrouter_reasoning_effort": "medium",
@@ -180,11 +224,11 @@ Model settings:
180
224
  }
181
225
  ```
182
226
 
183
- `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.
227
+ `model` is a legacy generic fallback. Provider-specific values take precedence. Catalog providers use `<runtime-id>_model`; for example, direct OpenAI uses `openai_api_model`, Gemini uses `gemini_model`, and Groq uses `groq_model`. Codex keeps `openai_model`. `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.
184
228
 
185
229
  Set `codex_show_raw_reasoning` to `true` to display raw Codex `reasoning_text` when the API does not provide reasoning summary text. It defaults to `false`; raw reasoning can include internal or unstable model output, so enable it only when you explicitly want to inspect that stream.
186
230
 
187
- `stream_idle_timeout_seconds` limits how long a streamed Codex or Anthropic response may go without receiving data. It defaults to `120`; set a positive value to override it. When the provider is silent longer than this limit, Kward closes the request and applies its normal transient-network retry behavior.
231
+ `stream_idle_timeout_seconds` limits how long a streamed Codex, Anthropic, or Local response may go without receiving data. It defaults to `120`; set a positive value to override it. When the provider is silent longer than this limit, Kward closes the request and applies its normal transient-network retry behavior.
188
232
 
189
233
  Defaults:
190
234
 
@@ -198,6 +242,24 @@ The Anthropic model choices include `claude-fable-5`, but Fable availability dep
198
242
 
199
243
  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.
200
244
 
245
+ ### Local model server
246
+
247
+ The `local` provider uses OpenAI-compatible Chat Completions and model-list endpoints. Configure a running local server with a model id and its actual context window:
248
+
249
+ ```json
250
+ {
251
+ "provider": "local",
252
+ "local_backend": "ollama",
253
+ "local_base_url": "http://127.0.0.1:11434/v1",
254
+ "local_model": "qwen2.5-coder:7b",
255
+ "local_context_window": 32768
256
+ }
257
+ ```
258
+
259
+ `local_backend` selects a convenience default: `ollama`, `lm_studio`, or `llama_cpp`. Their default base URLs are `http://127.0.0.1:11434/v1`, `http://127.0.0.1:1234/v1`, and `http://127.0.0.1:8080/v1`, respectively. Set `local_base_url` to use a custom endpoint. `local_api_key` is optional and is sent as a bearer token only when configured.
260
+
261
+ Set `local_context_window` to the context length configured for the loaded model. Kward does not infer this safely from an arbitrary local model name; without it, automatic context budgeting cannot report a reliable limit. Local providers do not expose Kward reasoning or image controls by default.
262
+
201
263
  ## Environment overrides
202
264
 
203
265
  Use environment variables for one-off runs or local secrets that you do not want in config.
@@ -205,10 +267,16 @@ Use environment variables for one-off runs or local secrets that you do not want
205
267
  Provider and model:
206
268
 
207
269
  - `KWARD_PROVIDER`
208
- - `OPENAI_MODEL`
209
- - `OPENAI_REASONING_EFFORT`
270
+ - `OPENAI_MODEL` and `OPENAI_REASONING_EFFORT` for Codex
271
+ - `OPENAI_API_MODEL` and `OPENAI_API_REASONING_EFFORT` for direct OpenAI
272
+ - `<PROVIDER>_MODEL` for catalog providers such as `GEMINI_MODEL`, `GROQ_MODEL`, and `XAI_MODEL`
210
273
  - `OPENROUTER_MODEL`
211
274
  - `OPENROUTER_REASONING_EFFORT`
275
+ - `KWARD_LOCAL_BACKEND`
276
+ - `KWARD_LOCAL_BASE_URL`
277
+ - `KWARD_LOCAL_MODEL`
278
+ - `KWARD_LOCAL_CONTEXT_WINDOW`
279
+ - `KWARD_LOCAL_API_KEY`
212
280
  - `ANTHROPIC_MODEL`
213
281
  - `ANTHROPIC_REASONING_EFFORT`
214
282
  - `COPILOT_MODEL`
@@ -216,7 +284,11 @@ Provider and model:
216
284
 
217
285
  Credentials:
218
286
 
219
- - `OPENAI_ACCESS_TOKEN`
287
+ - `OPENAI_ACCESS_TOKEN` for ChatGPT/Codex OAuth
288
+ - `OPENAI_API_KEY` for direct OpenAI
289
+ - `ANTHROPIC_API_KEY`
290
+ - `AZURE_OPENAI_API_KEY`
291
+ - `CEREBRAS_API_KEY`, `DEEPSEEK_API_KEY`, `FIREWORKS_API_KEY`, `GEMINI_API_KEY`, `GROQ_API_KEY`, `MISTRAL_API_KEY`, `NVIDIA_API_KEY` (or `NGC_API_KEY`), `TOGETHER_API_KEY`, and `XAI_API_KEY`
220
292
  - `OPENROUTER_API_KEY`
221
293
  - `COPILOT_GITHUB_TOKEN`
222
294
  - `GITHUB_TOKEN` or `GH_TOKEN` for authenticated GitHub API requests in `code_search`
@@ -233,16 +305,9 @@ Color and logging environment variables are covered below.
233
305
 
234
306
  The friendliest way to configure credentials is `/login` inside Kward, or `kward login` from your shell. See [Authentication](authentication.md) for the full provider flow.
235
307
 
236
- Credential settings can also live in config:
237
-
238
- ```json
239
- {
240
- "openai_oauth_client_id": "your-client-id",
241
- "openrouter_api_key": "sk-or-v1-..."
242
- }
243
- ```
308
+ API keys are not stored in `config.json`. `/login` writes them to the private `<config-dir>/api_keys.json` file; environment variables take precedence for one-off runs. `openrouter_api_key` is a legacy setting that Kward migrates to the private store.
244
309
 
245
- Use environment variables for temporary or local-only secrets when possible. If multiple credentials are available, OpenAI OAuth is used by default unless `provider` or `KWARD_PROVIDER` selects another backend such as `anthropic`, `openrouter`, or `copilot`.
310
+ Non-secret authentication setup, such as `openai_oauth_client_id` and Azure endpoint/deployment/API-version values, remains in config. If multiple credentials are available, set `provider`, use `/model`, or use `KWARD_PROVIDER` to choose explicitly.
246
311
 
247
312
  ## Overlay settings
248
313
 
@@ -330,9 +395,9 @@ The integrated Git and session diff viewers support unified and side-by-side lay
330
395
 
331
396
  `diff_view` can be `auto`, `unified`, or `side_by_side`. In `auto` mode, Kward uses side-by-side output when the terminal is at least 120 columns wide and unified output in narrower terminals. Change it with `/settings` → Interface → Diff view.
332
397
 
333
- 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.
398
+ The editor includes syntax highlighting, automatic indentation, and matching-pair insertion for common languages. Unknown file types and color-disabled terminals use plain text. See [Integrated editor](editor.md#What_the_editor_supports) for the supported languages and detailed editing behavior.
334
399
 
335
- 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:
400
+ Auto-indent and matching-pair insertion are enabled by default. To disable either feature:
336
401
 
337
402
  ```json
338
403
  {
@@ -375,11 +440,15 @@ Editable editor buffers request a vertical bar cursor by default. Terminals that
375
440
  }
376
441
  ```
377
442
 
378
- 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.
443
+ Choose the mode that matches how you already edit:
379
444
 
380
- 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.
445
+ | Mode | Best fit |
446
+ | --- | --- |
447
+ | `modern` | Familiar shortcuts such as `Ctrl+S` to save and `Ctrl+Q` to quit. |
448
+ | `emacs` | Non-modal Emacs-style movement, selection, kill, and yank keys. |
449
+ | `vibe` | A focused Vim-style experience with normal, insert, command, and visual modes. |
381
450
 
382
- Vibe mode opens files in normal mode and supports a compact Vim-style subset: normal/insert/command modes, character, line, and block visual modes, `h/j/k/l`, word and WORD movement, counts, `d`/`y`/`c` operators, line yanks and indentation, case operators, marks, macros, jump-list navigation, linewise paste, search, undo/redo, and common `:w`, `:q`, `:q!`, `:wq`, `:x`, `:e`, substitution, and `:number` commands. Yanks also copy to the terminal clipboard when OSC 52 is supported.
451
+ See [Integrated editor](editor.md#Choosing_an_editor_mode) for complete keymaps and mode-specific behavior.
383
452
 
384
453
  ## Session settings
385
454
 
@@ -502,6 +571,31 @@ Do not put shared or published API keys in this file.
502
571
 
503
572
  Put global engineering principles in `PRINCIPLES.md` beside your config file, usually `~/.kward/PRINCIPLES.md`. Kward appends this file to its built-in system instructions when present. Existing config-directory `AGENTS.md` files are still read as a legacy alias when `PRINCIPLES.md` is absent.
504
573
 
574
+ ## Replacement system prompt
575
+
576
+ Set `system_prompt.file` to use a file as the entire system prompt. In replacement mode Kward does not append its built-in instructions, global principles, memory context, personas, plugin context, skills, or workspace `AGENTS.md` guidance.
577
+
578
+ ```json
579
+ {
580
+ "system_prompt": {
581
+ "file": "prompts/local-minimal.md",
582
+ "include_principles": false
583
+ }
584
+ }
585
+ ```
586
+
587
+ Relative paths are resolved beside `config.json`. The file is sent to the configured model and can be recorded in session prompt snapshots, so do not place secrets in it. Use `kward sysprompt` to inspect the exact active prompt.
588
+
589
+ To retain Kward's normal prompt while omitting only global `PRINCIPLES.md` (and its legacy config-directory `AGENTS.md` fallback), configure:
590
+
591
+ ```json
592
+ {
593
+ "system_prompt": {
594
+ "include_principles": false
595
+ }
596
+ }
597
+ ```
598
+
505
599
  ## Workspace AGENTS.md
506
600
 
507
601
  By default, Kward does not inject the full workspace `AGENTS.md` into every request. When a workspace `AGENTS.md` exists, Kward injects a compact instruction telling the model to read it for repository-related tasks before analyzing or modifying project files.
@@ -528,11 +622,26 @@ Workspace guardrails are enabled by default. File tools such as `read_file`, `wr
528
622
  }
529
623
  ```
530
624
 
531
- This is not a sandbox setting. Shell commands already run as your OS user from the workspace directory and can access anything that user can access.
625
+ Workspace guardrails limit Kward file tools; they are not an operating-system sandbox and do not constrain arbitrary shell commands. See [Command sandboxing](sandboxing.md) to apply an opt-in operating-system boundary to model-requested `run_shell_command` workers.
626
+
627
+ ## Command sandboxing
628
+
629
+ Sandboxing is off by default. Use `/sandbox` to inspect or change the mode and child-network access. For additional writable roots or Git metadata protection, edit the `sandbox` config directly. `sandbox.mode` accepts `off`, `read_only`, or `workspace_write`; `sandbox.network` defaults to `deny`, and `sandbox.protect_git_metadata` defaults to `true`.
630
+
631
+ ```json
632
+ {
633
+ "sandbox": {
634
+ "mode": "workspace_write",
635
+ "network": "deny"
636
+ }
637
+ }
638
+ ```
639
+
640
+ When Kward cannot enforce a requested non-off mode, it denies the command rather than running it unrestricted. Current support and limits are documented in [Command sandboxing](sandboxing.md).
532
641
 
533
642
  ## Permissions
534
643
 
535
- Permissions are off by default. When enabled, Kward evaluates model-requested tools before execution. This is a permission policy, not an operating-system sandbox: permitted shell commands still run with your user account's access.
644
+ Permissions are off by default. When enabled, the permission policy decides whether a model-requested tool can start. It is not an operating-system sandbox: permitted shell commands still run with your user account's access.
536
645
 
537
646
  ```json
538
647
  {
@@ -1,8 +1,8 @@
1
1
  # Context budgeting and token savings
2
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.
3
+ Kward handles context budgeting automatically. Instead of reading whole files and pasting every byte of command output into the conversation, it gathers evidence in small steps, compacts noisy output, and keeps the original data available when needed.
4
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.
5
+ This guide explains why Kward sometimes reads an outline or a small section before opening a whole file, how it handles large tool output, and how you can inspect the resulting token savings.
6
6
 
7
7
  ## Why this matters
8
8
 
@@ -14,9 +14,9 @@ Kward's goal is not to build a heavyweight semantic index. It is to stay lightwe
14
14
  find likely files -> inspect outlines/previews -> read exact ranges -> read full files only when needed
15
15
  ```
16
16
 
17
- ## The current workflow
17
+ ## How Kward gathers context
18
18
 
19
- When Kward needs code context, it should usually start with one of these tools:
19
+ When Kward needs code context, it usually starts with one of these tools:
20
20
 
21
21
  - `context_for_task` for a compact task-shaped bundle.
22
22
  - `summarize_file_structure` for a source outline of one file.
@@ -27,11 +27,11 @@ Then it can escalate only as needed:
27
27
  - `read_file` with `mode: "range"`, `offset`, and `limit` for exact sections.
28
28
  - `read_file` with `mode: "full"` only when focused context is not enough.
29
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.
30
+ This happens automatically during normal work; you do not need to choose the tools or modes yourself.
31
31
 
32
32
  ## Focused task context
33
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:
34
+ `context_for_task` gives Kward a focused starting point. It accepts a task and, optionally, a set of paths and a byte budget, then returns a compact bundle with:
35
35
 
36
36
  - ranked candidate files (by term-matching score),
37
37
  - source outlines for each file,
data/doc/context-tools.md CHANGED
@@ -64,7 +64,7 @@ Constraints:
64
64
  - Each option requires both `label` and `description`.
65
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
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.
67
+ The question picker is available only in frontends that support structured questions. In the terminal, it lets Kward ask a concise multiple-choice question instead of guessing. RPC clients receive the same flow through UI events; see the [RPC question bridge](rpc.md) for notification and response details.
68
68
 
69
69
  Good uses:
70
70
 
@@ -72,7 +72,7 @@ Good uses:
72
72
  - confirming an ambiguous scope,
73
73
  - selecting a provider, model, or behavior when no default is obvious.
74
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.
75
+ Structured questions are most useful when the answer would materially change the implementation or avoid a risky assumption—not for every small uncertainty.
76
76
 
77
77
  ## Availability
78
78