kward 0.81.0 → 0.83.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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -0
  3. data/Gemfile.lock +2 -2
  4. data/README.md +1 -1
  5. data/Rakefile +44 -4
  6. data/doc/agent-tools.md +1 -0
  7. data/doc/composer.md +2 -2
  8. data/doc/configuration.md +18 -3
  9. data/doc/editor.md +20 -10
  10. data/doc/files.md +12 -5
  11. data/doc/permissions.md +1 -0
  12. data/doc/releasing.md +79 -38
  13. data/doc/rpc.md +2 -2
  14. data/doc/sandboxing.md +5 -1
  15. data/doc/security.md +2 -2
  16. data/doc/shell.md +42 -18
  17. data/doc/tabs.md +3 -0
  18. data/doc/usage.md +3 -2
  19. data/kward.gemspec +1 -1
  20. data/lib/kward/adaptive_pty_output_sink.rb +183 -0
  21. data/lib/kward/agent.rb +1 -0
  22. data/lib/kward/auth/anthropic_oauth.rb +7 -7
  23. data/lib/kward/cli/git.rb +5 -1
  24. data/lib/kward/cli/interactive_turn.rb +101 -19
  25. data/lib/kward/cli/rendering.rb +14 -2
  26. data/lib/kward/cli/runtime_helpers.rb +252 -46
  27. data/lib/kward/cli/settings.rb +5 -13
  28. data/lib/kward/cli/slash_commands.rb +12 -1
  29. data/lib/kward/cli/tabs.rb +71 -9
  30. data/lib/kward/cli.rb +12 -0
  31. data/lib/kward/compaction/token_estimator.rb +12 -6
  32. data/lib/kward/config_files.rb +17 -0
  33. data/lib/kward/editor_prompt.rb +46 -0
  34. data/lib/kward/editor_prompt_session.rb +28 -0
  35. data/lib/kward/ekwsh.rb +70 -10
  36. data/lib/kward/image_attachments.rb +98 -15
  37. data/lib/kward/interactive_pty_runner.rb +25 -19
  38. data/lib/kward/model/client.rb +1 -17
  39. data/lib/kward/model/model_info.rb +3 -2
  40. data/lib/kward/model/payloads.rb +0 -2
  41. data/lib/kward/persistent_shell_session.rb +750 -0
  42. data/lib/kward/project_files.rb +18 -5
  43. data/lib/kward/prompt_interface/composer_controller.rb +3 -3
  44. data/lib/kward/prompt_interface/composer_renderer.rb +28 -1
  45. data/lib/kward/prompt_interface/editor/auto_indent.rb +3 -0
  46. data/lib/kward/prompt_interface/editor/controller.rb +75 -6
  47. data/lib/kward/prompt_interface/editor/modes/emacs.rb +2 -2
  48. data/lib/kward/prompt_interface/editor/modes/modern.rb +4 -0
  49. data/lib/kward/prompt_interface/editor/modes/vibe.rb +12 -6
  50. data/lib/kward/prompt_interface/editor/renderer.rb +1 -0
  51. data/lib/kward/prompt_interface/editor/state.rb +11 -0
  52. data/lib/kward/prompt_interface/editor/word_completion.rb +124 -0
  53. data/lib/kward/prompt_interface/file_overlay.rb +21 -7
  54. data/lib/kward/prompt_interface/git_prompt.rb +1 -1
  55. data/lib/kward/prompt_interface/key_handler.rb +30 -0
  56. data/lib/kward/prompt_interface/overlay_renderer.rb +1 -0
  57. data/lib/kward/prompt_interface/project_browser.rb +192 -8
  58. data/lib/kward/prompt_interface/prompt_renderer.rb +15 -6
  59. data/lib/kward/prompt_interface/question_prompt.rb +1 -1
  60. data/lib/kward/prompt_interface/runtime_state.rb +5 -1
  61. data/lib/kward/prompt_interface/screen.rb +40 -20
  62. data/lib/kward/prompt_interface/selection_prompt.rb +5 -5
  63. data/lib/kward/prompt_interface/transcript_renderer.rb +4 -4
  64. data/lib/kward/prompt_interface.rb +159 -32
  65. data/lib/kward/prompts/commands.rb +1 -0
  66. data/lib/kward/pty_output_sink.rb +45 -0
  67. data/lib/kward/pty_transcript_normalizer.rb +93 -0
  68. data/lib/kward/rpc/auth_manager.rb +1 -1
  69. data/lib/kward/rpc/server.rb +2 -1
  70. data/lib/kward/session_catalog.rb +87 -0
  71. data/lib/kward/session_store.rb +94 -5
  72. data/lib/kward/shell_prompt.rb +50 -0
  73. data/lib/kward/shell_prompt_session.rb +58 -0
  74. data/lib/kward/terminal_image_support.rb +116 -0
  75. data/lib/kward/terminal_keys.rb +1 -0
  76. data/lib/kward/terminal_sequences.rb +43 -0
  77. data/lib/kward/tools/prepare_shell_command.rb +28 -0
  78. data/lib/kward/tools/registry.rb +63 -5
  79. data/lib/kward/tools/replace_editor_buffer.rb +30 -0
  80. data/lib/kward/tools/run_shell_command.rb +24 -6
  81. data/lib/kward/version.rb +1 -1
  82. data/templates/default/layout/html/layout.erb +1 -1
  83. metadata +15 -4
  84. data/.github/workflows/ci.yml +0 -48
  85. data/.github/workflows/pages.yml +0 -48
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2033aa9b07468c6668842a3b0ba51ef73cb0c1c58db95927c1159668129e345
4
- data.tar.gz: 0f7c86a02ccf5e76f01adf3a8d654b3bd559ef27c93f6479dfd6724401427435
3
+ metadata.gz: 678c9e9bb188e6c3d065dfde6b97c9ec5c31b29b178b40d69b0397b5200eb2a8
4
+ data.tar.gz: 3e09cb3d11ff6018ecc75e3eb31e8745e72e534dba7a4c3711a488451d353fcc
5
5
  SHA512:
6
- metadata.gz: 934c63dbcde19c9eba5dbdfb843a5cbb82a873d73371746d3db19c5698c27aa53ecef3820bb7099a928e077f05d04178190e4ddafef3ff8ed9e82aa7233c2d75
7
- data.tar.gz: 05ac5a0a3a695f9b49c56059915e642511c85f0dcaa68e406f0b470763b589497a92950416a0f7eddb2a69b304c9b7f6bcef3bcbea49cedd8032b06871c3cfba
6
+ metadata.gz: 7f4247a32300deff0906c95c10d7312aa6303108956596f16d9f2c6d2d4fc444b5ef377751f47dbd2157b041710d855c44a981a1a22f8a562c79203afe8b65ed
7
+ data.tar.gz: d93d09126d221c05d7ef0e931f46ccfaa4a84450e6eb5695dbea653d8b9de99bb27bc7fb070b323c74160477fd328f0be3cd972d544b45e3ea90ffbeb79cb087
data/CHANGELOG.md CHANGED
@@ -4,6 +4,62 @@ All notable changes to Kward will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.83.0] - 2026-08-28
8
+
9
+ ### Added
10
+
11
+ - Added `?` shell prompts for transient, context-aware assistance inside `/shell`, including shared shell-state commands and prepare-without-execute command drafts.
12
+ - Added `Ctrl+.` in Modern editor mode to open an in-editor prompt line for communicating with the dedicated editor agent.
13
+ - Added Vibe `:prompt <instruction>` support, allowing the agent to inspect and replace the active in-memory editor buffer without saving it automatically.
14
+ - Added current-buffer word completion to the integrated editor, with repeated Tab presses cycling nearby matches and existing smart indentation retained when no match exists.
15
+ - Added Claude Opus 5 to the Anthropic model picker with its 1M context window and high-reasoning metadata.
16
+ - Added an `i` toggle to the `/files` browser for showing Git-ignored files, which remain hidden by default.
17
+
18
+ ### Changed
19
+
20
+ - `/shell` now keeps one persistent local shell process per tab so shell variables, functions, aliases, and directory changes are shared by user and agent commands.
21
+ - Shell-agent turns use a transient per-tab context and receive only bounded, sanitized output after an explicit `?` request; ordinary shell output remains outside model context.
22
+ - Shell-agent transcript output is now retained as bounded, tab-local runtime state so it survives tab switches without entering session history.
23
+ - Vibe editor-agent turns now use an isolated, configurable model/reasoning context, remain visible with a status-line spinner, and stay out of normal chat transcripts and session history.
24
+ - Removed the obsolete GPT-5.6 Luna Responses Lite compatibility workaround so Luna requests retain Kward's identity and standard Codex payload.
25
+
26
+ ### Fixed
27
+
28
+ - Made persistent shell command cancellation and timeouts recover by restarting an unresponsive embedded shell, and stabilized raw-input coverage across platforms.
29
+ - Restored full-screen Git pagers and immediate key/Ctrl+C forwarding for interactive `/shell` commands by removing Kward's ambient `GIT_PAGER=cat` default and putting host input in raw mode during persistent-shell handoff, while keeping paging suppressed for captured and shell-agent commands.
30
+ - Fixed Claude subscription OAuth authorization and token-exchange requests by removing unsupported subscription scopes and the nonstandard `code` query parameter, and by forwarding the OAuth state to the token endpoint.
31
+ - Installed and enabled Bubblewrap during release verification so Linux worktree tests use the same sandbox setup as normal CI, added manual recovery for existing release tags, and made publication wait for and attach the canonical RubyGems artifact after trusted-publishing attestation.
32
+ - Fixed automatic context compaction so Codex response items are included in token estimates and long tool-call turns are checked before each model request.
33
+
34
+ ## [0.82.0] - 2026-08-23
35
+
36
+ ### Added
37
+
38
+ - Added `script/release` for validated, one-command release preparation from an argument or standard input, including changelog/version updates, preflight checks, an annotated tag, and an atomic push.
39
+ - Added a tag-triggered GitHub Actions release workflow using RubyGems trusted publishing, published-artifact checksum verification, changelog-based GitHub Releases, and safe reruns after partial publication.
40
+ - Added `+` and `-` controls for resizing inline `/files` image previews within the available overlay space.
41
+ - Added inline read-only previews for PNG, JPEG, GIF, and WebP files opened from `/files` in terminals that support Kitty or iTerm2 image sequences, with local conversion for Kitty-compatible terminals when needed.
42
+
43
+ ### Changed
44
+
45
+ - Excluded GitHub workflow and local release-script files from packaged gems and added explicit release metadata and package-content checks.
46
+ - Changed interactive PTY handoff to render conservative line/progress output above a frozen composer, with a permanent switch to exclusive full-terminal passthrough when the child emits screen-oriented or unknown controls.
47
+ - Kept safe, normalized shell output as explicit tab-local transient state so completed `/shell` and `!command` output can be reconstructed after tab switches without entering session history or model context.
48
+
49
+ ### Fixed
50
+
51
+ - Made the test environment explicitly disable terminal color and made unified diff-viewer tests select that mode explicitly, keeping release preflight assertions deterministic across terminal capabilities and widths.
52
+ - Kept `/files` image previews bounded within a fully cleared, bordered file-list overlay above the visible composer and preserved their aspect ratio in Kitty-compatible terminals.
53
+ - Fixed inline image protocol detection and viewer handoff for Ghostty and other Kitty-compatible terminals by retrying inconclusive probes, honoring recognized Kitty hints, suppressing Kitty acknowledgements, and using valid, chunked graphics sequences.
54
+ - Kept synchronized-output updates such as Homebrew downloads in the inline PTY region instead of resetting the cursor through an unnecessary exclusive handoff.
55
+ - Retained the final visible state of carriage-return and horizontal-cursor progress output from commands such as `git push` and Homebrew when reconstructing the transcript after PTY handback.
56
+ - Cached rebuildable session-list summaries so opening `/session` no longer reparses every unchanged conversation log, while retaining automatic fallback for existing, changed, or corrupt session data.
57
+ - Refreshed composer status immediately after model runtime changes and `/git` returns, so selected model details and Git dirty-state color do not remain stale until another input.
58
+ - Kept echoed passwords, OTPs, and other child input out of transient tab state by stopping safe PTY output retention before the first forwarded input byte.
59
+ - Reconstructed safe transient shell output as part of the PTY ownership handback frame, avoiding an extra clear and redraw after commands such as `ls`.
60
+ - Preserved the active `/shell` prompt and composer when Ctrl+L clears transient shell output, and avoided a redundant preliminary redraw.
61
+ - Reconstructed the complete Kward screen after interactive PTY handoff, including failure paths, instead of relying on the child process cursor position.
62
+
7
63
  ## [0.81.0] - 2026-08-20
