kward 0.83.0 → 0.85.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 (193) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +102 -15
  3. data/CONTRIBUTING.md +74 -0
  4. data/Gemfile.lock +8 -2
  5. data/README.md +21 -1
  6. data/Rakefile +46 -2
  7. data/SECURITY.md +31 -0
  8. data/doc/agent-tools.md +13 -1
  9. data/doc/api.md +21 -2
  10. data/doc/composer.md +2 -2
  11. data/doc/configuration.md +95 -25
  12. data/doc/editor.md +28 -13
  13. data/doc/extensibility.md +2 -1
  14. data/doc/files.md +8 -4
  15. data/doc/getting-started.md +3 -0
  16. data/doc/git.md +3 -1
  17. data/doc/pan.md +25 -15
  18. data/doc/permissions.md +4 -4
  19. data/doc/platform-support.md +48 -0
  20. data/doc/plugins.md +464 -15
  21. data/doc/rpc.md +154 -16
  22. data/doc/sandboxing.md +11 -5
  23. data/doc/security.md +10 -3
  24. data/doc/session-management.md +5 -4
  25. data/doc/shell.md +62 -45
  26. data/doc/tabs.md +6 -2
  27. data/doc/transports.md +15 -0
  28. data/doc/troubleshooting.md +12 -2
  29. data/doc/usage.md +9 -6
  30. data/doc/workspace-tools.md +9 -0
  31. data/examples/plugins/space_invaders.rb +1 -1
  32. data/examples/plugins/stardate_footer.rb +2 -2
  33. data/examples/plugins/telegram/plugin.rb +1 -1
  34. data/kward.gemspec +5 -4
  35. data/lib/kward/agent.rb +30 -14
  36. data/lib/kward/cli/auth_commands.rb +34 -13
  37. data/lib/kward/cli/commands.rb +83 -62
  38. data/lib/kward/cli/compaction.rb +9 -3
  39. data/lib/kward/cli/doctor.rb +39 -17
  40. data/lib/kward/cli/hook_commands.rb +22 -12
  41. data/lib/kward/cli/interactive_turn.rb +48 -7
  42. data/lib/kward/cli/plugins.rb +81 -12
  43. data/lib/kward/cli/project_skills_commands.rb +8 -4
  44. data/lib/kward/cli/prompt_interface.rb +52 -5
  45. data/lib/kward/cli/rendering.rb +18 -9
  46. data/lib/kward/cli/runtime_helpers.rb +228 -71
  47. data/lib/kward/cli/sessions.rb +9 -5
  48. data/lib/kward/cli/settings/menus.rb +745 -0
  49. data/lib/kward/cli/settings/model.rb +327 -0
  50. data/lib/kward/cli/settings.rb +6 -1055
  51. data/lib/kward/cli/slash_commands.rb +56 -17
  52. data/lib/kward/cli/tabs.rb +244 -33
  53. data/lib/kward/cli/tool_summaries.rb +14 -0
  54. data/lib/kward/{cli_transcript_formatter.rb → cli/transcript_formatter.rb} +14 -7
  55. data/lib/kward/cli/worktrees.rb +65 -2
  56. data/lib/kward/cli.rb +70 -30
  57. data/lib/kward/compactor.rb +18 -7
  58. data/lib/kward/config/core.rb +389 -0
  59. data/lib/kward/config/extensions.rb +96 -0
  60. data/lib/kward/config/prompts.rb +313 -0
  61. data/lib/kward/config/settings.rb +250 -0
  62. data/lib/kward/config_files.rb +14 -994
  63. data/lib/kward/conversation.rb +31 -2
  64. data/lib/kward/image_attachments.rb +1 -1
  65. data/lib/kward/model/client.rb +36 -24
  66. data/lib/kward/model/copilot_models.rb +2 -2
  67. data/lib/kward/model/model_info.rb +20 -3
  68. data/lib/kward/{openrouter_model_cache.rb → model/openrouter_model_cache.rb} +3 -3
  69. data/lib/kward/model/payloads.rb +12 -3
  70. data/lib/kward/model/provider_catalog.rb +5 -0
  71. data/lib/kward/model/stream_parser.rb +20 -4
  72. data/lib/kward/model/typesafe_client.rb +78 -0
  73. data/lib/kward/pan/index.html.erb +3 -3
  74. data/lib/kward/pan/server.rb +33 -10
  75. data/lib/kward/permissions/policy.rb +6 -2
  76. data/lib/kward/plugin_registry.rb +2 -659
  77. data/lib/kward/plugins/actions.rb +453 -0
  78. data/lib/kward/plugins/chat_contract.rb +121 -0
  79. data/lib/kward/{plugin_chat_runtime.rb → plugins/chat_runtime.rb} +62 -18
  80. data/lib/kward/plugins/host.rb +232 -0
  81. data/lib/kward/plugins/registry.rb +1190 -0
  82. data/lib/kward/plugins/resources.rb +206 -0
  83. data/lib/kward/plugins/turn_request.rb +36 -0
  84. data/lib/kward/plugins/ui.rb +219 -0
  85. data/lib/kward/prompt_interface/composer_renderer.rb +44 -40
  86. data/lib/kward/prompt_interface/composer_state.rb +33 -24
  87. data/lib/kward/prompt_interface/editor/auto_indent.rb +24 -22
  88. data/lib/kward/prompt_interface/editor/controller.rb +30 -33
  89. data/lib/kward/prompt_interface/editor/endwise.rb +13 -4
  90. data/lib/kward/prompt_interface/editor/markdown_code_block.rb +136 -0
  91. data/lib/kward/prompt_interface/editor/modes/vibe.rb +289 -44
  92. data/lib/kward/prompt_interface/editor/renderer.rb +108 -6
  93. data/lib/kward/prompt_interface/editor/runner.rb +362 -0
  94. data/lib/kward/prompt_interface/editor/runner_state.rb +78 -0
  95. data/lib/kward/prompt_interface/editor/scratchpad_languages.rb +74 -0
  96. data/lib/kward/prompt_interface/editor/scratchpad_runner.rb +182 -0
  97. data/lib/kward/prompt_interface/editor/state.rb +11 -11
  98. data/lib/kward/prompt_interface/editor/syntax_highlighter.rb +68 -6
  99. data/lib/kward/prompt_interface/editor/vibe_state.rb +3 -3
  100. data/lib/kward/prompt_interface/file_overlay.rb +71 -15
  101. data/lib/kward/prompt_interface/key_handler.rb +67 -0
  102. data/lib/kward/prompt_interface/layout.rb +1 -1
  103. data/lib/kward/prompt_interface/overlay_renderer.rb +7 -5
  104. data/lib/kward/prompt_interface/plugin_ui_requests.rb +82 -0
  105. data/lib/kward/prompt_interface/project_browser.rb +415 -14
  106. data/lib/kward/prompt_interface/runtime_state.rb +56 -2
  107. data/lib/kward/prompt_interface/screen.rb +11 -4
  108. data/lib/kward/prompt_interface/selection_prompt.rb +3 -1
  109. data/lib/kward/prompt_interface/slash_overlay.rb +19 -4
  110. data/lib/kward/prompt_interface/transcript_renderer.rb +12 -7
  111. data/lib/kward/prompt_interface.rb +151 -27
  112. data/lib/kward/prompts/commands.rb +3 -2
  113. data/lib/kward/prompts.rb +1 -1
  114. data/lib/kward/{adaptive_pty_output_sink.rb → pty/adaptive_output_sink.rb} +1 -1
  115. data/lib/kward/pty/detached_run.rb +44 -0
  116. data/lib/kward/{interactive_pty_runner.rb → pty/interactive_runner.rb} +104 -30
  117. data/lib/kward/{local_command_runner.rb → pty/local_command_runner.rb} +1 -1
  118. data/lib/kward/{local_pty_command_runner.rb → pty/local_pty_runner.rb} +3 -9
  119. data/lib/kward/{pty_output_sink.rb → pty/output_sink.rb} +52 -0
  120. data/lib/kward/{pty_transcript_normalizer.rb → pty/transcript_normalizer.rb} +1 -1
  121. data/lib/kward/rpc/plugin_chat_manager.rb +30 -10
  122. data/lib/kward/rpc/prompt_bridge.rb +25 -0
  123. data/lib/kward/rpc/server.rb +91 -12
  124. data/lib/kward/rpc/session_manager.rb +147 -44
  125. data/lib/kward/rpc/session_tree_rows.rb +2 -2
  126. data/lib/kward/rpc/tool_metadata.rb +1 -1
  127. data/lib/kward/rpc/transcript_normalizer.rb +7 -3
  128. data/lib/kward/sandbox/command_runner.rb +1 -1
  129. data/lib/kward/{session_catalog.rb → sessions/catalog.rb} +1 -1
  130. data/lib/kward/{session_store.rb → sessions/store.rb} +9 -9
  131. data/lib/kward/{session_tree_nodes.rb → sessions/tree_nodes.rb} +3 -3
  132. data/lib/kward/{session_tree_renderer.rb → sessions/tree_renderer.rb} +4 -4
  133. data/lib/kward/{session_tree_tool_display.rb → sessions/tree_tool_display.rb} +1 -1
  134. data/lib/kward/{ekwsh.rb → shell/kwsh.rb} +38 -19
  135. data/lib/kward/shell/kwshrc.rb +233 -0
  136. data/lib/kward/{persistent_shell_session.rb → shell/persistent_session.rb} +121 -28
  137. data/lib/kward/{shell_prompt.rb → shell/prompt.rb} +2 -0
  138. data/lib/kward/{shell_prompt_session.rb → shell/prompt_session.rb} +1 -1
  139. data/lib/kward/skills/trust_store.rb +1 -1
  140. data/lib/kward/tabs/driver.rb +194 -0
  141. data/lib/kward/{tab_store.rb → tabs/store.rb} +2 -2
  142. data/lib/kward/{ansi.rb → terminal/ansi.rb} +110 -10
  143. data/lib/kward/{clipboard.rb → terminal/clipboard.rb} +1 -1
  144. data/lib/kward/{terminal_image_support.rb → terminal/image_support.rb} +1 -1
  145. data/lib/kward/{terminal_keys.rb → terminal/keys.rb} +12 -0
  146. data/lib/kward/terminal/text.rb +121 -0
  147. data/lib/kward/text_matcher.rb +18 -0
  148. data/lib/kward/tools/base.rb +18 -0
  149. data/lib/kward/tools/context_for_task.rb +15 -6
  150. data/lib/kward/tools/edit_file.rb +9 -6
  151. data/lib/kward/tools/git_commit.rb +13 -7
  152. data/lib/kward/tools/list_directory.rb +4 -4
  153. data/lib/kward/tools/open_editor.rb +41 -0
  154. data/lib/kward/tools/plugin_tool.rb +41 -0
  155. data/lib/kward/tools/prepare_shell_command.rb +1 -1
  156. data/lib/kward/tools/read_file.rb +7 -6
  157. data/lib/kward/tools/registry.rb +109 -17
  158. data/lib/kward/tools/run_shell_command.rb +10 -8
  159. data/lib/kward/tools/search/code.rb +1 -1
  160. data/lib/kward/tools/summarize_file_structure.rb +5 -5
  161. data/lib/kward/tools/tool_call.rb +3 -1
  162. data/lib/kward/tools/typesafe_evaluate.rb +81 -0
  163. data/lib/kward/tools/workspace_targets.rb +58 -0
  164. data/lib/kward/tools/write_file.rb +9 -6
  165. data/lib/kward/{export_path.rb → transcripts/export_path.rb} +1 -1
  166. data/lib/kward/{markdown_transcript.rb → transcripts/markdown_transcript.rb} +2 -2
  167. data/lib/kward/transport/contracts.rb +200 -0
  168. data/lib/kward/transport/gateway.rb +79 -35
  169. data/lib/kward/transport/plugin_chat_gateway.rb +3 -2
  170. data/lib/kward/transport.rb +1 -200
  171. data/lib/kward/version.rb +1 -1
  172. data/lib/kward/{workspace_factory.rb → workspace/factory.rb} +2 -2
  173. data/lib/kward/{project_files.rb → workspace/files.rb} +2 -2
  174. data/lib/kward/{git_worktree_manager.rb → workspace/git_worktree_manager.rb} +28 -0
  175. data/lib/kward/{workspace.rb → workspace/workspace.rb} +3 -3
  176. data/templates/default/kward_navigation.rb +1 -0
  177. data/templates/default/layout/html/footer.erb +10 -0
  178. data/templates/default/layout/html/headers.erb +23 -0
  179. data/templates/default/layout/html/layout.erb +2 -2
  180. data/templates/default/layout/html/setup.rb +41 -2
  181. metadata +94 -47
  182. data/lib/kward/scratchpad_runner.rb +0 -56
  183. data/lib/kward/tab_driver.rb +0 -90
  184. /data/lib/kward/{editor_prompt.rb → cli/editor_prompt.rb} +0 -0
  185. /data/lib/kward/{editor_prompt_session.rb → cli/editor_prompt_session.rb} +0 -0
  186. /data/lib/kward/{diff_view_mode.rb → prompt_interface/editor/diff_view_mode.rb} +0 -0
  187. /data/lib/kward/{editor_mode.rb → prompt_interface/editor/editor_mode.rb} +0 -0
  188. /data/lib/kward/{session_diff.rb → sessions/diff.rb} +0 -0
  189. /data/lib/kward/{session_naming.rb → sessions/naming.rb} +0 -0
  190. /data/lib/kward/{session_trash.rb → sessions/trash.rb} +0 -0
  191. /data/lib/kward/{terminal_sequences.rb → terminal/sequences.rb} +0 -0
  192. /data/lib/kward/{transcript_export.rb → transcripts/transcript_export.rb} +0 -0
  193. /data/lib/kward/{path_guard.rb → workspace/path_guard.rb} +0 -0
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 should start with `/settings`, `/login`, `/model`, or `/reasoning` inside Kward. Edit JSON directly when you need an advanced setting, an integration, or a reproducible configuration.
4
4
 
