kward 0.76.0 → 0.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +8 -1
- data/CHANGELOG.md +62 -0
- data/Gemfile.lock +2 -2
- data/README.md +13 -4
- data/doc/agent-tools.md +0 -3
- data/doc/api.md +4 -0
- data/doc/code-search.md +9 -6
- data/doc/composer.md +219 -0
- data/doc/configuration.md +114 -27
- data/doc/editor.md +18 -2
- data/doc/files.md +1 -1
- data/doc/getting-started.md +4 -0
- data/doc/git.md +2 -2
- data/doc/lifecycle-hooks.md +2 -14
- data/doc/pan.md +167 -0
- data/doc/permissions.md +179 -0
- data/doc/plugins.md +58 -0
- data/doc/rpc.md +61 -22
- data/doc/security.md +184 -0
- data/doc/tabs.md +4 -3
- data/doc/usage.md +15 -32
- data/doc/web-search.md +4 -2
- data/lib/kward/ansi.rb +2 -2
- data/lib/kward/auth/anthropic_oauth.rb +2 -2
- data/lib/kward/auth/github_oauth.rb +3 -3
- data/lib/kward/auth/oauth_helpers.rb +4 -2
- data/lib/kward/auth/openai_oauth.rb +2 -1
- data/lib/kward/cancellation.rb +2 -2
- data/lib/kward/cli/commands.rb +1 -3
- data/lib/kward/cli/interactive_turn.rb +0 -17
- data/lib/kward/cli/plugins.rb +24 -7
- data/lib/kward/cli/prompt_interface.rb +1 -0
- data/lib/kward/cli/rendering.rb +7 -1
- data/lib/kward/cli/runtime_helpers.rb +11 -35
- data/lib/kward/cli/sessions.rb +14 -5
- data/lib/kward/cli/settings.rb +22 -0
- data/lib/kward/cli/slash_commands.rb +1 -561
- data/lib/kward/cli/tabs.rb +154 -36
- data/lib/kward/cli.rb +30 -26
- data/lib/kward/compactor.rb +3 -3
- data/lib/kward/config_files.rb +28 -0
- data/lib/kward/ekwsh.rb +0 -4
- data/lib/kward/hooks/catalog.rb +0 -5
- data/lib/kward/hooks/http_handler.rb +2 -1
- data/lib/kward/http.rb +18 -0
- data/lib/kward/image_attachments.rb +1 -1
- data/lib/kward/model/client.rb +33 -11
- data/lib/kward/model/payloads.rb +6 -1
- data/lib/kward/openrouter_model_cache.rb +2 -1
- data/lib/kward/pan/index.html.erb +459 -64
- data/lib/kward/pan/kward_logo.png +0 -0
- data/lib/kward/pan/server.rb +248 -23
- data/lib/kward/permissions/policy.rb +171 -0
- data/lib/kward/plugin_registry.rb +71 -1
- data/lib/kward/prompt_interface/approval_prompt.rb +62 -0
- data/lib/kward/prompt_interface/editor/auto_indent.rb +31 -23
- data/lib/kward/prompt_interface/editor/modes/vibe.rb +72 -3
- data/lib/kward/prompt_interface/layout.rb +0 -4
- data/lib/kward/prompt_interface/project_browser.rb +40 -1
- data/lib/kward/prompt_interface/question_prompt.rb +12 -3
- data/lib/kward/prompt_interface/runtime_state.rb +4 -0
- data/lib/kward/prompt_interface/selection_prompt.rb +0 -1
- data/lib/kward/prompt_interface/transcript_renderer.rb +0 -12
- data/lib/kward/prompt_interface.rb +20 -1
- data/lib/kward/prompts/commands.rb +1 -3
- data/lib/kward/prompts.rb +20 -0
- data/lib/kward/rpc/plugin_chat_manager.rb +299 -0
- data/lib/kward/rpc/server.rb +48 -41
- data/lib/kward/rpc/session_manager.rb +76 -25
- data/lib/kward/rpc/tool_event_normalizer.rb +2 -0
- data/lib/kward/rpc/tool_metadata.rb +23 -0
- data/lib/kward/rpc/transcript_normalizer.rb +18 -5
- data/lib/kward/session_store.rb +55 -16
- data/lib/kward/skills/registry.rb +21 -1
- data/lib/kward/starter_pack_installer.rb +3 -1
- data/lib/kward/tab_driver.rb +87 -0
- data/lib/kward/tab_store.rb +74 -12
- data/lib/kward/tools/base.rb +14 -0
- data/lib/kward/tools/code_search.rb +8 -2
- data/lib/kward/tools/fetch_content.rb +4 -2
- data/lib/kward/tools/fetch_raw.rb +3 -1
- data/lib/kward/tools/registry.rb +45 -17
- data/lib/kward/tools/search/code.rb +47 -13
- data/lib/kward/tools/search/web.rb +61 -18
- data/lib/kward/tools/search/web_fetch.rb +206 -38
- data/lib/kward/tools/tool_call.rb +0 -4
- data/lib/kward/tools/web_search.rb +3 -1
- data/lib/kward/transcript_export.rb +1 -1
- data/lib/kward/update_check.rb +2 -1
- data/lib/kward/version.rb +1 -1
- data/templates/default/kward_navigation.rb +7 -2
- data/templates/default/layout/html/layout.erb +2 -2
- data/templates/default/layout/html/setup.rb +1 -0
- metadata +11 -12
- data/lib/kward/workers/git_guard.rb +0 -93
- data/lib/kward/workers/job.rb +0 -99
- data/lib/kward/workers/live_view.rb +0 -49
- data/lib/kward/workers/manager.rb +0 -328
- data/lib/kward/workers/queue_runner.rb +0 -166
- data/lib/kward/workers/queue_store.rb +0 -112
- data/lib/kward/workers/store.rb +0 -72
- data/lib/kward/workers/tool_policy.rb +0 -23
- data/lib/kward/workers/worker.rb +0 -82
- data/lib/kward/workers/write_lock.rb +0 -38
- data/lib/kward/workers.rb +0 -10
data/doc/permissions.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Permissions
|
|
2
|
+
|
|
3
|
+
Kward's permission policy lets you put a human decision between a model-requested tool call and its side effect. It is useful when you want the agent to inspect a project freely, but want to confirm edits, commands, web requests, or MCP calls as they arise.
|
|
4
|
+
|
|
5
|
+
Permissions are **off by default**. Enabling them does not sandbox Kward or its subprocesses: an allowed shell command still runs with your operating-system user permissions.
|
|
6
|
+
|
|
7
|
+
## Start with approval mode
|
|
8
|
+
|
|
9
|
+
Add this to `~/.kward/config.json`, or enable it through your usual configuration workflow:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"permissions": {
|
|
14
|
+
"enabled": true,
|
|
15
|
+
"mode": "ask"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
In `ask` mode, Kward allows ordinary read-only tools and asks before the agent:
|
|
21
|
+
|
|
22
|
+
- writes or edits a workspace file,
|
|
23
|
+
- runs `run_shell_command`,
|
|
24
|
+
- searches or fetches content on the web,
|
|
25
|
+
- calls an MCP tool.
|
|
26
|
+
|
|
27
|
+
When approval is required in the interactive CLI, Kward opens a modal overlay. It shows the complete tool arguments, so an approval for `read_skill` includes the requested skill name and relative path, and an approval for a write includes its path and content. Choose **Allow once** to run that one call, **Allow this tool for this session** to allow later calls to the same tool in the current Kward session, or **Deny** to stop it. Pressing `Esc`, cancelling the overlay, or losing the approval bridge denies the call.
|
|
28
|
+
|
|
29
|
+
### Steer the agent with `Type something`
|
|
30
|
+
|
|
31
|
+
**Type something** is more than a denial. It stops the requested tool call and sends your text back to the agent as the tool result, so you can redirect its workflow without waiting for it to finish a wrong turn.
|
|
32
|
+
|
|
33
|
+
For example, the agent may propose this command:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
run_shell_command: grep -R "Permission" lib test
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Choose **Type something** and enter:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
Use ack instead of grep; it is installed here and respects our ignore files.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Kward does not run `grep`. The agent receives:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
Declined: Use ack instead of grep; it is installed here and respects our ignore files.
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
It can then continue by choosing an `ack` command. This is useful for steering details that are difficult to encode in a static rule, such as:
|
|
52
|
+
|
|
53
|
+
- use the project’s preferred formatter or test runner;
|
|
54
|
+
- run a focused test rather than the full suite;
|
|
55
|
+
- use a local mirror or a documented API endpoint;
|
|
56
|
+
- explain a proposed database command before running it;
|
|
57
|
+
- choose an existing project script instead of inventing a new command.
|
|
58
|
+
|
|
59
|
+
The typed response is part of the conversation, just like a normal follow-up message. It is stored in the session and may be sent to the active model provider. Do not put secrets in it unless that is acceptable for your selected provider and retained session data.
|
|
60
|
+
|
|
61
|
+
Use this mode first when working in an unfamiliar repository or when you want to review an agent's actions without preventing ordinary exploration.
|
|
62
|
+
|
|
63
|
+
## Choose a mode
|
|
64
|
+
|
|
65
|
+
Set `permissions.mode` to one of these values:
|
|
66
|
+
|
|
67
|
+
| Mode | Good for | Default behavior |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `ask` | Interactive supervised work | Asks before file changes, shell commands, web tools, and MCP tools. |
|
|
70
|
+
| `workspace-write` | Routine edits in selected paths | Allows file changes in `write_scopes`; still asks before shell, web, and MCP tools. |
|
|
71
|
+
| `read-only` | Code review and investigation | Denies risky tools by default. |
|
|
72
|
+
| `deny-by-default` | Automation or tightly controlled runs | Denies risky tools unless an `allow` rule matches. |
|
|
73
|
+
|
|
74
|
+
All modes leave ordinary read-only Kward tools available. Rules can make a decision more specific; see [Rules and precedence](#Rules_and_precedence).
|
|
75
|
+
|
|
76
|
+
## Let Kward edit only selected paths
|
|
77
|
+
|
|
78
|
+
Use `workspace-write` when you want routine changes in known source and test directories without an approval prompt for each edit:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"permissions": {
|
|
83
|
+
"enabled": true,
|
|
84
|
+
"mode": "workspace-write",
|
|
85
|
+
"write_scopes": ["lib/**", "test/**"]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
With this configuration, the agent may edit `lib/` and `test/` without asking. A proposed edit to `README.md` or `config/` is denied by the policy.
|
|
91
|
+
|
|
92
|
+
`write_scopes` narrows the policy's default workspace-write behavior; it does not broaden Kward's built-in workspace boundary. File tools still stay inside the active workspace by default, and existing files must still be read before Kward can edit them. See [Workspace tools](workspace-tools.md) for those guardrails.
|
|
93
|
+
|
|
94
|
+
An empty `write_scopes` array permits no default workspace writes. Omit `write_scopes` if you want the `workspace-write` mode to cover the normal workspace file-tool boundary.
|
|
95
|
+
|
|
96
|
+
## Rules and precedence
|
|
97
|
+
|
|
98
|
+
Use `allow`, `ask`, and `deny` arrays to describe exceptions. A rule can match these fields:
|
|
99
|
+
|
|
100
|
+
- `tool` — a model tool name, such as `run_shell_command` or `write_file`;
|
|
101
|
+
- `path` — the file-tool path supplied by the model;
|
|
102
|
+
- `command` — the requested shell command text;
|
|
103
|
+
- `host` — the host in a `fetch_content` or `fetch_raw` URL;
|
|
104
|
+
- `source` — currently useful for `mcp` tools.
|
|
105
|
+
|
|
106
|
+
Patterns support `*` within a path segment and `**` across directories. Rule matching is case-sensitive.
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"permissions": {
|
|
111
|
+
"enabled": true,
|
|
112
|
+
"mode": "ask",
|
|
113
|
+
"allow": [
|
|
114
|
+
{ "tool": "write_file", "path": "doc/**" },
|
|
115
|
+
{ "tool": "fetch_content", "host": "docs.ruby-lang.org" }
|
|
116
|
+
],
|
|
117
|
+
"ask": [
|
|
118
|
+
{ "tool": "run_shell_command", "command": "bundle exec *" }
|
|
119
|
+
],
|
|
120
|
+
"deny": [
|
|
121
|
+
{ "tool": "run_shell_command", "command": "git push*" },
|
|
122
|
+
{ "tool": "write_file", "path": "**/.env" }
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Kward evaluates matching rules in this order:
|
|
129
|
+
|
|
130
|
+
1. `deny`
|
|
131
|
+
2. `ask`
|
|
132
|
+
3. `allow`
|
|
133
|
+
4. the selected mode's default
|
|
134
|
+
|
|
135
|
+
A matching deny always wins. An ask rule wins over an allow rule. Keep rules narrow and easy to explain; prefer an exact command or a small path scope over a broad wildcard.
|
|
136
|
+
|
|
137
|
+
## A practical workflow
|
|
138
|
+
|
|
139
|
+
For a normal coding task:
|
|
140
|
+
|
|
141
|
+
1. Enable `ask` mode.
|
|
142
|
+
2. Ask Kward to inspect the project and propose a change.
|
|
143
|
+
3. Approve the file edit after checking its path and intent.
|
|
144
|
+
4. Approve a focused test command, or choose **Type something** to redirect it—for example, “run `bin/test unit` instead of the full suite.”
|
|
145
|
+
5. Review the diff and `git status` as usual.
|
|
146
|
+
|
|
147
|
+
If you repeatedly work in one source tree, move to `workspace-write` with narrow write scopes. Keep shell and network calls in approval mode unless you have a well-understood policy for them.
|
|
148
|
+
|
|
149
|
+
## RPC and Pan
|
|
150
|
+
|
|
151
|
+
RPC clients can continue to use the existing per-turn approval bridge:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"approvalMode": "ask"
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
That requests an approval notification for every tool call in that turn. The global permission policy is an additional restriction: a deny rule prevents the call even if the RPC client would approve it. If the global policy requires approval, a frontend without an approval bridge fails closed.
|
|
160
|
+
|
|
161
|
+
Pan currently has no dedicated approval interface. With permissions enabled, a Pan session cannot approve a policy `ask` decision, so Kward denies it. Use `read-only`, explicit allows, or a CLI/RPC frontend when approvals are needed.
|
|
162
|
+
|
|
163
|
+
## Limits: policy is not a sandbox
|
|
164
|
+
|
|
165
|
+
The policy runs before Kward dispatches a model-requested tool. It does not constrain what happens after a shell command starts. In particular:
|
|
166
|
+
|
|
167
|
+
- a permitted shell command can access files, processes, credentials, and network services available to your user account;
|
|
168
|
+
- command-text rules are useful review controls, not a reliable way to enforce network destinations or all subprocess behavior;
|
|
169
|
+
- direct commands that you type yourself—`!command`, `/shell`, and `/pty`—are treated as your actions and are outside this first policy scope;
|
|
170
|
+
- plugins, hooks, and MCP servers are trusted local extensions with their own process access.
|
|
171
|
+
|
|
172
|
+
For sensitive work, use a restricted operating-system account, container, virtual machine, or disposable checkout. A future OS-enforced sandbox may provide stronger filesystem and network isolation; it is not part of the current permissions feature.
|
|
173
|
+
|
|
174
|
+
## Related guides
|
|
175
|
+
|
|
176
|
+
- [Security and trust](security.md): trust boundaries, extensions, and safe work in unfamiliar repositories.
|
|
177
|
+
- [Configuration](configuration.md#Permissions): the complete configuration reference.
|
|
178
|
+
- [Lifecycle hooks](lifecycle-hooks.md): add trusted local policy or automation around Kward events.
|
|
179
|
+
- [RPC protocol](rpc.md#Tool_approval_bridge): implement the approval bridge in an RPC client.
|
data/doc/plugins.md
CHANGED
|
@@ -178,6 +178,64 @@ Returning `:exit` from the tick callback ends the loop, same as calling
|
|
|
178
178
|
Interactive commands require the TUI prompt interface. They are not available
|
|
179
179
|
in piped/non-interactive mode or through RPC.
|
|
180
180
|
|
|
181
|
+
## Add a plugin-owned tab
|
|
182
|
+
|
|
183
|
+
A plugin can provide a persistent tab with Kward's normal composer, transcript
|
|
184
|
+
rendering, streaming, image input, cancellation, and tab switching. The plugin
|
|
185
|
+
owns its transcript, storage, model behavior, and any global state; it does not
|
|
186
|
+
need to use a Kward workspace session.
|
|
187
|
+
|
|
188
|
+
```ruby
|
|
189
|
+
Kward.plugin do |plugin|
|
|
190
|
+
plugin.tab_type "example", id: "com.example.chat", title: "Example", singleton: :global do |host, descriptor|
|
|
191
|
+
ExampleChat.new(client: host.client, descriptor: descriptor)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Open it from interactive Kward:
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
/tab open example
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
`id` is a stable persisted identifier: do not change it after release.
|
|
203
|
+
Use `singleton: :global` for one plugin-managed chat shared by all tab views.
|
|
204
|
+
|
|
205
|
+
Plugin tabs do not notify global transcript observers by default. Set
|
|
206
|
+
`transcript_events: true` only when the tab explicitly permits its streamed
|
|
207
|
+
content to be delivered to every installed `on_transcript_event` handler, such
|
|
208
|
+
as a local text-to-speech plugin:
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
plugin.tab_type "example", id: "com.example.chat", transcript_events: true do |host, descriptor|
|
|
212
|
+
ExampleChat.new(client: host.client, descriptor: descriptor)
|
|
213
|
+
end
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The observer context exposes the plugin tab's `messages` through
|
|
217
|
+
`ctx.transcript.messages`; it has no workspace session. The tab driver returned by the block must provide:
|
|
218
|
+
|
|
219
|
+
- `messages` — renderable transcript messages;
|
|
220
|
+
- `submit(input, display_input:, cancellation:, steering:)` — a turn method
|
|
221
|
+
that returns the final response and yields stream events;
|
|
222
|
+
- `descriptor` — the durable tab descriptor;
|
|
223
|
+
- `supports_steering?` and `assistant_label`.
|
|
224
|
+
|
|
225
|
+
A driver may optionally implement `handles_command?(input)` and
|
|
226
|
+
`handle_command(input)` for its own slash commands. Other Kward session and
|
|
227
|
+
workspace commands stay unavailable inside plugin tabs.
|
|
228
|
+
|
|
229
|
+
Set `rpc: true` when the plugin tab can also be exposed as a trusted local RPC chat:
|
|
230
|
+
|
|
231
|
+
```ruby
|
|
232
|
+
plugin.tab_type "example", id: "com.example.chat", rpc: true do |host, descriptor|
|
|
233
|
+
ExampleChat.new(client: host.client, descriptor: descriptor)
|
|
234
|
+
end
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
RPC clients discover opted-in types through `initialize.capabilities.pluginChats`, open a chat with `pluginChats/open`, and must explicitly subscribe before receiving live `pluginChat/event` notifications. See [RPC](rpc.md) for the protocol. Plugin tabs remain CLI-only unless they opt in.
|
|
238
|
+
|
|
181
239
|
## Observe transcript events
|
|
182
240
|
|
|
183
241
|
Use transcript events when you need to log or react to live activity:
|
data/doc/rpc.md
CHANGED
|
@@ -52,6 +52,7 @@ Detailed capability fields include:
|
|
|
52
52
|
- `transcript`: Kward transcript format support, including normalized messages, image/tool support, compaction summaries, and restored assistant reasoning as Pi-compatible `thinking` content blocks.
|
|
53
53
|
- `sessions`: explicit RPC session mode, JSONL persistence, supported session methods, startup auto-resume capability/default, immediate transcript support for auto-resume, RPC list support, active live-session discovery, supported linear-session fork methods, supported compaction, supported tree navigation with labels and branch summarization, explicit unsupported import support, and unsupported live session updates reported with `notification: "session/updated"`.
|
|
54
54
|
- `turns`: async turn mode, per-session concurrency, active/recent turn listing, provider-gated native busy-input steering, queued follow-up input, best-effort cancellation, recent in-memory event replay behavior, per-turn options for model/reasoning/tool scope/tool approval, and structured client context for editor integrations.
|
|
55
|
+
- `pluginChats`: optional plugin-owned chats. The capability lists opted-in chat types and methods. Clients must explicitly subscribe before receiving `pluginChat/event` notifications; plugin chats are independent from workspace sessions.
|
|
55
56
|
- `events`: `turn/event` notification details, assistant/reasoning event names, normalized tool metadata, tool update/result events, diff result support, configured workspace guardrail status, focused context and context-budget stats tool support, and explicit unsupported shell changed-file detection/session update flags.
|
|
56
57
|
- `attachments`: supported input attachment contract for `turns/start`, with accepted base64 image MIME types and a stable max byte value.
|
|
57
58
|
- `models`: model/reasoning RPC methods, explicit OpenRouter catalog listing, exposed model fields, and no scoped model support.
|
|
@@ -67,7 +68,6 @@ Detailed capability fields include:
|
|
|
67
68
|
- `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.
|
|
68
69
|
- `security`: trusted-local behavior with optional per-turn tool approval. By default there is no workspace mutation guard or tool approval and shell/file mutation can run. File-tool workspace guardrails are reported under `capabilities.events.tools.workspaceGuardrails` and `runtime/state.workspaceGuardrailsEnabled`.
|
|
69
70
|
- `export`: supported transcript export formats. Currently `markdown` and `html`; default is `markdown`.
|
|
70
|
-
- `workers`: experimental agent worker pipeline. Reports `supported: false` by default; set to `supported: true` with `methods: ["workers/list", "workers/show"]` when Kward is launched with `--experimental-workers`.
|
|
71
71
|
- `starterPack`: explicitly unsupported (`supported: false`, reason `cliOnlyInstallCommand`). Use `kward init` from the shell.
|
|
72
72
|
- `shell`: explicitly unsupported (`supported: false`, reason `interactiveTuiOnly`) because `/shell` is the local embedded TUI shell.
|
|
73
73
|
- `logging`: local redacted telemetry logging support, the log directory, enabled categories, `methods: ["logging/stats", "logging/tokenCsv"]`, `usageCsv` sub-capability with bucket support, JSONL format, rotation (10 MB, manual retention), config key `logging`, env prefix `KWARD_LOGGING`, and redacted-metadata-only content.
|
|
@@ -277,6 +277,66 @@ Moves the active branch to the selected tree entry. If the entry is a user messa
|
|
|
277
277
|
|
|
278
278
|
Returns `{ "session": {}, "editorText": "...", "cancelled": false, "aborted": false }`. Fields with no value are omitted.
|
|
279
279
|
|
|
280
|
+
## Plugin chat methods
|
|
281
|
+
|
|
282
|
+
Plugin chats are optional trusted-plugin capabilities, not Kward workspace sessions. When `initialize.capabilities.pluginChats.supported` is true, use `pluginChats/list` to discover available types.
|
|
283
|
+
|
|
284
|
+
### `pluginChats/open`
|
|
285
|
+
|
|
286
|
+
Params:
|
|
287
|
+
|
|
288
|
+
- `typeId`: an opted-in plugin chat type, such as `kward.maria`.
|
|
289
|
+
|
|
290
|
+
Opens the plugin-owned chat in this RPC process and returns its metadata plus normalized transcript.
|
|
291
|
+
|
|
292
|
+
### `pluginChats/transcript`
|
|
293
|
+
|
|
294
|
+
Params:
|
|
295
|
+
|
|
296
|
+
- `chatId`;
|
|
297
|
+
- `limit`: optional bounded page size for plugin drivers that support transcript paging;
|
|
298
|
+
- `before`: optional opaque cursor returned by a preceding page.
|
|
299
|
+
|
|
300
|
+
Returns chat metadata and its normalized transcript. Paging-capable plugin chats return the newest page first plus `hasMore` and, when more history is available, `nextBefore`. Clients send that cursor as `before` to load the preceding page. Plugins that do not opt in retain the original complete-transcript behavior.
|
|
301
|
+
|
|
302
|
+
### `pluginChats/subscribe` and `pluginChats/unsubscribe`
|
|
303
|
+
|
|
304
|
+
Params:
|
|
305
|
+
|
|
306
|
+
- `chatId`.
|
|
307
|
+
|
|
308
|
+
Subscriptions are opt-in. `pluginChats/subscribe` enables live `pluginChat/event` notifications for that chat on the current RPC connection. `pluginChats/unsubscribe` disables them without affecting the chat or archive.
|
|
309
|
+
|
|
310
|
+
### `pluginChats/turns/start`
|
|
311
|
+
|
|
312
|
+
Params:
|
|
313
|
+
|
|
314
|
+
- `chatId`;
|
|
315
|
+
- `input`;
|
|
316
|
+
- `attachments`: optional base64 image attachments using the same MIME and size limits as `turns/start`.
|
|
317
|
+
|
|
318
|
+
Queues a plugin-chat turn and returns `{ id, chatId, status, ... }`. Plugin chat turns are serialized per chat and do not use workspace sessions, agents, or model overrides.
|
|
319
|
+
|
|
320
|
+
### `pluginChats/turns/cancel`, `pluginChats/turns/status`, `pluginChats/turns/events`, `pluginChats/turns/list`, `pluginChats/turns/listActive`
|
|
321
|
+
|
|
322
|
+
These methods mirror the corresponding `turns/*` lifecycle methods, using `chatId` where a list filter is needed. Event replay is bounded in memory and subscriptions are required for live notifications.
|
|
323
|
+
|
|
324
|
+
## Plugin chat notifications
|
|
325
|
+
|
|
326
|
+
Subscribed clients receive `pluginChat/event` notifications:
|
|
327
|
+
|
|
328
|
+
```json
|
|
329
|
+
{
|
|
330
|
+
"chatId": "kward.maria",
|
|
331
|
+
"turnId": "...",
|
|
332
|
+
"sequence": 1,
|
|
333
|
+
"type": "assistantDelta",
|
|
334
|
+
"payload": { "delta": "text" }
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Known event types are `turnQueued`, `turnStarted`, `reasoningDelta`, `reasoningBoundary`, `assistantDelta`, `assistantMessage`, `toolCall`, `toolResult`, `answer`, `turnCancelRequested`, and `turnFinished`.
|
|
339
|
+
|
|
280
340
|
## Turn methods
|
|
281
341
|
|
|
282
342
|
Turns are asynchronous. A session queues turns sequentially; only one turn runs per session at a time.
|
|
@@ -784,27 +844,6 @@ Completes the login using the submitted code.
|
|
|
784
844
|
|
|
785
845
|
Returns login status for a login ID.
|
|
786
846
|
|
|
787
|
-
## Worker methods (experimental)
|
|
788
|
-
|
|
789
|
-
Worker methods are available only when Kward is launched with `--experimental-workers`. The `workers` capability reports `supported: false` by default and `supported: true` with `methods: ["workers/list", "workers/show"]` when the flag is active.
|
|
790
|
-
|
|
791
|
-
### `workers/list`
|
|
792
|
-
|
|
793
|
-
Params:
|
|
794
|
-
|
|
795
|
-
- `sessionId`: active RPC session ID.
|
|
796
|
-
|
|
797
|
-
Returns the list of agent workers for the session.
|
|
798
|
-
|
|
799
|
-
### `workers/show`
|
|
800
|
-
|
|
801
|
-
Params:
|
|
802
|
-
|
|
803
|
-
- `sessionId`: active RPC session ID.
|
|
804
|
-
- `workerId`: worker ID.
|
|
805
|
-
|
|
806
|
-
Returns details for a specific worker.
|
|
807
|
-
|
|
808
847
|
## Security and privacy notes
|
|
809
848
|
|
|
810
849
|
- RPC is intended for a trusted local UI and can read/write files, run shell commands, update secrets, and use OAuth.
|
data/doc/security.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Security and trust
|
|
2
|
+
|
|
3
|
+
Kward can read code, edit files, run commands, call model and search providers, and load local extensions. That makes it useful, but it also means you should treat it like a developer tool running with your account—not like a sandbox.
|
|
4
|
+
|
|
5
|
+
This guide explains the trust boundaries and gives you a safe way to start work in an unfamiliar repository.
|
|
6
|
+
|
|
7
|
+
## The short version
|
|
8
|
+
|
|
9
|
+
- Kward and anything it launches run with your operating-system permissions.
|
|
10
|
+
- File tools stay inside the active workspace by default, but shell commands are not sandboxed.
|
|
11
|
+
- Existing files must be read before Kward's file tools can edit or overwrite them.
|
|
12
|
+
- Plugins, MCP servers, command hooks, and HTTP hooks should be configured only from sources and endpoints you trust.
|
|
13
|
+
- Project skills and workspace hooks are disabled until you opt in or trust them.
|
|
14
|
+
- Prompts, selected file contents, tool results, and conversation history may be sent to the active model provider as needed to answer a request.
|
|
15
|
+
- Web searches, fetched URLs, MCP calls, and HTTP hooks can send additional data to their respective services.
|
|
16
|
+
|
|
17
|
+
If a task involves secrets, production credentials, customer data, or an untrusted repository, narrow the workspace and tools before asking Kward to act.
|
|
18
|
+
|
|
19
|
+
## A safe first run in an unfamiliar repository
|
|
20
|
+
|
|
21
|
+
Start with project-provided extensions disabled, which is the default:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cd ~/code/unfamiliar-project
|
|
25
|
+
kward doctor
|
|
26
|
+
kward
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Then use a read-first workflow:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
Inspect the project structure and its AGENTS.md. Do not edit files or run project scripts yet. Tell me what instructions, hooks, skills, plugins, generated files, and risky setup commands I should review first.
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Before enabling or running anything:
|
|
36
|
+
|
|
37
|
+
1. Read the workspace `AGENTS.md` and any referenced instructions.
|
|
38
|
+
2. Inspect `.kward/hooks.json`, `.kward/skills/`, and `.agents/skills/` yourself.
|
|
39
|
+
3. Review setup scripts, package hooks, build files, and shell commands before allowing them to run.
|
|
40
|
+
4. Keep project skills disabled unless you trust their instructions.
|
|
41
|
+
5. Trust workspace hooks only after reviewing the full file with `kward hooks doctor` and `kward hooks trust`.
|
|
42
|
+
6. Do not add repository-provided Ruby files to `~/.kward/plugins` unless you are willing to run them as your user.
|
|
43
|
+
7. Ask Kward to explain proposed edits and commands before applying them when the impact is unclear.
|
|
44
|
+
|
|
45
|
+
For especially sensitive work, use a disposable checkout, container, virtual machine, or restricted operating-system account. Kward's own guardrails do not replace operating-system isolation.
|
|
46
|
+
|
|
47
|
+
## Workspace access is a guardrail, not a sandbox
|
|
48
|
+
|
|
49
|
+
Kward's built-in file tools normally resolve paths inside the active workspace. They reject paths outside that boundary, and existing files must be read in the current conversation before `write_file` or `edit_file` can change them.
|
|
50
|
+
|
|
51
|
+
These protections reduce accidental edits. They do not contain the whole process:
|
|
52
|
+
|
|
53
|
+
- `run_shell_command`, `!command`, `/shell`, and `/pty` run with your user permissions.
|
|
54
|
+
- A shell command can access files, environment variables, processes, and networks available to your account.
|
|
55
|
+
- Plugins, command hooks, and MCP servers are local processes with the same general operating-system access.
|
|
56
|
+
- Read-before-edit applies to Kward's file tools, not to arbitrary shell commands or extension code.
|
|
57
|
+
|
|
58
|
+
You can disable the file boundary with `tools.workspace_guardrails: false`, but doing so broadens file-tool access and is rarely needed. See [Workspace tools](workspace-tools.md) for exact limits and [Configuration](configuration.md#Tool_workspace_guardrails) for the setting.
|
|
59
|
+
|
|
60
|
+
## Tool approvals and policy hooks
|
|
61
|
+
|
|
62
|
+
The interactive CLI does not ask for blanket approval before every tool call. Built-in guardrails and configured lifecycle hooks still apply, but ordinary file and shell tools can run during a turn.
|
|
63
|
+
|
|
64
|
+
RPC clients can request per-turn approval with `approvalMode: "ask"`. Kward then emits `tool/approvalRequested` before each tool executes and waits for the client to answer. The default RPC approval mode is `none`.
|
|
65
|
+
|
|
66
|
+
Lifecycle hooks can add deterministic policy around tools, shell commands, files, Git actions, model requests, and other events. A hook can allow, deny, modify supported data, warn, or ask for approval. An `ask` decision fails closed when the frontend has no approval bridge.
|
|
67
|
+
|
|
68
|
+
Pan mode does not provide a dedicated hook-approval UI. Use `deny` or `warn` for Pan-facing policies instead of depending on interactive approval.
|
|
69
|
+
|
|
70
|
+
See [Lifecycle hooks](lifecycle-hooks.md) for policy examples and [RPC protocol](rpc.md#Tool_approval_bridge) for the approval contract.
|
|
71
|
+
|
|
72
|
+
## Opt-in permission policy
|
|
73
|
+
|
|
74
|
+
`permissions.enabled` is off by default. When enabled, Kward can allow, ask, or deny model-requested file changes, shell commands, web tools, and MCP tools before execution. The interactive CLI uses an approval overlay; an unavailable approval bridge fails closed. The policy is not a sandbox: after Kward permits a shell command, it still runs with the permissions of your user account. See [Permissions](permissions.md) for workflows, modes, rules, and limits.
|
|
75
|
+
|
|
76
|
+
## Know what you are trusting
|
|
77
|
+
|
|
78
|
+
### Workspace instructions
|
|
79
|
+
|
|
80
|
+
A repository-level `AGENTS.md` is guidance for the model, not executable code. Kward tells the model to read it for repository tasks. Instructions can still influence what the model proposes or which tools it calls, so review unfamiliar guidance just as you would review a contributor script.
|
|
81
|
+
|
|
82
|
+
### Project skills
|
|
83
|
+
|
|
84
|
+
Project skills under `.kward/skills/` and `.agents/skills/` are skipped by default. Enable them only after reviewing their `SKILL.md` instructions and supporting files:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
/settings → Tools & Search → Trust project skills
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This setting trusts project skills generally; it is not a per-repository digest. A skill's `allowed-tools` metadata does not grant permissions or constrain tools in Kward.
|
|
91
|
+
|
|
92
|
+
### Workspace hooks
|
|
93
|
+
|
|
94
|
+
Project hooks in `.kward/hooks.json` run only after `/hooks trust`. Trust is tied to the file digest, so a change invalidates it and requires another review. Command hooks execute local commands; HTTP hooks send event data to their configured endpoint.
|
|
95
|
+
|
|
96
|
+
### Plugins
|
|
97
|
+
|
|
98
|
+
Ruby plugins in `~/.kward/plugins/*.rb` run inside the Kward process with your permissions. They can read files and environment variables, write files, run commands, and make network requests. Kward intentionally does not load plugins from a workspace directory.
|
|
99
|
+
|
|
100
|
+
### MCP servers
|
|
101
|
+
|
|
102
|
+
Configured MCP servers are local child processes. Their tools can expose application state such as browser pages, console messages, network traffic, or screenshots. Kward currently supports local stdio servers, but local transport does not make an untrusted server safe.
|
|
103
|
+
|
|
104
|
+
Only add commands you trust to `mcpServers`, and review any environment variables supplied to them. See [MCP servers](mcp.md).
|
|
105
|
+
|
|
106
|
+
## What leaves your machine
|
|
107
|
+
|
|
108
|
+
### Model providers
|
|
109
|
+
|
|
110
|
+
To answer a turn, Kward sends the assembled conversation context to the active model provider. Depending on the task, that context can include:
|
|
111
|
+
|
|
112
|
+
- your prompts and prior conversation,
|
|
113
|
+
- system instructions, personas, skills, memory, and plugin context,
|
|
114
|
+
- file content read into the conversation,
|
|
115
|
+
- shell and tool results,
|
|
116
|
+
- images you attach,
|
|
117
|
+
- summaries produced during compaction.
|
|
118
|
+
|
|
119
|
+
Provider retention and training policies are controlled by the provider and your account or organization. Do not give Kward content you are not permitted to send to that provider.
|
|
120
|
+
|
|
121
|
+
### Web tools
|
|
122
|
+
|
|
123
|
+
Search queries go to the selected search provider. `fetch_content` and `fetch_raw` request the URL you provide or the model selects. Disable web tools when external lookup is inappropriate:
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"web_search": {
|
|
128
|
+
"enabled": false
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
See [Web search](web-search.md#Network_behavior) for provider order and request behavior.
|
|
134
|
+
|
|
135
|
+
### Hooks and MCP
|
|
136
|
+
|
|
137
|
+
HTTP hook payloads can include prompts, commands, file paths, tool arguments, and selected event results. Avoid forwarding raw events to third parties. Git and file after-events may include command output or changed content.
|
|
138
|
+
|
|
139
|
+
MCP tool arguments and results pass between Kward and the configured server. What the MCP server stores or forwards is determined by that server.
|
|
140
|
+
|
|
141
|
+
## Local data and permissions
|
|
142
|
+
|
|
143
|
+
Kward keeps user data under `~/.kward` by default, or mostly beside `KWARD_CONFIG_PATH` when that override is set.
|
|
144
|
+
|
|
145
|
+
| Data | Typical location | Notes |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| Main config and OpenRouter key | `~/.kward/config.json` | Do not commit or share it. |
|
|
148
|
+
| OAuth credentials | `~/.kward/auth.json`, `anthropic_auth.json`, `github_auth.json` | Written with mode `0600` when possible. |
|
|
149
|
+
| Sessions and tool results | `~/.kward/sessions/` | Conversation, file/tool output, and compaction history; files use mode `0600`. |
|
|
150
|
+
| Prompt history | `~/.kward/history/` | Workspace-scoped submitted prompts; files use mode `0600`. |
|
|
151
|
+
| Memory | `~/.kward/memory/` | Off by default; directory `0700` and files `0600`. |
|
|
152
|
+
| Telemetry logs | `~/.kward/logs/` | Off by default; redacted metadata, not intentional prompt or file-content logging. |
|
|
153
|
+
| Plugins | `~/.kward/plugins/` | Trusted Ruby code, not private data storage. |
|
|
154
|
+
| Hook audit log and trust records | `~/.kward/logs/`, `~/.kward/trusted_workspace_hooks.json` | Audit records use redacted metadata rather than raw event values. |
|
|
155
|
+
|
|
156
|
+
Private file modes help on normal Unix-like systems but do not protect data from your own account, privileged users, backups, malware, or a compromised machine. Session exports are written to the path you choose and should be protected separately.
|
|
157
|
+
|
|
158
|
+
Use these commands to inspect or remove stored credentials and context:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
kward auth status
|
|
162
|
+
kward auth logout
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
/session
|
|
167
|
+
/memory list
|
|
168
|
+
/memory forget <id>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
See [Authentication](authentication.md), [Sessions](session-management.md), [Memory](memory.md), and [Configuration](configuration.md#Logging_and_stats) for retention and management details.
|
|
172
|
+
|
|
173
|
+
## Practical habits
|
|
174
|
+
|
|
175
|
+
- Keep secrets out of prompts, screenshots, shell output, plugin context, and hook messages.
|
|
176
|
+
- Prefer temporary environment variables to storing short-lived API keys in config.
|
|
177
|
+
- Disable web search for private work that should not trigger external requests.
|
|
178
|
+
- Keep memory off unless cross-session recall is useful and appropriate.
|
|
179
|
+
- Review diffs and `git status` before committing agent changes.
|
|
180
|
+
- Treat generated commands as suggestions you are responsible for running.
|
|
181
|
+
- Use `kward sysprompt` to inspect instructions assembled for a new conversation.
|
|
182
|
+
- Run `kward doctor` and `kward hooks doctor` when configuration or trust behavior is unclear.
|
|
183
|
+
|
|
184
|
+
Security here is layered: Kward supplies guardrails and explicit trust controls, while real isolation and least privilege come from the environment in which you run it.
|
data/doc/tabs.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Use tabs when you want more than one Kward conversation open in the same interactive terminal session.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Normal tabs have their own session-backed conversation, transcript, composer state, and running agent turn. Plugins can also provide their own persistent tab types while Kward continues to supply the same composer and tab behavior. This makes tabs useful for splitting work without losing your place: one tab can investigate a bug, another can draft docs, and a third can wait on a long-running answer.
|
|
6
6
|
|
|
7
7
|
## Quick start
|
|
8
8
|
|
|
@@ -56,6 +56,7 @@ Tabs keep the conversations separate, so context from one tab does not automatic
|
|
|
56
56
|
| Command | Action |
|
|
57
57
|
| ------- | ------ |
|
|
58
58
|
| `/tab new` | Open a new tab with a fresh conversation |
|
|
59
|
+
| `/tab open <plugin-tab>` | Open a plugin-provided tab, such as a persistent companion chat. |
|
|
59
60
|
| `/tab 1` through `/tab 9` | Switch to a numbered tab |
|
|
60
61
|
| `/tab close` | Close the current tab |
|
|
61
62
|
| `/tab name <label>` | Rename the current tab |
|
|
@@ -110,9 +111,9 @@ Slash commands such as `/tab` still work while a tab is busy, so you can switch
|
|
|
110
111
|
|
|
111
112
|
## Persistence
|
|
112
113
|
|
|
113
|
-
|
|
114
|
+
Normal tabs are backed by Kward sessions. Plugins may also provide their own tab types; those tabs own their transcript and persistence independently of Kward sessions.
|
|
114
115
|
|
|
115
|
-
The tab layout is stored in Kward's config directory under `tabs/`. Session transcripts stay in the normal sessions directory. See [Sessions](session-management.md) for session naming, resuming, forking, exporting, and cleanup.
|
|
116
|
+
Kward stores the open tab list, labels, and active tab per workspace, then restores them the next time you start interactive Kward in that workspace. The tab layout is stored in Kward's config directory under `tabs/`. Session transcripts stay in the normal sessions directory. See [Sessions](session-management.md) for session naming, resuming, forking, exporting, and cleanup.
|
|
116
117
|
|
|
117
118
|
## Notes and limitations
|
|
118
119
|
|