kward 0.71.0 → 0.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +30 -0
  3. data/CHANGELOG.md +93 -0
  4. data/Gemfile.lock +2 -2
  5. data/README.md +4 -0
  6. data/doc/agent-tools.md +15 -6
  7. data/doc/authentication.md +22 -1
  8. data/doc/code-search.md +42 -2
  9. data/doc/configuration.md +106 -3
  10. data/doc/context-budgeting.md +136 -0
  11. data/doc/context-tools.md +16 -3
  12. data/doc/editor.md +415 -0
  13. data/doc/extensibility.md +16 -7
  14. data/doc/files.md +100 -0
  15. data/doc/getting-started.md +25 -18
  16. data/doc/git.md +123 -0
  17. data/doc/memory.md +24 -4
  18. data/doc/personas.md +34 -5
  19. data/doc/plugins.md +72 -1
  20. data/doc/releasing.md +37 -9
  21. data/doc/rpc.md +75 -5
  22. data/doc/session-management.md +35 -1
  23. data/doc/shell.md +332 -0
  24. data/doc/tabs.md +122 -0
  25. data/doc/troubleshooting.md +77 -1
  26. data/doc/usage.md +79 -7
  27. data/doc/web-search.md +12 -4
  28. data/doc/workspace-tools.md +51 -12
  29. data/examples/plugins/space_invaders.rb +377 -0
  30. data/lib/kward/agent.rb +1 -1
  31. data/lib/kward/ansi.rb +62 -23
  32. data/lib/kward/cli/commands.rb +33 -2
  33. data/lib/kward/cli/git.rb +150 -0
  34. data/lib/kward/cli/interactive_turn.rb +73 -9
  35. data/lib/kward/cli/plugins.rb +54 -4
  36. data/lib/kward/cli/prompt_interface.rb +32 -1
  37. data/lib/kward/cli/rendering.rb +4 -1
  38. data/lib/kward/cli/runtime_helpers.rb +268 -4
  39. data/lib/kward/cli/sessions.rb +2 -2
  40. data/lib/kward/cli/settings.rb +217 -9
  41. data/lib/kward/cli/slash_commands.rb +628 -2
  42. data/lib/kward/cli/tabs.rb +725 -0
  43. data/lib/kward/cli/tool_summaries.rb +6 -0
  44. data/lib/kward/cli.rb +150 -26
  45. data/lib/kward/clipboard.rb +2 -3
  46. data/lib/kward/compactor.rb +7 -19
  47. data/lib/kward/config_files.rb +145 -1
  48. data/lib/kward/context_budget_meter.rb +44 -0
  49. data/lib/kward/conversation.rb +12 -4
  50. data/lib/kward/editor_mode.rb +25 -0
  51. data/lib/kward/ekwsh.rb +559 -0
  52. data/lib/kward/image_attachments.rb +3 -1
  53. data/lib/kward/interactive_pty_runner.rb +151 -0
  54. data/lib/kward/local_command_runner.rb +155 -0
  55. data/lib/kward/local_pty_command_runner.rb +171 -0
  56. data/lib/kward/model/context_usage.rb +2 -2
  57. data/lib/kward/model/payloads.rb +2 -5
  58. data/lib/kward/plugin_registry.rb +61 -0
  59. data/lib/kward/project_files.rb +52 -0
  60. data/lib/kward/prompt_history.rb +84 -0
  61. data/lib/kward/prompt_interface/composer_controller.rb +69 -1
  62. data/lib/kward/prompt_interface/composer_renderer.rb +109 -13
  63. data/lib/kward/prompt_interface/composer_state.rb +96 -27
  64. data/lib/kward/prompt_interface/editor/auto_close_pairs.rb +123 -0
  65. data/lib/kward/prompt_interface/editor/auto_indent.rb +510 -0
  66. data/lib/kward/prompt_interface/editor/buffer.rb +109 -0
  67. data/lib/kward/prompt_interface/editor/controller.rb +1218 -0
  68. data/lib/kward/prompt_interface/editor/endwise.rb +321 -0
  69. data/lib/kward/prompt_interface/editor/file_marker.rb +40 -0
  70. data/lib/kward/prompt_interface/editor/indent_navigation.rb +61 -0
  71. data/lib/kward/prompt_interface/editor/kill_ring.rb +78 -0
  72. data/lib/kward/prompt_interface/editor/modes/emacs.rb +259 -0
  73. data/lib/kward/prompt_interface/editor/modes/modern.rb +354 -0
  74. data/lib/kward/prompt_interface/editor/modes/vibe.rb +1812 -0
  75. data/lib/kward/prompt_interface/editor/modes/vibe_insert_readline.rb +166 -0
  76. data/lib/kward/prompt_interface/editor/renderer.rb +244 -0
  77. data/lib/kward/prompt_interface/editor/search.rb +76 -0
  78. data/lib/kward/prompt_interface/editor/selections.rb +120 -0
  79. data/lib/kward/prompt_interface/editor/state.rb +1271 -0
  80. data/lib/kward/prompt_interface/editor/status_text.rb +23 -0
  81. data/lib/kward/prompt_interface/editor/syntax_highlighter.rb +422 -0
  82. data/lib/kward/prompt_interface/editor/undo_history.rb +46 -0
  83. data/lib/kward/prompt_interface/editor/vibe_state.rb +44 -0
  84. data/lib/kward/prompt_interface/file_overlay.rb +211 -0
  85. data/lib/kward/prompt_interface/git_prompt.rb +288 -0
  86. data/lib/kward/prompt_interface/interactive/controller.rb +186 -0
  87. data/lib/kward/prompt_interface/interactive/renderer.rb +71 -0
  88. data/lib/kward/prompt_interface/interactive/state.rb +62 -0
  89. data/lib/kward/prompt_interface/key_handler.rb +451 -57
  90. data/lib/kward/prompt_interface/overlay_renderer.rb +21 -2
  91. data/lib/kward/prompt_interface/project_browser.rb +524 -0
  92. data/lib/kward/prompt_interface/question_prompt.rb +99 -56
  93. data/lib/kward/prompt_interface/runtime_state.rb +43 -0
  94. data/lib/kward/prompt_interface/screen.rb +19 -3
  95. data/lib/kward/prompt_interface/selection_prompt.rb +10 -19
  96. data/lib/kward/prompt_interface/slash_overlay.rb +2 -0
  97. data/lib/kward/prompt_interface/stream_state.rb +7 -0
  98. data/lib/kward/prompt_interface/transcript_buffer.rb +6 -0
  99. data/lib/kward/prompt_interface.rb +366 -222
  100. data/lib/kward/prompts/commands.rb +9 -0
  101. data/lib/kward/prompts.rb +2 -0
  102. data/lib/kward/rpc/memory_methods.rb +83 -0
  103. data/lib/kward/rpc/server.rb +169 -83
  104. data/lib/kward/rpc/session_manager.rb +45 -121
  105. data/lib/kward/rpc/session_tree_rows.rb +9 -115
  106. data/lib/kward/rpc/tool_event_normalizer.rb +1 -1
  107. data/lib/kward/rpc/tool_metadata.rb +11 -0
  108. data/lib/kward/rpc/transcript_normalizer.rb +4 -39
  109. data/lib/kward/scratchpad_runner.rb +56 -0
  110. data/lib/kward/session_diff.rb +20 -3
  111. data/lib/kward/session_naming.rb +11 -0
  112. data/lib/kward/session_store.rb +44 -0
  113. data/lib/kward/session_tree_nodes.rb +136 -0
  114. data/lib/kward/session_tree_renderer.rb +9 -131
  115. data/lib/kward/tab_store.rb +47 -0
  116. data/lib/kward/terminal_keys.rb +84 -0
  117. data/lib/kward/terminal_sequences.rb +42 -0
  118. data/lib/kward/text_boundary.rb +25 -0
  119. data/lib/kward/tools/context_budget_stats.rb +54 -0
  120. data/lib/kward/tools/context_for_task.rb +204 -0
  121. data/lib/kward/tools/read_file.rb +8 -4
  122. data/lib/kward/tools/registry.rb +62 -16
  123. data/lib/kward/tools/tool_call.rb +10 -0
  124. data/lib/kward/version.rb +1 -1
  125. data/lib/kward/workers/git_guard.rb +93 -0
  126. data/lib/kward/workers/job.rb +99 -0
  127. data/lib/kward/workers/live_view.rb +49 -0
  128. data/lib/kward/workers/manager.rb +288 -0
  129. data/lib/kward/workers/queue_runner.rb +166 -0
  130. data/lib/kward/workers/queue_store.rb +112 -0
  131. data/lib/kward/workers/store.rb +72 -0
  132. data/lib/kward/workers/tool_policy.rb +23 -0
  133. data/lib/kward/workers/worker.rb +82 -0
  134. data/lib/kward/workers/write_lock.rb +38 -0
  135. data/lib/kward/workers.rb +10 -0
  136. data/lib/kward/workspace.rb +125 -87
  137. data/templates/default/fulldoc/html/css/kward.css +140 -36
  138. data/templates/default/fulldoc/html/images/kward_screen_1.png +0 -0
  139. data/templates/default/fulldoc/html/setup.rb +1 -0
  140. data/templates/default/kward_navigation.rb +12 -1
  141. data/templates/default/layout/html/layout.erb +23 -34
  142. data/templates/default/layout/html/setup.rb +6 -0
  143. metadata +67 -1