5
- On first start, Kward creates the file when it does not exist. The starter config records defaults for personas, memory, the composer, editor, overlays, web search, update checks, sessions, skills, MCP, and workspace guardrails. Provider-specific model defaults are added only when you choose a provider or model.
5
+ On first start, Kward creates the file when it does not exist. The starter config records defaults for personas, memory, the composer, editor, overlays, web search, update checks, sessions, skills, MCP, plugins, and workspace guardrails. Provider-specific model defaults are added only when you choose a provider or model.
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
 
@@ -50,6 +50,27 @@ Add trusted local Model Context Protocol servers under `mcpServers`:
50
50
 
51
51
  See [MCP servers](mcp.md) for setup, supported fields, and security notes.
52
52
 
53
+ ### Plugin configuration
54
+
55
+ Identified plugins read immutable configuration from the `plugins` object under
56
+ their stable ID:
57
+
58
+ ```json
59
+ {
60
+ "plugins": {
61
+ "com.example.issues": {
62
+ "endpoint": "https://issues.example.com"
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ Plugin-managed state is stored privately under `plugin_state/<plugin-id>` in the
69
+ active config directory. Credentials can come from private plugin config or the
70
+ plugin's documented environment variables; do not commit them to shared config
71
+ files. See [Plugins](plugins.md#Plugin_identity_and_host_services) for the host
72
+ API, secret lookup order, and storage example.
73
+
53
74
  ### Transport plugins
54
75
 
55
76
  Transport plugin settings live under `transports` and are scoped by the
@@ -128,7 +149,7 @@ By default, Kward stores user data under `~/.kward`. Common files and directorie
128
149
  ~/.kward/anthropic_auth.json
129
150
  ~/.kward/github_auth.json
130
151
  ~/.kward/PRINCIPLES.md
131
- ~/.kward/ekwsh.yml
152
+ ~/.kward/kwshrc
132
153
  ~/.kward/prompts/
133
154
  ~/.kward/skills/
134
155
  ~/.kward/plugins/
@@ -169,24 +190,51 @@ Project-local hooks can also live in `.kward/hooks.json`, but Kward loads them o
169
190
 
170
191
  ## Embedded shell config
171
192
 
172
- 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.
193
+ The embedded Kward shell (`/shell`, internally `kwsh`) reads the shell-style rc files `~/.kward/kwshrc` and `~/.kwshrc`, in that order. When `KWARD_CONFIG_PATH` is set, the first path is beside that config file instead. Later rc entries override earlier aliases and exported variables.
173
194
 
174
- Example:
195
+ Example rc file:
196
+
197
+ ```sh
198
+ alias ll='ls -la'
199
+ alias gs="git status --short"
200
+ export BUNDLE_WITHOUT=production
201
+ export PATH="$HOME/bin:$PATH"
202
+ source ~/.kward/kwsh-aliases
203
+ ```
204
+
205
+ Only declarative `alias`, `export`, and `source` (or `.`) directives are handled. `source` parses the referenced file without executing it, resolving relative paths from the containing rc file. Other shell scripting is ignored for now.
206
+
207
+ ### Shell-agent model
175
208
 
176
- ```yaml
177
- env:
178
- FORCE_COLOR: "1"
179
- CLICOLOR_FORCE: "1"
209
+ The transient shell assistant normally follows the active conversation's model and reasoning effort. Override those defaults in the main JSON configuration:
180
210
 