8
64
 
9
65
  ### Added
@@ -62,6 +118,7 @@ All notable changes to Kward will be documented in this file.
62
118
  - Added Git worktree bindings for normal interactive session tabs. `/tab worktree` can move a tab into a strict linked-worktree workspace after research, preserve its transcript, warn about dirty origin changes, and keep the branch available when explicitly detached.
63
119
  - Added the active worktree `git_commit` model tool, allowing explicitly requested agent commits through the trusted host-side Git workflow without widening the shell sandbox.
64
120
  - Added `/tab worktree merge` for explicitly merging a clean worktree branch into the branch checked out in its original workspace, plus `/tab worktree merge abort` for conflicted merges.
121
+ - Added `/worktree` as a concise alias for `/tab worktree` on the active tab.
65
122
  - Added `j`/`k` keyboard navigation to the `/files` project browser.
66
123
  - Added `h`/`l` keyboard navigation for collapsing and expanding `/files` directories.
67
124
  - Added `j`/`k` keyboard navigation to the `/git` changed-file overlay.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kward (0.81.0)
4
+ kward (0.83.0)
5
5
  base64
6
6
  nokogiri
7
7
  tiktoken_ruby
@@ -146,7 +146,7 @@ CHECKSUMS
146
146
  html-proofer (5.2.1) sha256=fdd958a7cbf9c3255fb96fe7cfc4e611f64e2706e469488a3326309ad007d2fd
147
147
  io-event (1.16.2) sha256=9f9cb0a96ea5c3850a672606c65f27bc96d7621399ef6196acbfe2be0cd1279c
148
148
  json (2.19.9) sha256=9b9025b7cdddafa38d316eca0b2358488e42d417045c1b90d216a9fefe46b79a
149
- kward (0.81.0)
149
+ kward (0.83.0)
150
150
  logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
151
151
  metrics (0.15.0) sha256=61ded5bac95118e995b1bc9ed4a5f19bc9814928a312a85b200abbdac9039072
152
152
  minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
data/README.md CHANGED
@@ -92,7 +92,7 @@ Extend and integrate:
92
92
  - [Plugins](doc/plugins.md): trusted Ruby plugins for commands, footer UI, prompt context, transcript events, and RPC clients.
93
93
  - [Lifecycle hooks](doc/lifecycle-hooks.md): deterministic runtime hooks for policy, approvals, automation, and command-hook integrations.
94
94
  - [RPC protocol](doc/rpc.md): JSON-RPC backend mode for trusted local UI clients.
95
- - [Releasing](doc/releasing.md): release checklist for RubyGems publishing.
95
+ - [Releasing](doc/releasing.md): prepare a version and publish it through RubyGems and GitHub Releases.
96
96
 
97
97
  Reference guides:
98
98
 
data/Rakefile CHANGED
@@ -1,5 +1,7 @@
1
+ require "bundler/gem_tasks"
1
2
  require "fileutils"
2
3
  require "html-proofer"
4
+ require "open3"
3
5
  require "rdoc/task"
4
6
  require "rubygems/package"
5
7
  require "webrick"
@@ -33,6 +35,36 @@ def packaged_gem_files(gem_name)
33
35
  gem.spec.files.sort
34
36
  end
35
37
 