@@ -18,13 +18,21 @@ Install the gem:
18
18
  gem install kward
19
19
  ```
20
20
 
21
- Install the starter pack:
21
+ Optionally install the starter pack:
22
22
 
23
23
  ```bash
24
24
  kward init
25
25
  ```
26
26
 
27
- The starter pack adds default prompts and a base `PRINCIPLES.md` under `~/.kward`. It does not overwrite existing files.
27
+ The starter pack adds default prompts and a base `PRINCIPLES.md` under `~/.kward`. It does not overwrite existing files. It is safe to skip if you prefer to create your own instructions. It requires network access because it fetches the pack from GitHub.
28
+
29
+ Verify your setup:
30
+
31
+ ```bash
32
+ kward doctor
33
+ ```
34
+
35
+ This checks your config, auth, writable directories, and workspace. Run `kward help` to see all available commands and examples.
28
36
 
29
37
  If you are working from a checkout instead:
30
38
 
@@ -49,6 +57,14 @@ Or from inside an interactive session:
49
57
 
50
58
  Kward supports OpenAI/ChatGPT, Anthropic Claude Pro/Max, OpenRouter, and experimental Copilot credentials. See [Authentication](authentication.md) when you need a specific provider.
51
59
 
60
+ Confirm your credentials are saved:
61
+
62
+ ```bash
63
+ kward auth status
64
+ ```
65
+
66
+ If your provider offers multiple models, choose one inside Kward with `/model`.
67
+
52
68
  ## Start an interactive chat
53
69
 
54
70
  Run Kward from the project you want it to work on:
@@ -58,6 +74,12 @@ cd ~/code/my-project
58
74
  kward
59
75
  ```