181
- aliases:
182
- ll: "ls -la"
183
- gs: "git status --short"
184
- gd: "git diff --color=always"
211
+ ```json
212
+ {
213
+ "shell": {
214
+ "agent": {
215
+ "provider": "openrouter",
216
+ "model": "openai/gpt-5.6-sol",
217
+ "reasoning_effort": "none"
218
+ }
219
+ }
220
+ }
221
+ ```
222
+
223
+ The optional `provider` selects a different backend for the transient shell assistant. Use the lowercase configuration IDs listed in [Model providers](providers.md). When it is omitted, the shell assistant follows the active conversation's provider, model, and reasoning effort. If a provider is explicitly configured without a model or reasoning effort, Kward uses that provider's defaults rather than inheriting values from the active conversation.
224
+
225
+ Environment variables take precedence over the JSON settings:
226
+
227
+ ```sh
228
+ export KWSH_PROVIDER="openrouter"
229
+ export KWSH_MODE="openai/gpt-5.6-sol"
230
+ export KWSH_REASONING="none"
185
231
  ```
186
232
 
187
- `env` values are applied when shell mode starts, after Kward's conservative color defaults. `/shell` keeps one persistent local interactive shell process per tab. 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.
233
+ `KWSH_PROVIDER` selects the shell-agent provider, `KWSH_MODE` selects its model, and `KWSH_REASONING` selects its reasoning effort. Empty values are ignored.
188
234
 
189
- `aliases` expand the first word of a command once. For example, `ll lib` runs `ls -la lib`. Configured aliases are available both inside `/shell` and after the normal composer's `!` prefix, including command-name Tab completion. Built-in shell commands such as `cd`, `pwd`, `export`, `unset`, `alias`, `capture`, `clear`, `pty`, and `exit` take precedence over aliases inside `/shell`. External commands receive an interactive PTY by default. Prefix a submitted line with `?` inside `/shell` to ask the transient shell assistant about the current command output or state. An alias value can begin with `capture` when its `/shell` output should use the configured timeout, output limit, and transcript sanitization. Leading-`!` alias invocations are always interactive, so Kward removes a leading `capture` or legacy `pty` mode marker from the expanded alias before execution. Run `alias` inside `ekwsh` to list configured aliases. Aliases created at runtime with that built-in belong only to the current `/shell` session and are not available to `!command` input.
235
+ `export` values are applied when shell mode starts, after Kward's conservative color defaults, and are also available to leading-`!` commands. Keys must be valid environment-variable names; invalid keys are ignored. Values support shell quoting and simple `$VAR`/`${VAR}` expansion. `/shell` keeps one persistent local interactive shell process per tab.
236
+
237
+ `alias` entries expand the first word of a command once. For example, `alias ll='ls -la'` makes `ll lib` run `ls -la lib`. Configured aliases are available both inside `/shell` and after the normal composer's `!` prefix, including command-name Tab completion. Built-in shell commands such as `cd`, `pwd`, `export`, `unset`, `alias`, `capture`, `clear`, `pty`, and `exit` take precedence over aliases inside `/shell`. External commands receive an interactive PTY by default. Prefix a submitted line with `?` inside `/shell` to ask the transient shell assistant about the current command output or state. An alias value can begin with `capture` when its `/shell` output should use the configured timeout, output limit, and transcript sanitization. Leading-`!` alias invocations are always interactive, so Kward removes a leading `capture` or legacy `pty` mode marker from the expanded alias before execution. Run `alias` inside `kwsh` to list configured aliases. Aliases created at runtime with that built-in belong only to the current `/shell` session and are not available to `!command` input.
190
238
 
191
239
  ## Provider and model settings
192
240
 
@@ -236,7 +284,7 @@ Model settings:
236
284
 
237
285
  `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.
238
286
 
239
- 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.
287
+ OpenAI-hosted models do not expose their raw reasoning tokens. Kward displays the reasoning summaries and visible Codex commentary they provide. Set `codex_show_raw_reasoning` to `true` only for a backend that emits raw Codex `reasoning_text`; it defaults to `false` because raw reasoning can include internal or unstable model output.
240
288
 
241
289
  `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.