38
+ def verify_release_metadata
39
+ version = Kward::VERSION
40
+ tag = "v#{version}"
41
+ changelog = File.read("CHANGELOG.md")
42
+ abort("CHANGELOG.md is missing a [#{version}] release heading") unless changelog.match?(/^## \[#{Regexp.escape(version)}\] - \d{4}-\d{2}-\d{2}$/)
43
+
44
+ if ENV["GITHUB_REF_TYPE"] == "tag" && ENV["GITHUB_REF_NAME"] != tag
45
+ abort("GitHub tag #{ENV["GITHUB_REF_NAME"]} does not match gem version #{version}")
46
+ end
47
+
48
+ tag_commit, tag_status = Open3.capture2e("git", "rev-parse", "--verify", "#{tag}^{commit}")
49
+ return unless tag_status.success?
50
+
51
+ head_commit = `git rev-parse HEAD`.strip
52
+ abort("Tag #{tag} does not point at HEAD") unless tag_commit.strip == head_commit
53
+ end
54
+
55
+ def verify_packaged_gem(gem_name)
56
+ files = packaged_gem_files(gem_name)
57
+ required = ["exe/kward", "lib/kward/version.rb"]
58
+ missing = required - files
59
+ abort("Packaged gem is missing: #{missing.join(", ")}") unless missing.empty?
60
+
61
+ forbidden_prefixes = [".github/", "script/", "test/", "plan/"]
62
+ forbidden = files.select { |file| forbidden_prefixes.any? { |prefix| file.start_with?(prefix) } }
63
+ abort("Packaged gem includes development files: #{forbidden.join(", ")}") unless forbidden.empty?
64
+
65
+ files
66
+ end
67
+
36
68
  def rewrite_yard_markdown_links
37
69
  guide_names = Dir.glob("doc/*.md").map { |path| File.basename(path, ".md") }
38
70
 
@@ -75,15 +107,23 @@ YARD::Rake::YardocTask.new do |yard|
75
107
  end
76
108
 
77
109
  namespace :release do
110
+ desc "Verify the version, changelog, and release tag agree"
111
+ task :verify do
112
+ verify_release_metadata
113
+ end
114
+
78
115
  desc "Run release checks and build a local gem"
79
- task preflight: [:test, "docs:check"] do
80
- gem_name = "kward-#{Kward::VERSION}.gem"
116
+ task preflight: ["release:verify", :test, "docs:check"] do
117
+ gem_name = File.join("pkg", "kward-#{Kward::VERSION}.gem")
81
118
  FileUtils.rm_f(gem_name)
82
- sh "gem", "build", "kward.gemspec"
83
- puts packaged_gem_files(gem_name)
119
+ Rake::Task["build"].invoke
120
+ puts verify_packaged_gem(gem_name)
84
121
  end
85
122
  end
86
123
 
124
+ Rake::Task["release:source_control_push"].enhance(["release:verify"])
125
+ Rake::Task["release:rubygem_push"].enhance(["release:verify"])
126
+
87
127
  namespace :docs do
88
128
  desc "Serve the built YARD documentation site locally and rebuild on changes"
89
129
  task serve: :build do
data/doc/agent-tools.md CHANGED
@@ -15,6 +15,7 @@ Tools also enforce important boundaries:
15
15
  | Category | Tools | Guide |
16
16
  | --- | --- | --- |
17
17
  | Workspace tools | `list_directory`, `read_file`, `context_for_task`, `context_budget_stats`, `summarize_file_structure`, `write_file`, `edit_file`, `run_shell_command` | [Workspace tools](workspace-tools.md) |
18
+ | Shell prompt tools | `run_shell_command`, `prepare_shell_command` (available only to the transient `?` shell assistant) | [Embedded shell](shell.md) |
18
19
  | Web tools | `web_search`, `fetch_content`, `fetch_raw` | [Web search](web-search.md) |
19
20
  | Code search | `code_search` | [Code search](code-search.md) |
20
21
  | Context and interaction tools | `read_skill`, `retrieve_tool_output`, `ask_user_question` | [Context tools](context-tools.md) |
data/doc/composer.md CHANGED
@@ -186,7 +186,7 @@ Example:
186
186
 
187
187
  If the cursor is at the start of an otherwise empty draft, Backspace removes the most recently added pending attachment. Submitting the draft clears its pending attachments.
188
188
 
189
- The active model must support image input. iTerm2 and Kitty-compatible terminals can render submitted images inline; other terminals still show attachment badges and send the image to the model without an inline preview.
189
+ The active model must support image input. iTerm2 and Kitty-compatible terminals can render submitted images inline; Kward uses active Kitty capability detection when running on a real TTY and falls back to conservative terminal hints otherwise. Other terminals still show attachment badges and send the image to the model without an inline preview.
190
190
 
191
191
  ## Understand composer status
192
192
 
@@ -213,4 +213,4 @@ If rendering becomes corrupted after resize or after an external program writes
213
213
 
214
214
  You can also press `Ctrl+L`; it rebuilds the durable current-tab view without deleting the conversation transcript, removing transient shell output. If a shortcut never reaches Kward, prefer its slash-command equivalent or change `composer.tab_keybindings` in `/settings`.
215
215
 
216
- External commands inside `/shell` and one-shot `!command` input receive an interactive PTY by default, so full-screen programs such as Vim or `less` temporarily own the terminal. Use `capture <command>` inside `/shell` or `/capture <command>` from the normal composer when output should remain in Kward's transcript instead.
216
+ External commands inside `/shell` and one-shot `!command` input receive an interactive PTY by default. They begin inline above a frozen composer, then switch to full-terminal passthrough if they emit screen-oriented or unknown terminal controls; full-screen programs such as Vim or `less` can therefore temporarily own the terminal. While Kward owns the shell composer, a leading `?` asks the transient shell assistant; it receives only bounded, sanitized output from the latest command. Use `capture <command>` inside `/shell` or `/capture <command>` from the normal composer for bounded, sanitized transcript output.
data/doc/configuration.md CHANGED
@@ -184,9 +184,9 @@ aliases:
184
184
  gd: "git diff --color=always"
185
185
  ```
186
186
 
187
- `env` values are applied when shell mode starts, after Kward's conservative color defaults. Keys must look like environment variable names (`A_Z`, digits after the first character, and underscores); invalid keys are ignored. Values are converted to strings.
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.
188
188
 
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 `ekwsh` 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. 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.
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.
190
190
 
191
191
  ## Provider and model settings
192
192
 
@@ -248,7 +248,7 @@ Defaults:
248
248
  - Copilot: `gpt-5-mini`
249
249
  - Reasoning effort: `medium`
250
250
 
251
- The Anthropic model choices include `claude-fable-5`, but Fable availability depends on the logged-in account and organization. Selecting it without access returns an Anthropic provider error.
251
+ 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
252
 
253
253
  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.
254
254
 
@@ -393,6 +393,21 @@ The built-in TUI file editor supports three keybinding modes. Modern is the defa
393
393
 
394
394
  `mode` can be `modern`, `emacs`, or `vibe`. The old `default` value is still accepted as an alias for `modern`. You can change this from `/settings` → Interface → Editor mode; newly opened editor buffers pick up the setting immediately.
395
395
 
396
+ Vibe `:prompt` uses a dedicated transient editor agent. Configure its model and reasoning effort under `editor.agent` when it should differ from the active tab:
397
+
398
+ ```json
399
+ {
400
+ "editor": {
401
+ "agent": {
402
+ "model": "gpt-5.5",
403
+ "reasoning_effort": "medium"
404
+ }
405
+ }
406
+ }
407
+ ```
408
+
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.
410
+
396
411
  The integrated Git and session diff viewers support unified and side-by-side layouts:
397
412
 
398
413
  ```json
data/doc/editor.md CHANGED
@@ -43,7 +43,7 @@ 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, `@` 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, `@` 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.
47
47
 
48
48
  For an unsaved buffer, open a scratchpad:
49
49
 
@@ -85,21 +85,26 @@ $doc/editor.md
85
85
  1. Type `$doc/editor.md` in the composer.
86
86
  2. Pick the file from the matching results, or press `Enter` if the path is already complete.
87
87
  3. Edit the file.
88
- 4. Save with `Ctrl+S` in Modern mode, `C-x C-s` in Emacs mode, or `:w` in Vibe mode. For an unsaved scratchpad in Vibe mode, use `:w filename`.
89
- 5. Quit with `Ctrl+Q`, `C-x C-c`, or `:q`.
90
- 6. Continue chatting with Kward.
88
+ 4. In Vibe normal mode, use `:prompt <instruction>` to ask the agent to update the current in-memory buffer. In Modern mode, press `Ctrl+.` and type the instruction in the editor prompt line. For example, `write a HelloWorld class`.
89
+ 5. The editor stays visible while the agent works; its status line shows a spinner. Review the generated buffer and save with `Ctrl+S` in Modern mode, `C-x C-s` in Emacs mode, or `:w` in Vibe mode. For an unsaved scratchpad in Vibe mode, use `:w filename`.
90
+ 6. Quit with `Ctrl+Q`, `C-x C-c`, or `:q`.
91
+ 7. Continue chatting with Kward.
91
92
 
92
93
  ## What the editor supports
93
94
 
94
95
  The editor is intentionally compact, but it covers the basics you need for quick changes:
95
96
 
96
97
  - Syntax highlighting for common languages, including Ruby, ERB templates, 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. ERB highlights template HTML outside ERB tags and Ruby inside `<% ... %>` tags. Unknown file types render as plain text.
97
- - Auto-indent, enabled by default. New lines inherit indentation, Tab jumps to the expected indentation or the next indentation stop, Shift+Tab moves indentation back, obvious closing tokens are re-indented, and Backspace in leading whitespace removes one indentation unit when possible. ERB recognizes common inline Ruby control tags and HTML opening tags when calculating the next indentation. For Ruby, Crystal, Elixir, Julia, Lua, Makefiles, and shell scripts, Enter after a block opener inserts the matching closing keyword; Ctrl+Enter also works from the middle of the line in terminals that report modified Enter keys.
98
+ - Current-buffer word completion. After a partial word, Tab completes from words elsewhere in the active buffer; repeated Tab presses cycle nearby matches. Completion is case-sensitive and recognizes letters, numbers, and underscores. No project files or external sources are searched.
99
+ - Auto-indent, enabled by default. New lines inherit indentation. When word completion does not apply, Tab jumps to the expected indentation or the next indentation stop. Shift+Tab moves indentation back, obvious closing tokens are re-indented, and Backspace in leading whitespace removes one indentation unit when possible. ERB recognizes common inline Ruby control tags and HTML opening tags when calculating the next indentation. For Ruby, Crystal, Elixir, Julia, Lua, Makefiles, and shell scripts, Enter after a block opener inserts the matching closing keyword; Ctrl+Enter also works from the middle of the line in terminals that report modified Enter keys.
98
100
  - Undo and redo, with up to 100 history entries per buffer.
99
101
  - Incremental search forward and backward.
100
102
  - Selection, copy, cut, and paste. Copy and cut also write to the terminal clipboard through OSC 52 when the terminal supports it.
101
103
  - A line-number gutter and a status line that shows the current mode and prompts.
102
104
  - Soft-wrap, enabled by default so long lines wrap within the editor width instead of scrolling sideways. Disable it with `editor.soft_wrap: false`.
105
+ - Vibe `:prompt <instruction>` and Modern `Ctrl+.` prompt lines send the complete current buffer and document metadata to a dedicated, transient editor agent. The agent can replace the in-memory buffer through an explicit editor tool; it does not save files automatically.
106
+ - Editor prompts and their tool activity are not added to the normal chat transcript or session history.
107
+ - The editor remains visible and locked for editing while the agent runs. Its status line displays progress and a spinner; `Ctrl+C` cancels the request.
103
108
 
104
109
  ## Choosing an editor mode
105
110
 
@@ -122,12 +127,16 @@ You can also configure it in `config.json`:
122
127
  ```json
123
128
  {
124
129
  "editor": {
125
- "mode": "modern"
130
+ "mode": "modern",
131
+ "agent": {
132
+ "model": "gpt-5.5",
133
+ "reasoning_effort": "medium"
134
+ }
126
135
  }
127
136
  }
128
137
  ```
129
138
 
130
- `mode` can be `modern`, `emacs`, or `vibe`. The old `default` value is still accepted as an alias for `modern`.
139
+ `mode` can be `modern`, `emacs`, or `vibe`. The optional `editor.agent.model` and `editor.agent.reasoning_effort` settings configure the dedicated Vibe editor agent. They use the active tab's provider. When either value is omitted, it falls back to the active tab's setting and then the client default. Editor-agent turns use a dedicated system prompt and are not persisted in the active tab transcript. The old `default` value is still accepted as an alias for `modern`.
131
140
 
132
141
  To disable auto-indent or auto-close pairs:
133
142
 
@@ -156,6 +165,7 @@ Modern mode is the default and is the easiest place to start. It uses common ter
156
165
  | --------------------- | ------------------------------------------------- |
157
166
  | `Ctrl+S` | Save |
158
167
  | `Ctrl+Q` | Quit; press again to discard unsaved changes |
168
+ | `Ctrl+.` | Open the editor-agent prompt line |
159
169
  | `/` | Search forward |
160
170
  | `?` | Search backward |
161
171
  | `Ctrl+C` | Copy selection, or cancel search |
@@ -192,7 +202,7 @@ Modern mode is the default and is the easiest place to start. It uses common ter
192
202
  | `Home` / `End` | Move to start / end of line |
193
203
  | `PageUp` / `PageDown` | Scroll |
194
204
  | `Enter` | Insert newline, or confirm search |
195
- | `Tab` | Smart-indent to the expected indentation or next stop |
205
+ | `Tab` | Complete a buffer word, or smart-indent when no match exists |
196
206
  | `Shift+Tab` | Move indentation back by one stop |
197
207
  | `Backspace` | Delete before cursor |
198
208
  | `Delete` | Delete character at cursor |
@@ -233,7 +243,7 @@ Emacs mode is for users who prefer classic Emacs-style non-modal editing. Save a
233
243
  | `Home` / `End` | Move to start / end of line |
234
244
  | `PageUp` / `PageDown` | Scroll |
235
245
  | `Enter` | Insert newline, or confirm search |
236
- | `Tab` | Smart-indent to the expected indentation or next stop |
246
+ | `Tab` | Complete a buffer word, or smart-indent when no match exists |
237
247
  | `Shift+Tab` | Move indentation back by one stop |
238
248
  | `Backspace` | Delete before cursor |
239
249
  | `Delete` / `C-d` | Delete character at cursor |
@@ -370,7 +380,7 @@ Vibe insert mode also supports readline-style shortcuts for efficient editing wi
370
380
  | ---------------- | ---------------------------------------- |
371
381
  | type text | Insert characters |
372
382
  | `Enter` | Insert newline |
373
- | `Tab` | Smart-indent to the expected indentation or next stop |
383
+ | `Tab` | Complete a buffer word, or smart-indent when no match exists |
374
384
  | `Shift+Tab` | Move indentation back by one stop |
375
385
  | `Backspace` | Delete before cursor |
376
386
  | `Delete` | Delete character at cursor |
data/doc/files.md CHANGED
@@ -12,9 +12,9 @@ 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.
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.
16
16
 
17
- When you quit the editor, Kward returns to the file browser at the same position so you can keep browsing nearby files.
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
 
19
19
  ## What appears in the browser
20
20
 
@@ -24,7 +24,7 @@ Inside a Git repository, `/files` uses Git's project view:
24
24
  git ls-files --cached --others --exclude-standard
25
25
  ```
26
26
 
27
- That means tracked files and normal untracked files appear, while ignored files stay out of the list.
27
+ That means tracked files and normal untracked files appear by default, while ignored files stay out of the list. Press `i` in the tree view to show or hide Git-ignored files; Kward remembers this choice for the workspace.
28
28
 
29
29
  Outside Git, Kward scans the workspace directory and skips common noisy directories such as `.git`, `.yardoc`, `_yardoc`, `node_modules`, `rdoc`, `tmp`, and `vendor/bundle`.
30
30
 
@@ -39,7 +39,10 @@ Outside Git, Kward scans the workspace directory and skips common noisy director
39
39
  | `Tab` | Start or stop search |
40
40
  | `/` | Start search |
41
41
  | `Backspace` | Delete the last search character |
42
+ | `i` | Show or hide Git-ignored files |
42
43
  | `Esc` | Leave search; press again to close the browser |
44
+ | `Q` | Close an image preview |
45
+ | `+` / `-` | Zoom an image preview in / out |
43
46
  | `@` | Insert the selected file as an `@path` mention |
44
47
 
45
48
  Directories use `▸` and `▾` markers to show collapsed and expanded state. Files are shown under their containing directory with indentation. File-type icons are off by default; users with a compatible Nerd Font can enable them under Interface in `/settings`. See [Configuration](configuration.md#project-browser-icons).
@@ -88,13 +91,17 @@ See [Integrated editor](editor.md) for editor modes, save/quit keys, search, sel
88
91
 
89
92
  ## Remembered state
90
93
 
91
- Kward remembers the expanded folders and selected path for each workspace. The next time you open `/files` in the same project, it restores the browser close to where you left it.
94
+ 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.
92
95
 
93
96
  Search itself is temporary. Closing search returns to the normal tree, and closing the browser leaves your chat session intact.
94
97
 
98
+ ## Image previews
99
+
100
+ Image previews are read-only and replace the file-list overlay while leaving the prompt composer and tabs visible. Press `+` or `-` to make the image larger or smaller within the available overlay space. Press `Esc` or `Q` to return to `/files`. Kward probes Kitty-compatible terminals when it has a real interactive TTY, uses recognized terminal identity hints when probing is inconclusive, and retries transient detection failures. Terminals without reachable Kitty or iTerm2 inline-image support keep the selection in the browser and show a status message instead of opening binary data in the text editor. Kitty-compatible terminals use PNG data; JPEG, GIF, and WebP previews require an available local image converter.
101
+
95
102
  ## Notes and limitations
96
103
 
97
104
  - `/files` is only available in the interactive prompt.
98
105
  - It opens files inside the current workspace.
99
106
  - It is a focused project browser, not a full file manager: it does not rename, move, copy, or delete files.
100
- - Ignored Git files are intentionally hidden when Git can provide the file list.
107
+ - Ignored Git files are hidden by default when Git can provide the file list; press `i` in the tree view to show them.
data/doc/permissions.md CHANGED
@@ -176,6 +176,7 @@ The policy runs before Kward dispatches a model-requested tool. It does not cons
176
176
  - a permitted shell command can access files, processes, credentials, and network services available to your user account;
177
177
  - command-text rules are useful review controls, not a reliable way to enforce network destinations or all subprocess behavior;
178
178
  - direct commands that you type yourself—`!command`, `/capture`, `/shell`, and `/pty`—are treated as your actions and are outside this first policy scope;
179
+ - commands run by the transient `?` shell assistant go through the normal permission and hook checks but deliberately use the user-owned `/shell` process, so the command sandbox cannot contain them;
179
180
  - plugins, hooks, and MCP servers are trusted local extensions with their own process access.
180
181
 
181
182
  For sensitive work, use a restricted operating-system account, container, virtual machine, or disposable checkout. [Command sandboxing](sandboxing.md) is a separate, opt-in operating-system boundary for model-requested `run_shell_command` workers. It can add filesystem and child-network restrictions, but does not cover Kward's host process, extensions, or direct interactive commands.
data/doc/releasing.md CHANGED
@@ -1,74 +1,115 @@
1
1
  # Releasing Kward
2
2
 
3
- ## Before you begin
3
+ Kward releases are prepared locally and published by GitHub Actions. The local command updates the version and changelog, runs every release check, creates the release commit and annotated tag, then pushes both atomically. The tag-triggered workflow publishes the gem to RubyGems.org and creates a GitHub Release with the same gem attached.
4
4
 
5
- Kward requires Ruby >= 3.4 (`spec.required_ruby_version` in `kward.gemspec`). If you develop with a newer Ruby, verify tests pass against the minimum supported version before releasing.
5
+ ## One-time setup
6
6
 
7
- ## Prepare the release
7
+ Kward publishes through [RubyGems trusted publishing](https://guides.rubygems.org/trusted-publishing/), so the repository does not need a long-lived RubyGems API key.
8
8
 
9
- Before publishing:
9
+ Before the first automated release:
10
10
 
11
- 1. Update `CHANGELOG.md` for the version. Move `[Unreleased]` entries under a new version heading.
12
- 2. Update `Kward::VERSION` in `lib/kward/version.rb`.
13
- 3. Run the release preflight:
11
+ 1. In the GitHub repository, create an Actions environment named `release`. Add required reviewers if releases should have a manual approval gate.
12
+ 2. On the RubyGems.org page for the `kward` gem, add a trusted publisher with:
13
+ - Repository owner: `kaiwood`
14
+ - Repository name: `kward`
15
+ - Workflow filename: `release.yml`
16
+ - Environment: `release`
17
+ 3. Confirm GitHub Actions can write repository contents. The release job requests only `contents: write` for the GitHub Release and `id-token: write` for RubyGems OIDC authentication.
14
18
 
15
- ```bash
16
- bundle exec rake release:preflight
17
- ```
19
+ GitHub Packages is intentionally not used. RubyGems.org remains the canonical package registry; the built `.gem` is also attached to each GitHub Release.
18
20
 
19
- This runs the full test suite, builds and checks the generated docs, builds a local gem, and prints the packaged file list for review.
21
+ ## Prepare a release
20
22
 
21
- 4. Run focused tests for any areas you changed during the release prep itself (docs, config, etc.):
23
+ Keep notable changes under the appropriate `Added`, `Changed`, `Fixed`, or `Removed` heading in the `[Unreleased]` section of `CHANGELOG.md`. Do not add the version heading by hand.
22
24
 
23
- ```bash
24
- ruby -Itest test/test_cli.rb
25
- ```
25
+ Before releasing, make sure `main` is clean, pushed, and synchronized with `origin/main`. Then run:
26
26
 
27
- 5. Preview docs locally if you changed documentation or public APIs:
27
+ ```bash
28
+ script/release 0.82.0
29
+ ```
30
+
31
+ The version can also come from standard input:
32
+
33
+ ```bash
34
+ printf '0.82.0\n' | script/release
35
+ ```
36
+
37
+ The command fails closed unless:
38
+
39
+ - The version is a valid RubyGems version newer than `Kward::VERSION`.
40
+ - The working tree is clean and checked out on `main`.
41
+ - Local `main` exactly matches `origin/main`.
42
+ - The tag does not exist locally or on GitHub.
43
+ - RubyGems.org does not already contain the version.
44
+ - `[Unreleased]` contains at least one changelog entry.
45
+
46
+ If validation succeeds, it:
28
47
 
29
- ```bash
30
- bundle exec rake docs:serve
31
- ```
48
+ 1. Updates `Kward::VERSION` in `lib/kward/version.rb`.
49
+ 2. Refreshes `Gemfile.lock` with `bundle lock --local`.
50
+ 3. Moves the unreleased changelog entries under a dated version heading.
51
+ 4. Runs `bundle exec rake release:preflight`.
52
+ 5. Commits the three release files as `Release v0.82.0`.
53
+ 6. Creates an annotated `v0.82.0` tag.
54
+ 7. Atomically pushes `main` and the tag to `origin`.
32
55
 
33
- The preview builds `_yardoc/`, serves it with WEBrick, and rebuilds in a fresh process when documentation sources, library code, or templates change. Refresh your browser after rebuilds.
56
+ If preparation fails before the commit, the command restores the version, lockfile, and changelog. If tagging or pushing fails after the commit, it leaves the release commit in place and prints the failed command; inspect the repository before retrying rather than creating another release commit.
34
57
 
35
- 6. If you want to run the documentation check separately:
58
+ ## What the release workflow does
36
59
 
37
- ```bash
38
- bundle exec rake docs:build
39
- bundle exec rake docs:check
40
- ```
60
+ A pushed `v*` tag starts `.github/workflows/release.yml`. The workflow:
41
61
 
42
- `docs:check` validates generated internal links, images, and scripts. Pushes to `main` deploy the generated YARD site to GitHub Pages. You can also run `bundle exec rake rdoc` to generate a separate RDoc site as a sanity check, but it is not deployed.
62
+ 1. Checks that the tag, gem version, and changelog heading agree.
63
+ 2. Installs and enables Bubblewrap, then runs the full test suite and generated-documentation checks against Ruby 3.4 using the same Linux sandbox setup as normal CI.
64
+ 3. Builds the gem and verifies its packaged files.
65
+ 4. Publishes through RubyGems trusted publishing.
66
+ 5. Downloads the canonical published gem from RubyGems.org, waiting for propagation when necessary, and verifies its checksum against the RubyGems API.
67
+ 6. Creates `Kward VERSION` as a GitHub Release using that version's changelog section and attaches the verified RubyGems artifact.
43
68
 
44
- 7. Inspect the packaged files printed by `release:preflight` and confirm no local config, sessions, logs, or secrets are included. The gemspec uses `git ls-files` and excludes `test/`, `plan/`, `.ruby-lsp/`, `.gitignore`, and `AGENTS.md`.
69
+ The publishing job uses the protected `release` environment. If RubyGems.org already has the version after a partially completed workflow, a rerun downloads and verifies the canonical published gem before continuing. This also accommodates trusted-publishing attestations that can change the published gem bytes. For an existing GitHub Release, the workflow downloads and compares the gem, uploads it when missing, and publishes an unfinished draft. This makes normal workflow reruns safe without silently replacing mismatched artifacts.
45
70
 
46
- 8. Install the built gem locally and smoke test the `kward` executable in a clean workspace.
71
+ If the workflow itself needs a fix after a tag has already been pushed, commit and push the fix to `main`, then recover the existing tag with the updated workflow:
47
72
 
48
- ## Tag and publish
73
+ ```bash
74
+ gh workflow run Release --ref main -f tag=v0.82.0
75
+ ```
76
+
77
+ Manual recovery still checks out and verifies the tagged source before publishing. The `release` environment permits automatic version-tag runs and manual recovery runs from `main` only.
49
78
 
50
- Commit the version bump and create a Git tag:
79
+ Follow the run from the repository's **Actions Release** page. Installation can be checked after publication with:
51
80
 
52
81
  ```bash
53
- git commit -am "Bump to VERSION"
54
- git tag vVERSION
55
- git push && git push --tags
82
+ gem install kward --version 0.82.0
83
+ kward --version
56
84
  ```
57
85
 
58
- Publish the built gem from the release checkout:
86
+ ## Run checks without releasing
87
+
88
+ After updating to an unreleased version, run the complete preflight directly with:
89
+
90
+ ```bash
91
+ bundle exec rake release:preflight
92
+ ```
93
+
94
+ This verifies release metadata, runs tests, builds and checks the generated documentation, builds `pkg/kward-VERSION.gem`, rejects development-only packaged files, and prints the final gem contents.
95
+
96
+ Individual checks remain available:
59
97
 
60
98
  ```bash
61
- gem push kward-VERSION.gem
99
+ bundle exec rake test
100
+ bundle exec rake docs:check
101
+ bundle exec rake release:verify
102
+ bundle exec rake build
62
103
  ```
63
104
 
64
- RubyGems MFA is required for publishing. Prefer RubyGems trusted publishing for automated releases if CI publishing is added later, so long-lived API keys do not need to be stored in CI secrets.
105
+ Use `bundle exec rake docs:serve` to preview documentation locally.
65
106
 
66
107
  ## If you need to yank a release
67
108
 
68
- If a published gem has a serious problem, you can yank it within 24 hours of pushing:
109
+ If a published gem has a serious problem, yank it within 24 hours of pushing:
69
110
 
70
111
  ```bash
71
112
  gem yank kward --version VERSION
72
113
  ```
73
114
 
74
- Yanking removes the gem from the default install index but does not delete the version entirely. After yanking, fix the issue, bump the version, and release again.
115
+ Yanking removes the gem from the default install index but does not delete the version. Fix the issue, choose a new version, and run the normal release command again. Never move or reuse a published version tag.
data/doc/rpc.md CHANGED
@@ -80,11 +80,11 @@ Read `capabilities` at runtime instead of assuming every feature is available. I
80
80
  - `mcp`: local stdio MCP server support through the shared `mcpServers` config. RPC exposes MCP tools to turns and advertises discovery with `methods: ["tools/list", "mcp/status"]`, `toolMetadata: true`, and `serverStatus: true`. It does not support MCP resources, prompts, sampling, or Streamable HTTP.
81
81
  - `startupResources`: supported startup resource listing for context, skills, prompts, and plugins.
82
82
  - `extensionUi`: question bridge support via `ui/question` and `ui/answerQuestion`, plus plugin footer updates via `ui/footer`; other UI primitives are explicitly unsupported.
83
- - `composer`: composer-only UI features. Interactive session diff totals are explicitly unsupported over RPC (`composer.sessionDiff.supported: false`) because RPC clients already receive per-tool diff results and no live composer status payload is exposed. Clipboard copy is also unsupported over RPC (`composer.copy.supported: false`) because UI clients own clipboard access.
83
+ - `composer`: composer-only UI features. Interactive session diff totals are explicitly unsupported over RPC (`composer.sessionDiff.supported: false`) because RPC clients already receive per-tool diff results and no live composer status payload is exposed. Clipboard copy is also unsupported over RPC (`composer.copy.supported: false`) because UI clients own clipboard access. Vibe editor prompts are unsupported over RPC (`composer.editorPrompt.supported: false`) because RPC has no live integrated editor buffer.
84
84
  - `security`: trusted-local behavior and optional per-turn tool approval. By default, RPC turns have no workspace mutation guard or tool approval, so shell commands and file changes can run. Clients can inspect file-tool guardrails through `capabilities.events.tools.workspaceGuardrails` and `runtime/state.workspaceGuardrailsEnabled`. `security.sandbox` reports the command sandbox mode, enforcement backend, and filesystem and network capabilities; session pinning and one-time elevation are unsupported. See [Command sandboxing](sandboxing.md) for the boundary and its limits.
85
85
  - `export`: supported transcript export formats. Currently `markdown` and `html`; default is `markdown`.
86
86
  - `starterPack`: explicitly unsupported (`supported: false`, reason `cliOnlyInstallCommand`). Use `kward init` from the shell.
87
- - `shell`: explicitly unsupported (`supported: false`, reason `interactiveTuiOnly`) because `/shell`, `!command`, `/capture`, and PTY handoff require the local TUI. Model-requested `run_shell_command` tools remain bounded, captured, and noninteractive over RPC.
87
+ - `shell`: explicitly unsupported (`supported: false`, reason `interactiveTuiOnly`) because `/shell`, its transient `?` shell assistant, `!command`, `/capture`, and PTY handoff require the local TUI. Model-requested `run_shell_command` tools remain bounded, captured, and noninteractive over RPC.
88
88
  - `logging`: local redacted telemetry, its directory and enabled categories, `logging/stats` and `logging/tokenCsv`, bucketed `usageCsv` support, JSONL storage, and 10 MB rotation with manual retention. Logs contain redacted metadata only. Configuration uses the `logging` key and `KWARD_LOGGING` environment prefix.
89
89
 
90
90
  ### `shutdown`
data/doc/sandboxing.md CHANGED
@@ -106,12 +106,16 @@ this interface.
106
106
  ## Boundaries and limits
107
107
 
108
108
  The current implementation protects **model-requested command workers only**.
109
+ The transient `?` shell assistant is intentionally not one of those workers: its
110
+ `run_shell_command` calls use the active user-owned `/shell` process so shell
111
+ state can persist.
112
+
109
113
  It does not sandbox:
110
114
 
111
115
  - the Kward Ruby host process;
112
116
  - model-provider, search-provider, or RPC traffic;
113
117
  - trusted Ruby plugins;
114
- - MCP servers, lifecycle hooks, `/shell`, `!command`, `/capture`, or `/pty`.
118
+ - MCP servers, lifecycle hooks, `/shell`, `?` shell-agent commands, `!command`, `/capture`, or `/pty`.
115
119
 
116
120
  Sandboxed command workers receive a minimal environment: Kward preserves only
117
121
  basic terminal, locale, and path variables, then supplies a private `HOME` and