60
76
 
77
+ Or point Kward at a project without leaving your shell:
78
+
79
+ ```bash
80
+ kward --working-directory ~/code/my-project
81
+ ```
82
+
61
83
  Ask something concrete:
62
84
 
63
85
  ```text
@@ -88,7 +110,7 @@ git diff | kward "Review this diff for bugs"
88
110
 
89
111
  One-shot prompts do not use Kward memory.
90
112
 
91
- ## Useful first commands
113
+ ## Useful interactive commands
92
114
 
93
115
  Inside interactive Kward:
94
116
 
@@ -97,27 +119,12 @@ Inside interactive Kward:
97
119
  /model choose a model
98
120
  /status show session and context status
99
121
  /sessions open the saved sessions picker
100
- /resume alias for /sessions
101
122
  /rewind revisit an earlier prompt
102
123
  /export notes.md export the transcript
103
124
  /compact summarize older context when a chat gets long
104
125
  /exit leave Kward
105
126
  ```
106
127
 
107
- ## Run from source
108
-
109
- ```bash
110
- ruby lib/main.rb login
111
- ruby lib/main.rb
112
- ruby lib/main.rb "Explain this project"
113
- ```
114
-
115
- You can also run:
116
-
117
- ```bash
118
- exe/kward
119
- ```
120
-
121
128
  ## Next steps
122
129
 
123
130
  - Read [Usage](usage.md) for day-to-day workflows.