242
290
 
@@ -248,6 +296,8 @@ Defaults:
248
296
  - Copilot: `gpt-5-mini`
249
297
  - Reasoning effort: `medium`
250
298
 
299
+ The OpenAI/Codex and Copilot model choices include `gpt-6-astra`. GPT-6 Astra has a 1,050,000-token context window and supports `low`, `medium`, `high`, `xhigh`, and `max` reasoning effort; it does not support `none`.
300
+
251
301
  The Anthropic model choices include `claude-fable-5`, `claude-opus-5`, and `claude-sonnet-5`. Fable and Opus availability depends on the logged-in account and organization. Selecting a model without access returns an Anthropic provider error. Kward keeps Sonnet 5 as its default because it supports both Pro and Max subscriptions; select Opus 5 explicitly when it is available on the account.
252
302
 
253
303
  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.
@@ -399,14 +449,15 @@ Vibe `:prompt` uses a dedicated transient editor agent. Configure its model and
399
449
  {
400
450
  "editor": {
401
451
  "agent": {
402
- "model": "gpt-5.5",
452
+ "provider": "anthropic",
453
+ "model": "claude-sonnet-5",
403
454
  "reasoning_effort": "medium"
404
455
  }
405
456
  }
406
457
  }
407
458
  ```
408
459
 
409
- These settings use the active tab's provider. If either value is omitted, Kward falls back to the active tab's value and then the client default. Editor-agent prompts and tool activity are kept out of the normal transcript and session history; the editor remains visible with a spinner while the transient turn runs.
460
+ The optional `provider` selects a different backend for the transient editor assistant. Use the lowercase configuration IDs listed in [Model providers](providers.md). When it is omitted, the editor assistant follows the active tab's provider, model, and reasoning effort. `KWARD_EDITOR_PROVIDER` can override the JSON provider for one-off runs. If a provider is explicitly configured without a model or reasoning effort, Kward uses that provider's defaults rather than inheriting values from the active tab. Editor-agent prompts and tool activity are kept out of the normal transcript and session history; the editor remains visible with a spinner while the transient turn runs.
410
461
 
411
462
  The integrated Git and session diff viewers support unified and side-by-side layouts:
412
463
 
@@ -420,6 +471,27 @@ The integrated Git and session diff viewers support unified and side-by-side lay
420
471
 
421
472
  `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.
422
473
 
474
+ ### Editor runners
475
+
476
+ The editor can run the current in-memory buffer for supported scratchpad languages and normal files. It never saves a normal file automatically before running. Configure runner binaries under `editor.runners`; omitted entries use the built-in defaults.
477
+
478
+ ```json
479
+ {
480
+ "editor": {
481
+ "runners": {
482
+ "node": { "binary": "node" },
483
+ "python": { "binary": ".venv/bin/python" },
484
+ "shell": { "binary": "/bin/bash" },
485
+ "go": { "binary": "/usr/local/go/bin/go" }
486
+ }
487
+ }
488
+ }
489
+ ```
490
+
491
+ `binary` may be an executable name resolved through `PATH`, an absolute path, or a relative path resolved from the active workspace. JavaScript and TypeScript use the `node` runner. TypeScript `.ts` buffers require a Node version with built-in TypeScript support; Node strips erasable types but does not type-check the buffer or read `tsconfig.json`. Node's built-in support does not run `.tsx` buffers. Runner processes execute directly without a shell.
492
+
493
+ The initial runnable languages are Ruby, JavaScript, TypeScript, Python, Shell, Lua, Julia, Elixir, Crystal, Go, and Swift. Other highlighted languages remain editor-only until they have a suitable execution model.
494
+
423
495
  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.
424
496
 
425
497
  Auto-indent and matching-pair insertion are enabled by default. To disable either feature:
@@ -532,22 +604,20 @@ Manual `/compact [instructions]` works even when auto-compaction is disabled.
532
604
 
533
605
  ## Pan mode
534
606
 
535
- `kward pan` starts a LAN-reachable web UI and requires HTTP Basic Auth. Configure credentials before starting it:
607
+ `kward pan` starts a local web UI and requires HTTP Basic Auth. Configure credentials before starting it:
536
608
 
537
609
  ```json
538
610
  {
539
611
  "pan_mode": {
540
- "host": "0.0.0.0",
541
- "port": 8765,
542
612
  "username": "kward",
543
613
  "password": "choose-a-private-password"
544
614
  }
545
615
  }
546
616
  ```
547
617
 
548
- `host` defaults to `0.0.0.0` and `port` defaults to `8765`. Kward fails to start pan mode unless `username` and `password` are configured.
618
+ `host` defaults to `127.0.0.1` and `port` defaults to `8765`. Set `host` to `0.0.0.0` only when you intentionally want access from another device on a trusted LAN. Kward prints a warning for every non-loopback binding because Pan uses plain HTTP without TLS.
549
619
 
550
- These credentials are stored in plaintext config. Use a private, user-specific password and do not share the config file. Pan mode exposes the agent's file, shell, web, and configured extension tools to anyone on the LAN who has the credentials, so use it only on trusted networks. See [Pan mode](pan.md) for the full browser workflow, session behavior, security guidance, and limitations.
620
+ Kward fails to start Pan unless `username` and either `password` or the `KWARD_PAN_PASSWORD` environment variable are configured. Config-file credentials are stored in plaintext; use a unique password and do not share the file. Pan exposes the agent's file, shell, web, and configured extension tools to anyone who can connect and authenticate. See [Pan mode](pan.md) for the full browser workflow, session behavior, security guidance, and limitations.
551
621
 
552
622
  ## Web search
553
623
 
@@ -681,9 +751,9 @@ Available modes are:
681
751
 
682
752
  | Mode | Behavior |
683
753
  | --- | --- |
684
- | `ask` | Read-only tools run normally; file changes, shell commands, web tools, and MCP tools need approval. |
685
- | `workspace-write` | File changes within `write_scopes` run without approval; shell and network tools still need approval. |
686
- | `read-only` | Denies file changes, shell commands, web tools, and MCP tools. |
754
+ | `ask` | Read-only tools run normally; file changes, shell commands, web tools, MCP tools, and plugin tools need approval. |
755
+ | `workspace-write` | File changes within `write_scopes` run without approval; shell, network, MCP, and plugin tools still need approval. |
756
+ | `read-only` | Denies file changes, shell commands, web tools, MCP tools, and plugin tools. |
687
757
  | `deny-by-default` | Denies risky tools unless an `allow` rule matches. |
688
758
 
689
759
  `allow`, `ask`, and `deny` rules are arrays of objects matching `tool`, `path`, `host`, `command`, or `source`. Deny rules always take precedence, then ask, then allow. Use `write_scopes` to restrict writes in `workspace-write` mode:
data/doc/editor.md CHANGED
@@ -23,7 +23,7 @@ cd ~/code/my-project
23
23
  kward edit lib/kward/agent.rb
24
24
  ```
25
25
 
26
- Kward uses the current directory as the workspace, opens the file in the integrated editor, and exits when you close the editor. Use `--working-directory` when the file belongs to another workspace:
26
+ Kward uses the current directory as the workspace, opens the file in the integrated editor, and exits when you close the editor. During an interactive chat session, you can also ask Kward to open a workspace file for you; it uses the `open_editor` tool when that capability is available. Opening the editor does not change or save the file unless you choose to do so. Use `--working-directory` when the file belongs to another workspace:
27
27
 
28
28
  ```bash
29
29
  kward --working-directory ~/code/my-project edit lib/kward/agent.rb
@@ -43,18 +43,23 @@ For a nested project tree, run:
43
43
  /files
44
44
  ```
45
45
 
46
- In the tree browser, use `↑`/`↓` to move, `←`/`→` to collapse or expand directories, `Enter` to toggle a directory or open a file, `Tab` or `/` to search, `i` to show or hide Git-ignored files, `@` to insert the selected file as an `@path` mention, and `Esc` to close. When you open a file from `/files`, quitting the editor returns to the browser at the same position.
46
+ In the tree browser, use `↑`/`↓` to move, `←`/`→` to collapse or expand directories, `Enter` to toggle a directory or open a file, `Tab` or `/` to search, `i` to show or hide Git-ignored files, `f` to create a file, `d` to create a directory, `r` to rename the selected entry, `Backspace` to delete after confirmation, `@` to insert the selected file as an `@path` mention, and `Esc` to close. Create and rename names are entered in the prompt and must be single entry names. When you open a file from `/files`, quitting the editor returns to the browser at the same position.
47
47
 
48
48
  For an unsaved buffer, open a scratchpad:
49
49
 
50
50
  ```text
51
51
  /scratchpad
52
52
  /scratchpad markdown
53
- /scratchpad ruby
53
+ /scratchpad js
54
+ /scratchpad python
55
+ /scratchpad help
54
56
  ```
55
57
 
56
- Scratchpads start as virtual editor buffers named `scratchpad.txt`, `scratchpad.md`, or `scratchpad.rb`. In Vibe mode, save one to a real file with `:w filename`.
57
- Ruby scratchpads can run with `:run` in Vibe mode or `Ctrl+R` in Modern mode; Kward executes the buffer and writes combined output after `__END__`, replacing any previous output there.
58
+ Scratchpads accept canonical language names and familiar file-extension shortcuts. For example, `js` selects JavaScript, `py` selects Python, `rb` selects Ruby, `yml` selects YAML, `cs` selects C#, and `cpp` selects C++. Use `/scratchpad help` to print the complete list of names and aliases.
59
+
60
+ All 26 built-in syntax-highlighted languages are available: Ruby, ERB, 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. Markdown buffers also apply the tagged language highlighter, auto-indentation, and endwise behavior inside fenced code blocks, such as a fence tagged `ruby` or `js`; unknown tags remain readable as plain text. Scratchpads use a matching virtual filename such as `scratchpad.js` or `scratchpad.py`; in Vibe mode, save one to a real file with `:w filename`.
61
+
62
+ Supported editable buffers can run with `:run` in Vibe mode or `Ctrl+R` in Modern mode. This works for both scratchpads and normal editor files. Kward runs the current in-memory buffer, including unsaved changes, without saving the file automatically. It opens a read-only output pane in the lower half of the editor with the captured output, exit status, and duration. Drag with the mouse to make a virtual selection inside the output, then press `Ctrl+C` or `Cmd+C` to copy it (`y` in Vibe mode). Only the selected output text is copied; pane borders are excluded. `Cmd+C` requires the terminal to forward the Command key to Kward. Press `Esc` to return to editing, use the arrow or page keys to scroll, and press `Ctrl+C` without a selection to cancel a running buffer. Runnable languages are Ruby, JavaScript, TypeScript, Python, Shell, Lua, Julia, Elixir, Crystal, Go, and Swift; other languages currently provide editing and highlighting only.
58
63
 
59
64
  ```ruby
60
65
  puts "foo"
@@ -63,14 +68,14 @@ __END__
63
68
  foo