data/doc/git.md ADDED
@@ -0,0 +1,123 @@
1
+ # Git
2
+
3
+ Kward has a small interactive Git workflow built into the terminal UI. It lets you review the current working tree, inspect per-file diffs, stage or unstage files, write a commit message, and create a commit without leaving the chat.
4
+
5
+ Use it when you have just finished a change with Kward and want one last pass before committing. It is intentionally focused: it is not a full Git client, just the common review-and-commit loop.
6
+
7
+ ## Quick start
8
+
9
+ From an interactive Kward session inside a Git repository, run:
10
+
11
+ ```text
12
+ /git
13
+ ```
14
+
15
+ Kward opens a Git overlay showing the same short status style you would see from:
16
+
17
+ ```bash
18
+ git status --short --untracked-files=normal
19
+ ```
20
+
21
+ Example:
22
+
23
+ ```text
24
+ M lib/kward/cli.rb
25
+ A doc/git.md
26
+ ?? tmp/example.txt
27
+ ```
28
+
29
+ Use the overlay to review and shape the commit:
30
+
31
+ | Key | Action |
32
+ | --- | --- |
33
+ | `↑` / `↓` | Move between changed files. |
34
+ | `Enter` | Open the selected file in the diff viewer. |
35
+ | `s` | Stage or unstage the selected file. |
36
+ | `Tab` | Switch to commit-message entry. |
37
+ | `Esc` | Cancel and return to chat. |
38
+
39
+ When you press `Tab`, the prompt changes from `Git>` to `Commit>`. Type the commit message and press `Enter` to commit. Press `Tab` again to return to the file list without losing the draft message.
40
+
41
+ Use `Shift+Enter` to insert a newline if you need a multi-line commit message.
42
+
43
+ ## Review changes with the diff viewer
44
+
45
+ Highlight a file in the `/git` overlay and press `Enter`.
46
+
47
+ Kward opens a read-only diff viewer in the composer area. It shows classic Git diff output with added and removed lines colorized when terminal color is enabled.
48
+
49
+ Useful keys in the diff viewer:
50
+
51
+ | Key | Action |
52
+ | --- | --- |
53
+ | `↑` / `↓` | Move through the diff one line at a time. |
54
+ | `Page Up` / `Page Down` | Scroll by a page. |
55
+ | `Home` / `End` | Move within the current line. |
56
+ | `/` or `Ctrl+F` | Search within the diff. |
57
+ | `Ctrl+C` / `Cmd+C` | Copy the current selection. |
58
+ | `Enter` | Confirm the current search. |
59
+ | `Esc` | Cancel search, or close the diff viewer. |
60
+ | `Ctrl+Q` | Close the diff viewer. |
61
+
62
+ After you close the viewer, Kward returns to the Git overlay with the file list refreshed.
63
+
64
+ The diff viewer is read-only. It is meant for checking what changed, not editing. If you spot something you want to fix, close the viewer, return to chat, and ask Kward to make the change or open the file with the built-in editor using `$path/to/file` (see [Configuration](configuration.md) for editor modes and settings).
65
+
66
+ ## Example workflow
67
+
68
+ A typical end-to-end flow looks like this:
69
+
70
+ ```text
71
+ /git
72
+ ```
73
+
74
+ 1. Use `↑` and `↓` to scan the changed files.
75
+ 2. Press `Enter` on a file that looks risky.
76
+ 3. Search the diff with `/` if you need to find a symbol or error message.
77
+ 4. Press `Esc` to close the diff viewer.
78
+ 5. Press `s` on files you want in this commit.
79
+ 6. Press `Tab` to write the commit message.
80
+ 7. Press `Enter` to commit.
81
+
82
+ If no files are staged when you submit the commit message, Kward stages all current workspace changes before committing. If at least one file is already staged, Kward commits only the staged changes.
83
+
84
+ That means you can use `/git` in two ways:
85
+
86
+ - **Simple commit:** do not stage anything manually; write a message and Kward commits all current changes.
87
+ - **Selective commit:** stage specific files with `s`; Kward commits only what is staged.
88
+
89
+ ## How staged changes work
90
+
91
+ The `s` key toggles the selected file:
92
+
93
+ - unstaged files are staged with `git add -- <path>`
94
+ - staged files are unstaged with `git restore --staged -- <path>`
95
+
96
+ The status list refreshes after each toggle, so you can see what will be included before committing.
97
+
98
+ For untracked files, the diff viewer shows the file as a new file with every line added. That makes it possible to review new files before staging them.
99
+
100
+ Renamed or copied files (status codes `R` and `C`) appear in the list with their destination path after the `->` arrow, and the diff viewer shows the destination file.
101
+
102
+ ## Git branch indicator
103
+
104
+ In the interactive composer status line, Kward also shows the current Git branch or short commit SHA when the workspace is inside a repository. The indicator turns yellow when the working tree has uncommitted changes.
105
+
106
+ This is just a lightweight status hint. Use `/git` when you want to review or commit the changes.
107
+
108
+ If the working tree is clean when you run `/git`, the overlay shows `No uncommitted changes.` and there is nothing to stage or commit.
109
+
110
+ ## Notes and limitations
111
+
112
+ - `/git` is available in the interactive terminal UI, not in one-shot prompts or the RPC backend.
113
+ - The command must run inside a Git repository.
114
+ - The diff viewer compares tracked files against `HEAD` with `git diff HEAD -- <path>`.
115
+ - The commit command uses `git commit -m <message>`.
116
+ - Kward does not push, pull, merge, rebase, amend, or manage branches from this overlay.
117
+ - Commit success still depends on your local Git configuration, hooks, and repository state.
118
+
119
+ For AI-assisted review without committing, you can still pipe a diff into a one-shot prompt:
120
+
121
+ ```bash
122
+ git diff | kward "Review this diff"
123
+ ```
data/doc/memory.md CHANGED
@@ -51,7 +51,7 @@ Add a workspace-specific hint when it only applies to the current project:
51
51
  /memory add "This workspace uses Minitest."
52
52
  ```
53
53
 
54
- Use global core memory sparingly. It has higher priority than workspace memory.
54
+ Use global core memory sparingly. It applies everywhere, so it has a wider blast radius than workspace memory.
55
55
 
56
56
  ## Let Kward summarize useful memories
57
57
 
@@ -61,6 +61,12 @@ Auto-summary is off by default. Enable it if you want Kward to learn recurring p
61
61
  /memory auto-summary enable
62
62
  ```
63
63
 
64
+ Disable it again:
65
+
66
+ ```text
67
+ /memory auto-summary disable
68
+ ```
69
+
64
70
  This only runs when memory is enabled. It does not run for one-shot prompts.
65
71
 
66
72
  You can also ask Kward to summarize the current session manually:
@@ -69,10 +75,14 @@ You can also ask Kward to summarize the current session manually:
69
75
  /memory summarize
70
76
  ```
71
77
 
78
+ `/memory learn` is an alias for `/memory summarize`.
79
+
72
80
  Kward is conservative about inferred memories and refuses to automatically persist emotional, intimate, romantic, or dependency-forming memories.
73
81
 
74
82
  ## Inspect what Kward remembers
75
83
 
84
+ Running `/memory` with no argument prints a summary of all available subcommands.
85
+
76
86
  List active memories for the current workspace:
77
87
 
78
88
  ```text
@@ -108,6 +118,12 @@ Promote a workspace hint when it should become a stronger rule:
108
118
  /memory promote soft_001
109
119
  ```
110
120
 
121
+ `/memory promote` also works on workspace core memories, promoting them to global scope so they apply everywhere:
122
+
123
+ ```text
124
+ /memory promote core_003
125
+ ```
126
+
111
127
  Relax a global memory back to the current workspace:
112
128
 
113
129
  ```text
@@ -124,7 +140,7 @@ Kward uses three layers:
124
140
 
125
141
  Core memories override soft memories. Soft memories are treated as hints, not facts.
126
142
 
127
- Kward does not inject every stored memory into every prompt. It retrieves a bounded set that appears relevant to the current turn.
143
+ Kward does not inject every stored memory into every prompt. It retrieves a bounded set that appears relevant to the current turn: up to 6 core and 6 soft memories. Core memories are included by scope match (global and current workspace). Soft memories are scored by text and tag overlap with the current input, confidence level, and expiry, and only the top-scoring ones are injected.
128
144
 
129
145
  ## Where memory is stored
130
146
 
@@ -136,12 +152,16 @@ Default files:
136
152
  ~/.kward/memory/events.jsonl
137
153
  ```
138
154
 
155
+ The memory directory is created with mode `0700` and each file with mode `0600`.
156
+
139
157
  `events.jsonl` stores a small audit trail for actions such as enable, add, retrieve, summarize, promote, and forget.
140
158
 
141
159
  When a soft memory is forgotten, its text is replaced with `[forgotten]` while inactive audit metadata can remain.
142
160
 
143
- If `KWARD_CONFIG_PATH` is set, memory files live beside that config file instead of under `~/.kward`.
161
+ Soft memories have a time-to-live of 60 days by default. Each time a soft memory is retrieved, its `last_seen_at` timestamp is updated and its hit count is incremented. If a soft memory is not retrieved within its TTL window, it expires and is no longer injected into prompts. Forgotten and expired memories remain in the file for audit but are not shown in `/memory list`.
162
+
163
+ If `KWARD_CONFIG_PATH` is set, memory files live beside that config file instead of under `~/.kward`. See [Configuration](configuration.md) for the config-file representation.
144
164
 
145
165
  ## RPC support
146
166
 
147
- The experimental RPC backend exposes memory methods such as `memory/list`, `memory/add`, `memory/forget`, `memory/why`, and `memory/summarize`. See [RPC protocol](rpc.md) if you are building a client.
167
+ The experimental RPC backend exposes memory methods including `memory/status`, `memory/enable`, `memory/disable`, `memory/autoSummary/enable`, `memory/autoSummary/disable`, `memory/list`, `memory/add`, `memory/addCore`, `memory/forget`, `memory/promote`, `memory/relax`, `memory/inspect`, `memory/why`, and `memory/summarize`. See the [RPC documentation](rpc.md) for the full protocol.
data/doc/personas.md CHANGED
@@ -108,7 +108,7 @@ Assistant> I found the failing test.
108
108
  Samantha> I found the failing test.
109
109
  ```