64
69
  ```
65
70
 
66
- The next run receives the current `__END__` section as Ruby `DATA`, then replaces it with the new output.
71
+ The next run receives the current `__END__` section as Ruby `DATA`; the output window is refreshed without changing the source buffer.
67
72
 
68
73
  You can also type a relative path yourself and press `Enter`. If the file does not exist, Kward asks whether to create it.
69
74
 
70
75
  A few things to know:
71
76
 
72
77
  - `$` only opens the editor when it is the first character in the composer.
73
- - `/scratchpad` opens a plain-text scratchpad; pass `markdown` or `ruby` to pick another mode.
78
+ - `/scratchpad` opens a plain-text scratchpad; pass a language name or shortcut to select syntax highlighting. `/scratchpad help` lists the available choices.
74
79
  - Once a file or scratchpad opens, the composer becomes the editor.
75
80
  - Save or quit to return to normal chat.
76
81
  - If the file changed on disk while you were editing, Kward asks before overwriting it.
@@ -252,7 +257,7 @@ Emacs mode is for users who prefer classic Emacs-style non-modal editing. Save a
252
257
 
253
258
  Vibe mode is a modal editor built for Kward, inspired by classic Vi and Vim. If you already know Vim, you will feel at home here. Files open in normal mode, where keys run commands. Press `i`, `a`, `o`, or another insert command to type text, then press `Esc` to return to normal mode.
254
259
 
255
- It supports a compact but practical modal-editing set: counts, operators with motions, visual selections, visual block edits, marks, registers, macros, search, repeat (`.`), Ruby-aware navigation, and `:` commands. It is not a full Vim clone — there are no splits or ex-mode scripting — but it covers everyday keyboard editing inside the conversation.
260
+ It supports a compact but practical modal-editing set: counts, operators with motions, visual selections, multi-cursor and visual block edits, marks, registers, macros, search, repeat (`.`), Ruby-aware navigation, and `:` commands. It is not a full Vim clone — there are no splits or ex-mode scripting — but it covers everyday keyboard editing inside the conversation.
256
261
 
257
262
  The status line always shows the current mode (`NORMAL`, `INSERT`, `VISUAL`, `REPLACE`, or `:`) so you never lose track of where you are.
258
263
 
@@ -288,7 +293,7 @@ Use normal mode for movement, operators, marks, registers, macros, search, and c
288
293
  | `Ctrl+K` | Move up by indentation level |
289
294
  | `Ctrl+F` | Page down |
290
295
  | `Ctrl+B` | Page up |
291
- | `Ctrl+D` | Half page down |
296
+ | `Ctrl+D` | Select the next occurrence and enter insert mode |
292
297
  | `Ctrl+U` | Half page up |
293
298
  | `Ctrl+E` | Scroll down one line |
294
299
  | `Ctrl+Y` | Scroll up one line |
@@ -354,17 +359,20 @@ Use normal mode for movement, operators, marks, registers, macros, search, and c
354
359
 
355
360
  ### Visual mode
356
361
 
357
- Visual mode uses the same motion language as normal mode where practical. Start characterwise visual mode with `v`, linewise mode with `V`, or visual block mode with `Ctrl+V`.
362
+ Visual mode uses the same motion language as normal mode where practical. Arrow keys and plain `h`/`j`/`k`/`l` extend the selection. Start characterwise visual mode with `v`, linewise mode with `V`, or visual block mode with `Ctrl+V`.
358
363
 
359
364
  | Key | Action |
360
365
  | ----------------------- | ----------------------------------------------- |
361
366
  | `o` | Switch active end of visual selection |
367
+ | `Ctrl+h` / `Ctrl+l` | Outdent / indent selected lines |
368
+ | `Ctrl+j` / `Ctrl+k` | Move selected lines down / up |
362
369
  | `G` / `gg` / `N`motion | Extend visual selection with counts/motions |
363
370
  | `%`, `f`/`F`/`t`/`T` | Extend visual selection with advanced motions |
364
371
  | `iw` / `a(` / `ip` | Select visual text objects |
365
372
  | `>` / `<` | Indent / outdent selected lines |
366
373
  | `=` | Reindent selected lines |
367
- | `I` / `A` | Insert / append text across visual block lines |
374
+ | `I` / `A` | Insert cursors at the start / end of each selected line |
375
+ | `Ctrl+D` | Add the next occurrence of a characterwise selection |
368
376
  | `J` | Join selected lines |
369
377
  | `~` / `u` / `U` | Swapcase / lowercase / uppercase selection |
370
378
  | `/` / `?` / `n` / `N` | Extend visual selection with search |
@@ -388,7 +396,7 @@ Vibe insert mode also supports readline-style shortcuts for efficient editing wi
388
396
  | `Ctrl+E` | Move to end of line |
389
397
  | `Ctrl+B` | Move left |
390
398
  | `Ctrl+F` | Move right |
391
- | `Ctrl+D` | Delete character at cursor |
399
+ | `Ctrl+D` | Select the next occurrence |
392
400
  | `Ctrl+K` | Kill to end of line |
393
401
  | `Ctrl+U` | Kill to start of line |
394
402
  | `Ctrl+W` | Delete word before cursor |
@@ -416,7 +424,7 @@ Typing an opening bracket (`(`, `[`, `{`) or quote (`"`, `'`, `` ` ``) in visual
416
424
 
417
425
  ### Command mode
418
426
 
419
- Enter command mode with `:` from normal mode. Type a command and press `Enter`. Press `Esc` or `Ctrl+C` to cancel.
427
+ Enter command mode with `:` from normal mode. Type a command and press `Enter`. Press `Esc` or `Ctrl+C` to cancel. From visual mode, `:` starts the command with the selected line range (`'<,'>`), as in Vim.
420
428
 
421
429
  | Command | Action |
422
430
  | ------- | ------------------------------------------ |
@@ -426,6 +434,13 @@ Enter command mode with `:` from normal mode. Type a command and press `Enter`.
426
434
  | `:wq` | Save and quit |
427
435
  | `:x` | Save if changed, then quit |
428
436
  | `:N` | Go to line `N` |
437
+ | `:run` | Run the complete current supported editor buffer; inside a Markdown fence, run that block into its `<output>` field |
438
+ | `:run all` | Run every runnable Markdown fenced block sequentially into its `<output>` field |
439
+ | `:prompt instruction` | Ask the editor agent to update the buffer |
440
+ | `:s/a/b/g` | Substitute `a` with `b` |
441
+ | `:'<,'>s/a/b/g` | Substitute only across the visual selection |
442
+
443
+ Visual line ranges apply to `:s` and `:run`. For `:run`, select the body or complete fence of one Markdown code block with a runnable language, or place the cursor inside that block without making a selection; Kward runs that block and inserts or replaces a formatted `<output>` field without opening the output pane. `:run all` executes every runnable fenced block in document order, skips unlabeled or unsupported fences, continues after failures, and writes each runner error into that block's output field. An existing output field is searched for after the block until the next code fence, so inline fields are reformatted too. Without a matching output field, one is inserted directly below the block with one blank line. Other commands retain their normal save, navigation, file, and quit behavior.
429
444
 
430
445
  ### Vibe design notes
431
446
 
data/doc/extensibility.md CHANGED
@@ -14,6 +14,7 @@ Start simple. Most users only need `PRINCIPLES.md`, workspace `AGENTS.md`, and m
14
14
  | Task-specific reusable instructions | skills |
15
15
  | Different tone or role | [personas](personas.md) |
16
16
  | Local Ruby behavior or integrations | plugins |
17
+ | Slash commands that run a turn with system-level instructions | [plugin model-turn requests](plugins.md) |
17
18
  | External messaging or event integration | transport plugins |
18
19
  | Deterministic runtime policy or automation | lifecycle hooks |
19
20
 
@@ -89,7 +90,7 @@ Hooks are deterministic automation and policy. They are not model instructions.
89
90
 
90
91
  Use plugins when text instructions are not enough and you need Ruby code to run locally.
91
92
 
92
- Plugins can add slash commands, prompt context, footer UI, transcript observers, RPC-visible commands, and external transports. Transport plugins can connect external conversations to normal Kward sessions or explicitly transport-capable plugin chats; they remain distinct from plugin-owned tabs.
93
+ Plugins can add legacy or schema-typed slash commands, namespaced typed RPC actions, model-callable tools, structured frontend-neutral UI, prompt context, footer UI, transcript observers, plugin-owned tabs, and external transports. Identified plugins also receive namespaced configuration, private durable storage, secret lookup, logging, lifecycle callbacks, cooperative background tasks, and managed cleanup through a shared host. Transport plugins can connect external conversations to normal Kward sessions or explicitly transport-capable plugin chats; they remain distinct from plugin-owned tabs.
93
94
 
94
95
  Use `kward transport list` and `kward transport status` to inspect registered transports. Run a foreground transport with `kward transport run NAME`.
95
96
 
data/doc/files.md CHANGED
@@ -12,7 +12,7 @@ From an interactive Kward session, run:
12
12
  /files
13
13
  ```
14
14
 
15
- Kward opens the project file browser. Use the arrow keys or `j`/`k` to move through the tree, then press `Enter` on a file to open it in the integrated editor. Supported images (PNG, JPEG, GIF, and WebP) open as read-only inline previews when the terminal supports Kitty or iTerm2 image sequences.
15
+ Kward opens the project file browser. Use the arrow keys or `j`/`k` to move through the tree, then press `Enter` on a file to open it in the integrated editor. Supported images (PNG, JPEG, GIF, and WebP) open as read-only inline previews when the terminal supports Kitty or iTerm2 image sequences. Use `f` for a new file, `d` for a new directory, or `r` to rename the selected file or directory; type the single entry name in the prompt and press `Enter`.
16
16
 
17
17
  When you quit the editor or close an image preview, Kward returns to the file browser at the same position so you can keep browsing nearby files.
18
18
 
@@ -40,7 +40,11 @@ Outside Git, Kward scans the workspace directory and skips common noisy director
40
40
  | `/` | Start search |
41
41
  | `Backspace` | Delete the last search character |
42
42
  | `i` | Show or hide Git-ignored files |
43
- | `Esc` | Leave search; press again to close the browser |
43
+ | `f` | Create a file beneath the selected directory, or beside the selected file |
44
+ | `d` | Create a directory beneath the selected directory, or beside the selected file |
45
+ | `r` | Rename the selected file or directory; the prompt starts with its current name |
46
+ | `Backspace` | Start deletion confirmation for the selected file or directory |
47
+ | `Esc` | Leave search or name entry; cancel deletion; press again to close the browser |
44
48
  | `Q` | Close an image preview |
45
49
  | `+` / `-` | Zoom an image preview in / out |
46
50
  | `@` | Insert the selected file as an `@path` mention |
@@ -93,7 +97,7 @@ See [Integrated editor](editor.md) for editor modes, save/quit keys, search, sel
93
97
 
94
98
  Kward remembers the expanded folders, selected path, and Git-ignored file visibility for each workspace. The next time you open `/files` in the same project, it restores the browser close to where you left it.
95
99
 
96
- Search itself is temporary. Closing search returns to the normal tree, and closing the browser leaves your chat session intact.
100
+ Search itself is temporary. Closing search returns to the normal tree, and closing the browser leaves your chat session intact. Create and rename operations reject existing names rather than replacing them; name entry accepts only one file or directory name, not a path. Backspace requires confirmation before deleting. Non-empty directories display an additional warning and require a second confirmation before recursive deletion.
97
101
 
98
102
  ## Image previews
99
103
 
@@ -103,5 +107,5 @@ Image previews are read-only and replace the file-list overlay while leaving the
103
107
 
104
108
  - `/files` is only available in the interactive prompt.
105
109
  - It opens files inside the current workspace.
106
- - It is a focused project browser, not a full file manager: it does not rename, move, copy, or delete files.
110
+ - It is a focused project browser, not a full file manager: it does not move or copy files.
107
111
  - Ignored Git files are hidden by default when Git can provide the file list; press `i` in the tree view to show them.
@@ -7,6 +7,7 @@ This page gets you from install to a first useful chat.
7
7
  ## Requirements
8
8
 
9
9
  - Ruby 3.4 or newer.
10
+ - macOS or Linux. WSL is best effort; native Windows is not currently supported. See [Platform support](platform-support.md).
10
11
  - Credentials for one model provider. The easiest setup is `kward login` or `/login` inside Kward.
11
12
  - Bundler only if you run Kward from a source checkout.
12
13
 
@@ -96,6 +97,8 @@ Find where user authentication is implemented and summarize the flow.
96
97
 
97
98
  Kward can read files, suggest edits, apply changes, and run commands from the workspace. Existing files must be read in the current conversation before Kward can edit them.
98
99
 
100
+ The composer footer highlights the two main discovery shortcuts: type `/` to browse commands and `@` to find and mention project files. If no model provider is connected, the startup screen points directly to `/login` and `/model` before you submit a prompt.
101
+
99
102
  ## Ask one question and exit
100
103
 
101
104
  For quick tasks, pass the prompt directly:
data/doc/git.md CHANGED
@@ -111,7 +111,9 @@ If the working tree is clean when you run `/git`, the overlay shows `No uncommit
111
111
 
112
112
  When an active worktree tab receives an explicit request to commit, the agent can use the model-facing `git_commit` tool. It runs Git in the trusted host process so linked-worktree metadata can be updated without granting arbitrary shell commands write access to shared `.git` metadata.
113
113
 
114
- The tool requires a commit message and can receive an optional list of workspace-relative paths. If paths are omitted, all current changes in the active worktree are included. Generic `run_shell_command` Git commands remain sandboxed and cannot replace this operation. It is exposed only for active interactive worktree tabs; RPC sessions do not currently support worktree bindings.
114
+ The tool requires a commit message and can receive an optional list of paths relative to its selected worktree. It uses the active linked worktree by default. In an active worktree tab, `target: "origin"` selects the verified original repository worktree, allowing the same agent to finish a conflicted merge or commit explicitly requested origin changes without switching tabs. If paths are omitted, all current changes in the selected worktree are included.
115
+
116
+ Selecting `origin` does not add a separate approval prompt; the normal configured tool-permission policy applies exactly as it does for `active`. Generic `run_shell_command` Git commands remain sandboxed and cannot replace `git_commit`. The tool is exposed only for active interactive worktree tabs; RPC sessions do not currently support worktree bindings.
115
117
 
116
118
  ## Notes and limitations
117
119
 
data/doc/pan.md CHANGED
@@ -8,39 +8,41 @@ Use it when you want to work from another browser or device on a trusted network
8
8
 
9
9
  Pan is a small local HTTP server, not a hosted service. The machine running Kward performs model requests, reads and edits workspace files, runs tools, and stores sessions.
10
10
 
11
- Pan requires HTTP Basic Auth. Add credentials to `~/.kward/config.json`:
11
+ Pan requires HTTP Basic Auth. Add a username and password to `~/.kward/config.json`:
12
12
 
13
13
  ```json
14
14
  {
15
15
  "pan_mode": {
16
- "host": "0.0.0.0",
17
- "port": 8765,
18
16
  "username": "kward",
19
17
  "password": "choose-a-long-private-password"
20
18
  }
21
19
  }
22
20
  ```
23
21
 
24
- The defaults are:
22
+ Pan listens on `127.0.0.1:8765` by default, so only browsers on the same machine can connect. Kward refuses to start Pan unless a username and password are available.
23
+
24
+ To keep the password out of `config.json`, omit `password` and provide it when starting Pan:
25
25
 
26
- - `host`: `0.0.0.0`, which listens on all network interfaces.
27
- - `port`: `8765`.
26
+ ```bash
27
+ KWARD_PAN_PASSWORD="choose-a-long-private-password" kward pan
28
+ ```
28
29
 
29
- Kward refuses to start Pan unless both `username` and `password` are configured. The password is stored as plaintext in your config file, so do not reuse an important password or share the file.
30
+ When stored in `config.json`, the password is plaintext. Do not reuse an important password or share the file. Environment variables avoid config-file storage but may still be visible to processes or shell-history tooling on your machine.
30
31
 
31
- For access from the same machine only, bind to loopback instead:
32
+ To use Pan from another device on a trusted LAN, explicitly listen on all interfaces:
32
33
 
33
34
  ```json
34
35
  {
35
36
  "pan_mode": {
36
- "host": "127.0.0.1",
37
+ "host": "0.0.0.0",
37
38
  "port": 8765,
38
- "username": "kward",
39
- "password": "choose-a-long-private-password"
39
+ "username": "kward"
40
40
  }
41
41
  }
42
42
  ```
43
43
 
44
+ Then start Pan with `KWARD_PAN_PASSWORD` or add the password to that configuration. Kward prints a plain-HTTP exposure warning whenever Pan binds to a non-loopback address.
45
+
44
46
  ## Start Pan
45
47
 
46
48
  Run Pan from the project it should control:
@@ -56,12 +58,14 @@ Or select the workspace explicitly:
56
58
  kward --working-directory ~/code/my-project pan
57
59
  ```
58
60
 
59
- Kward prints the listening URL, workspace, and initial session path. With the default LAN binding, it detects and prints the machine's routed LAN address when available. Open port `8765` at that address, for example:
61
+ Kward prints the listening URL, workspace, and initial session path. With the default loopback binding, open:
60
62
 
61
63
  ```text
62
- http://192.168.1.25:8765/
64
+ http://127.0.0.1:8765/
63
65
  ```
64
66
 
67
+ With an explicit `0.0.0.0` LAN binding, Kward detects and prints the machine's routed LAN address when available, such as `http://192.168.1.25:8765/`.
68
+
65
69
  Your browser asks for the configured Basic Auth username and password.
66
70
 
67
71
  Press `Ctrl+C` in the server terminal to stop Pan. Closing a browser tab does not stop the server or an active turn.
@@ -83,6 +87,12 @@ Press Return to send. Use Shift+Return for a new line. The composer grows with m
83
87
 
84
88
  Prompts are accepted while another turn is running. Pan puts them into a single queue and executes them sequentially. The status below the composer shows whether Kward is working and how many prompts remain queued.
85
89
 
90
+ Plugin slash commands that request model turns (such as `/iddqd`) are not
91
+ supported in Pan: its composer submits ordinary prompts, not plugin commands.
92
+ Use the interactive TUI or RPC `turns/start` for these commands. The `/transcript`
93
+ response reports `capabilities.pluginCommandTurns.supported: false` so browser
94
+ clients can make this limitation explicit.
95
+
86
96
  ## Work with sessions
87
97
 
88
98
  Pan saves conversations through the same workspace-scoped session store as the interactive CLI. The session sidebar shows up to 50 recent sessions with their title, modified time, and message count.
@@ -142,8 +152,8 @@ Pan exposes powerful agent tools through ordinary HTTP. Basic Auth protects ever
142
152
 
143
153
  Use these precautions:
144
154
 
145
- - Run it only on a network and machine you trust.
146
- - Prefer `127.0.0.1` when remote access is unnecessary.
155
+ - Keep the default `127.0.0.1` binding when remote access is unnecessary.
156
+ - Bind to `0.0.0.0` only on a network and machine you trust.
147
157
  - Do not expose the port directly to the public internet.
148
158
  - Do not put Pan behind a public tunnel unless you provide a properly secured TLS/authentication boundary and understand the risk.
149
159
  - Use a unique password and protect `config.json`.
data/doc/permissions.md CHANGED
@@ -22,7 +22,7 @@ In `ask` mode, Kward allows ordinary read-only tools and asks before the agent:
22
22
  - writes or edits a workspace file,
23
23
  - runs `run_shell_command`,
24
24
  - searches or fetches content on the web,
25
- - calls an MCP tool.
25
+ - calls an MCP or model-callable plugin tool.
26
26
 
27
27
  When Kward needs approval in the interactive CLI, it shows the complete tool arguments in an overlay. For example, a write request includes the file path and content.
28
28
 
@@ -75,8 +75,8 @@ Set `permissions.mode` to one of these values:
75
75
 
76
76
  | Mode | Good for | Default behavior |
77
77
  | --- | --- | --- |
78
- | `ask` | Interactive supervised work | Asks before file changes, shell commands, web tools, and MCP tools. |
79
- | `workspace-write` | Routine edits in selected paths | Allows file changes in `write_scopes`; still asks before shell, web, and MCP tools. |
78
+ | `ask` | Interactive supervised work | Asks before file changes, shell commands, web tools, MCP tools, and plugin tools. |
79
+ | `workspace-write` | Routine edits in selected paths | Allows file changes in `write_scopes`; still asks before shell, web, MCP, and plugin tools. |
80
80
  | `read-only` | Code review and investigation | Denies risky tools by default. |
81
81
  | `deny-by-default` | Automation or tightly controlled runs | Denies risky tools unless an `allow` rule matches. |
82
82
 
@@ -110,7 +110,7 @@ Use `allow`, `ask`, and `deny` arrays to describe exceptions. A rule can match t
110
110
  - `path` — the file-tool path supplied by the model;
111
111
  - `command` — the requested shell command text;
112
112
  - `host` — the host in a `fetch_content` or `fetch_raw` URL;
113
- - `source` — currently useful for `mcp` tools.
113
+ - `source` — currently useful for `mcp` and `plugin` tools.
114
114
 
115
115
  Patterns support `*` within a path segment and `**` across directories. Rule matching is case-sensitive.
116
116
 
@@ -0,0 +1,48 @@
1
+ # Platform support
2
+
3
+ Kward is a terminal application built around Ruby, PTYs, filesystem tools, and operating-system command boundaries. The core agent works across Unix-like systems, while a few terminal and sandbox features depend on the host platform.
4
+
5
+ ## Support matrix
6
+
7
+ | Platform | Support level | Notes |
8
+ | --- | --- | --- |
9
+ | macOS | Supported | Primary support for the interactive TUI, PTY handoff, editor, shell, Pan, RPC, and Seatbelt command sandboxing. |
10
+ | Linux | Supported | Interactive TUI, PTY handoff, editor, shell, Pan, and RPC are supported. Bubblewrap is required for OS-enforced command sandboxing. |
11
+ | WSL | Best effort | Core CLI behavior should work under a current WSL environment. Clipboard, browser launch, inline images, PTY controls, and host integration vary by terminal and Windows configuration. |
12
+ | Native Windows | Unsupported | Kward currently depends on Unix-style PTY and process behavior. Use WSL rather than a native Windows Ruby installation. |
13
+
14
+ Kward requires Ruby 3.4 or newer. CI exercises Ruby 3.4 and the current Ruby release on Linux. Releases are developed and used on macOS as well.
15
+
16
+ ## Terminal expectations
17
+
18
+ Use a modern UTF-8 terminal with ANSI control-sequence support. Basic chat works without optional graphics protocols. Some features depend on terminal capabilities:
19
+
20
+ - modified keys such as Shift+Return and Ctrl+Tab may be intercepted by the terminal;
21
+ - inline images require iTerm2 or a recognized Kitty-compatible terminal;
22
+ - full-screen child applications temporarily own the terminal through PTY handoff;
23
+ - Nerd Font project-file icons are opt-in because Kward cannot detect the configured font.
24
+
25
+ See [Interactive composer](composer.md) for keyboard fallbacks and [Embedded shell](shell.md) for PTY behavior.
26
+
27
+ ## Sandboxing
28
+
29
+ Command sandboxing is opt-in and platform-specific:
30
+
31
+ - macOS uses Seatbelt profiles;
32
+ - Linux uses Bubblewrap and requires a host configuration that permits unprivileged namespaces;
33
+ - WSL support depends on the Linux distribution and host namespace policy;
34
+ - native Windows has no supported command sandbox backend.
35
+
36
+ When Kward cannot enforce a requested non-off sandbox mode, it fails closed rather than silently running the model-requested command without that boundary. See [Command sandboxing](sandboxing.md) for setup and exact limits.
37
+
38
+ ## Reporting a platform problem
39
+
40
+ Run these commands first:
41
+
42
+ ```bash
43
+ ruby --version
44
+ kward --version
45
+ kward doctor
46
+ ```
47
+
48
+ When opening a bug report, include the operating system, terminal, Ruby version, Kward version, and the smallest reproduction. Remove credentials, private paths, repository content, and sensitive command output before posting logs.