110
110
 
111
- This is not only decorative. It is the name Kward uses when rendering assistant messages in the terminal transcript. If no active persona label is available, Kward uses `Assistant>`.
111
+ This is not only decorative. It is the name Kward uses when rendering assistant messages in the terminal transcript. If the active persona has no `label` field, Kward uses `Assistant>` instead — the character `key` is not used as a fallback label. If no persona is active at all, Kward also uses `Assistant>`.
112
112
 
113
113
  For RPC clients, the active label is also exposed as `activePersonaLabel` so a UI can show the same speaker identity.
114
114
 
@@ -163,6 +163,19 @@ You can also define characters as a map:
163
163
  }
164
164
  ```
165
165
 
166
+ In the map form, the key is the character key. You can also use a bare string as the definition, which becomes the instruction; the transcript label then falls back to `Assistant>` unless you use a hash with `label`:
167
+
168
+ ```json
169
+ {
170
+ "personas": {
171
+ "characters": {
172
+ "duck": "You are a patient rubber duck."
173
+ },
174
+ "default": "duck"
175
+ }
176
+ }
177
+ ```
178
+
166
179
  The array form is easier to read and is recommended for new configs.
167
180
 
168
181
  `personas.crew` is accepted as a legacy alias for `personas.characters`.
@@ -179,13 +192,25 @@ Set `personas.default` to the character key you want by default:
179
192
  }
180
193
  ```
181
194
 
195
+ `personas.default` can also be a raw instruction string instead of a character key. When the value does not match any character, Kward uses it directly as the persona instruction:
196
+
197
+ ```json
198
+ {
199
+ "personas": {
200
+ "default": "You are a calm assistant."
201
+ }
202
+ }
203
+ ```
204
+
205
+ This is a quick way to set a persona without defining a `characters` entry.
206
+
182
207
  You can also change the default from interactive Kward:
183
208
 
184
209
  ```text
185
210
  /settings
186
211
  ```
187
212
 
188
- Then choose the personalization/default persona option.
213
+ Choose **Personalization**, then **Default persona** to pick from your configured characters. The same menu also offers **Active instructions summary**, which shows the active persona label and whether `PRINCIPLES.md` and workspace `AGENTS.md` are present.
189
214
 
190
215
  ## Workspace-specific personas
191
216
 
@@ -268,7 +293,7 @@ anthropic_reasoning_effort
268
293
  copilot_reasoning_effort
269
294
  ```
270
295
 
271
- Personas do not choose the model and do not set reasoning effort by themselves. What personas can do is add extra character direction based on the active reasoning effort.
296
+ Personas do not choose the model and do not set reasoning effort by themselves. What personas can do is add extra character direction based on the active reasoning effort. See [Configuration](configuration.md) for the full provider, model, and reasoning config reference.
272
297
 
273
298
  In plain English:
274
299
 
@@ -324,7 +349,7 @@ Example:
324
349
  }
325
350
  ```
326
351
 
327
- If no bucket matches, no time-of-day modifier is added.
352
+ If no bucket matches, no time-of-day modifier is added. Hours 12:00-20:59 (noon through early evening) have no bucket, so no time-of-day modifier is applied during that window.
328
353
 
329
354
  ## Weekday modifiers
330
355
 
@@ -404,7 +429,11 @@ From the shell:
404
429
  kward sysprompt
405
430
  ```
406
431
 
407
- `kward sysprompt` shows the assembled prompt sections, including the persona text that would be used for a new conversation.
432
+ `kward sysprompt` shows the assembled prompt sections, including the persona text that would be used for a new conversation. Add `--raw` to print the raw system prompt content without section formatting, which is useful for scripting or piping to another tool:
433
+
434
+ ```bash
435
+ kward sysprompt --raw
436
+ ```
408
437
 
409
438
  ## When to use personas
410
439
 
data/doc/plugins.md CHANGED
@@ -21,6 +21,8 @@ Plugins run inside the Kward process with your user permissions. Install only pl
21
21
  | Repository rules | `AGENTS.md` |
22
22
  | Local Ruby code or integration | plugin |
23
23
 
24
+ See [Extensibility](extensibility.md) for the full overview of Kward's extension points and prompt assembly order.
25
+
24
26
  ## Where plugins live
25
27
 
26
28
  Kward loads top-level Ruby files from:
@@ -56,6 +58,8 @@ Start Kward and run:
56
58
  /hello World
57
59
  ```
58
60
 
61
+ When developing plugins, use `/reload` inside Kward to reload all plugin files without restarting. This picks up changes to existing plugins and registers new ones, then rebuilds the system message.
62
+
59
63
  ## Add a slash command
60
64
 
61
65
  Use plugin commands for local actions that should not call the model.
@@ -77,7 +81,7 @@ A plugin command cannot replace a built-in command or prompt-template command.
77
81
 
78
82
  Prompt context is short text injected into future model requests.
79
83
 
80
- Use it for stable facts the model should know, not for large files or secrets.
84
+ Use it for stable facts the model should know, not for large files or secrets. The block should return a string (injected into the system prompt) or `nil` (skipped). The example below uses Ruby's `next` to return `nil` early when the condition does not match.
81
85
 
82
86
  ```ruby
83
87
  Kward.plugin do |plugin|
@@ -109,6 +113,71 @@ end
109
113
 
110
114
  Only one footer is active. If multiple plugins register footers, the later one replaces the earlier one and Kward prints a warning.
111
115
 
116
+ ## Add an interactive command
117
+
118
+ Interactive commands take over the composer region with a Kward-driven render and
119
+ input loop. The plugin receives a controller object with a canvas API for
120
+ drawing colored cells and reading keys. This is useful for games, dashboards,
121
+ viewers, and similar full-region interactive experiences.
122
+
123
+ `interactive_command` accepts `description:` and `argument_hint:` keyword arguments, which appear in the slash command list and completion overlay just like regular plugin commands. `rows:` sets the fixed canvas height (minimum 1), and `fps:` sets the target frame rate (1–120, default 30).
124
+
125
+ ```ruby
126
+ Kward.plugin do |plugin|
127
+ plugin.interactive_command "demo", rows: 10, fps: 30, description: "Canvas demo" do |ui, ctx|
128
+ x = 0
129
+ ui.on_tick do |ui|
130
+ ui.clear_frame
131
+ ui.put(0, x, "X", :red)
132
+ x = (x + 1) % ui.width
133
+ key = ui.poll_key
134
+ return :exit if key == :ctrl_c || key == "q"
135
+ end
136
+ end
137
+ end
138
+ ```
139
+
140
+ Run it with `/demo` from the interactive TUI. The canvas renders inside the
141
+ composer area for the specified number of rows. The transcript above stays
142
+ intact.
143
+
144
+ ### Controller API
145
+
146
+ The `ui` controller object passed to the handler block exposes:
147
+
148
+ | Method | Description |
149
+ | --- | --- |
150
+ | `put(row, col, char, *colors)` | Place a character at a zero-based position with optional ANSI color styles |
151
+ | `clear_frame` | Reset all canvas cells to blank |
152
+ | `render` | Mark the canvas as ready for Kward to draw |
153
+ | `poll_key` | Return the next pending key (non-blocking, nil if none) |
154
+ | `exit` | Request that the interactive loop exit |
155
+ | `on_tick { \|ui\| }` | Register a tick callback invoked each frame at the configured fps |
156
+ | `width` | Canvas width in terminal columns |
157
+ | `height` | Canvas height in terminal rows |
158
+ | `fps` | Target frame rate |
159
+
160
+ Keys are returned as symbols (`:left`, `:right`, `:up`, `:down`, `:return`,
161
+ `:backspace`, `:space`, `:pageup`, `:pagedown`) or raw strings for keys
162
+ without a named mapping. Ctrl+C always exits the loop immediately.
163
+
164
+ The tick callback runs at the configured frame rate (1–120 fps, default 30).
165
+ Returning `:exit` from the tick callback ends the loop, same as calling
166
+ `ui.exit`.
167
+
168
+ ### Lifecycle
169
+
170
+ - The composer state is saved on entry and fully restored on exit (input text,
171
+ cursor, and transcript viewport).
172
+ - Interactive mode is a distinct state from the busy-input spinner lifecycle —
173
+ no spinner or busy chrome is shown.
174
+ - Ctrl+C, the plugin calling `exit`, or the tick callback returning `:exit`
175
+ all exit cleanly and restore the prior composer state.
176
+ - Resize during interactive mode forces a clean exit and restore.
177
+
178
+ Interactive commands require the TUI prompt interface. They are not available
179
+ in piped/non-interactive mode or through RPC.
180
+
112
181
  ## Observe transcript events
113
182
 
114
183
  Use transcript events when you need to log or react to live activity:
@@ -151,6 +220,8 @@ Handlers receive a `ctx` object. Common methods:
151
220
  - `ctx.session_path`
152
221
  - `ctx.refresh_system_message!`
153
222
 
223
+ These methods are available in all handler types: commands, footers, prompt context renderers, and transcript event observers. `ctx.say` outputs to the active frontend (terminal or RPC) wherever it is called.
224
+
154
225
  The transcript is read-only. Use context methods instead of mutating Kward internals.
155
226
 
156
227
  ## RPC support
data/doc/releasing.md CHANGED
@@ -1,16 +1,24 @@
1
1
  # Releasing Kward
2
2
 
3
+ Kward requires Ruby >= 3.2 (`spec.required_ruby_version` in `kward.gemspec`). If you develop with a newer Ruby, verify tests pass against the minimum supported version before releasing.
4
+
3
5
  Release steps before publishing:
4
6
 
5
- 1. Update `CHANGELOG.md` for the version.
7
+ 1. Update `CHANGELOG.md` for the version. Move `[Unreleased]` entries under a new version heading.
6
8
  2. Update `Kward::VERSION` in `lib/kward/version.rb`.
7
- 3. Run the test suite:
9
+ 3. Run the full test suite:
8
10
 
9
11
  ```bash
10
12
  bundle exec rake test
11
13
  ```
12
14
 
13
- 4. Preview docs locally if you changed documentation or public APIs:
15
+ 4. Run focused tests for any areas you changed during the release prep itself (docs, config, etc.):
16
+
17
+ ```bash
18
+ ruby -Itest test/test_cli.rb
19
+ ```
20
+
21
+ 5. Preview docs locally if you changed documentation or public APIs:
14
22
 
15
23
  ```bash
16
24
  bundle exec rake docs:serve
@@ -18,24 +26,36 @@ Release steps before publishing:
18
26
 
19
27
  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.
20
28
 
21
- 5. Generate and check documentation:
29
+ 6. Generate and check documentation:
22
30
 
23
31
  ```bash
24
- bundle exec rake rdoc
25
32
  bundle exec rake docs:build
26
33
  bundle exec rake docs:check
27
34
  ```
28
35
 
29
- `docs:check` validates generated internal links, images, and scripts. Pushes to `main` deploy the generated YARD site to GitHub Pages.
36
+ `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.
30
37
 
31
- 6. Build the gem locally:
38
+ 7. Build the gem locally:
32
39
 
33
40
  ```bash
34
41
  gem build kward.gemspec
35
42
  ```
36
43
 
37
- 7. Inspect the packaged files and confirm no local config, sessions, logs, or secrets are included.
38
- 8. Install the built gem locally and smoke test the `kward` executable.
44
+ 8. Inspect the packaged files 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`. To verify what is packaged:
45
+
46
+ ```bash
47
+ tar tf kward-VERSION.gem
48
+ ```
49
+
50
+ 9. Install the built gem locally and smoke test the `kward` executable in a clean workspace.
51
+
52
+ Commit the version bump and create a git tag:
53
+
54
+ ```bash
55
+ git commit -am "Bump to VERSION"
56
+ git tag vVERSION
57
+ git push && git push --tags
58
+ ```
39
59
 
40
60
  Publish the built gem from the release checkout:
41
61
 
@@ -44,3 +64,11 @@ gem push kward-VERSION.gem
44
64
  ```
45
65
 
46
66
  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.
67
+
68
+ If a published gem has a serious problem, you can yank it within 24 hours of pushing:
69
+
70
+ ```bash
71
+ gem yank kward --version VERSION
72
+ ```
73
+
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.