kward 0.77.0 → 0.79.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 +7 -2
- data/.github/workflows/pages.yml +1 -1
- data/CHANGELOG.md +50 -0
- data/Gemfile.lock +2 -2
- data/README.md +5 -2
- data/doc/agent-tools.md +1 -1
- data/doc/code-search.md +9 -6
- data/doc/configuration.md +106 -1
- data/doc/extensibility.md +2 -0
- data/doc/getting-started.md +1 -1
- data/doc/local-models.md +130 -0
- data/doc/permissions.md +180 -0
- data/doc/plugins.md +58 -0
- data/doc/releasing.md +1 -1
- data/doc/rpc.md +73 -1
- data/doc/sandboxing.md +120 -0
- data/doc/security.md +15 -5
- data/doc/skills.md +10 -0
- data/doc/tabs.md +4 -3
- data/doc/web-search.md +4 -2
- data/doc/workspace-tools.md +3 -3
- data/kward.gemspec +1 -1
- 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/cli/doctor.rb +21 -0
- data/lib/kward/cli/plugins.rb +22 -0
- data/lib/kward/cli/rendering.rb +7 -1
- data/lib/kward/cli/runtime_helpers.rb +15 -1
- data/lib/kward/cli/settings.rb +66 -4
- data/lib/kward/cli/slash_commands.rb +109 -1
- data/lib/kward/cli/tabs.rb +140 -34
- data/lib/kward/cli.rb +31 -10
- data/lib/kward/config_files.rb +90 -1
- data/lib/kward/conversation.rb +14 -1
- data/lib/kward/hooks/http_handler.rb +2 -1
- data/lib/kward/http.rb +18 -0
- data/lib/kward/local_command_runner.rb +2 -2
- data/lib/kward/model/client.rb +173 -15
- data/lib/kward/model/model_info.rb +11 -1
- data/lib/kward/model/payloads.rb +7 -1
- data/lib/kward/model/stream_parser.rb +58 -26
- data/lib/kward/openrouter_model_cache.rb +2 -1
- data/lib/kward/pan/index.html.erb +50 -0
- data/lib/kward/pan/server.rb +49 -2
- data/lib/kward/permissions/policy.rb +171 -0
- data/lib/kward/plugin_registry.rb +54 -2
- data/lib/kward/prompt_interface/approval_prompt.rb +62 -0
- data/lib/kward/prompt_interface/editor/controller.rb +36 -3
- data/lib/kward/prompt_interface/question_prompt.rb +12 -3
- data/lib/kward/prompt_interface.rb +20 -0
- data/lib/kward/prompts/commands.rb +2 -0
- data/lib/kward/prompts.rb +16 -5
- data/lib/kward/rpc/plugin_chat_manager.rb +302 -0
- data/lib/kward/rpc/server.rb +76 -3
- data/lib/kward/rpc/session_manager.rb +43 -8
- data/lib/kward/rpc/transcript_normalizer.rb +14 -5
- data/lib/kward/sandbox/capabilities.rb +39 -0
- data/lib/kward/sandbox/command_runner.rb +28 -0
- data/lib/kward/sandbox/environment.rb +24 -0
- data/lib/kward/sandbox/linux_bubblewrap_runner.rb +71 -0
- data/lib/kward/sandbox/macos_seatbelt_runner.rb +96 -0
- data/lib/kward/sandbox/passthrough_runner.rb +13 -0
- data/lib/kward/sandbox/policy.rb +74 -0
- data/lib/kward/sandbox/runner_factory.rb +55 -0
- data/lib/kward/sandbox/unavailable_runner.rb +21 -0
- data/lib/kward/sandbox.rb +9 -0
- data/lib/kward/session_store.rb +26 -0
- data/lib/kward/skills/capture.rb +144 -0
- 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/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 +56 -8
- data/lib/kward/tools/search/code.rb +46 -12
- data/lib/kward/tools/search/web.rb +60 -17
- data/lib/kward/tools/search/web_fetch.rb +206 -38
- data/lib/kward/tools/web_search.rb +3 -1
- data/lib/kward/update_check.rb +2 -1
- data/lib/kward/version.rb +1 -1
- data/lib/kward/workspace.rb +18 -3
- data/lib/kward/workspace_factory.rb +17 -0
- data/templates/default/fulldoc/html/js/kward.js +1 -0
- data/templates/default/kward_navigation.rb +5 -2
- data/templates/default/layout/html/layout.erb +2 -0
- data/templates/default/layout/html/setup.rb +2 -0
- metadata +22 -2
data/doc/permissions.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
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 unless you separately enable [command sandboxing](sandboxing.md) for model-requested shell commands.
|
|
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. [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.
|
|
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
|
+
- [Command sandboxing](sandboxing.md): configure the separate OS boundary for model-requested shell commands.
|
|
179
|
+
- [Lifecycle hooks](lifecycle-hooks.md): add trusted local policy or automation around Kward events.
|
|
180
|
+
- [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/releasing.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Releasing Kward
|
|
2
2
|
|
|
3
|
-
Kward requires Ruby >= 3.
|
|
3
|
+
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.
|
|
4
4
|
|
|
5
5
|
Release steps before publishing:
|
|
6
6
|
|
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.
|
|
@@ -61,11 +62,12 @@ Detailed capability fields include:
|
|
|
61
62
|
- `auth`: Kward auth provider format, OpenAI and Anthropic OAuth, OpenRouter API-key login, GitHub/Copilot status reporting, and provider logout for stored credentials. GitHub OAuth login is CLI-only; RPC reports `supported: false` for the GitHub provider with a reason string.
|
|
62
63
|
- `memory`: opt-in structured memory support, interactive prompt injection only, JSON/JSONL local storage, and dedicated `memory/*` methods.
|
|
63
64
|
- `commands`: supported `commands/list` capability for prompt, skill, and plugin command sources, plus plugin execution through `commands/run` or plugin slash turns.
|
|
65
|
+
- `skillCapture`: capture a reviewed personal `SKILL.md` from any saved session’s active branch through `skills/captureSessions`, `skills/captureDraft`, and `skills/saveCapturedDraft`.
|
|
64
66
|
- `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`. MCP resources, prompts, sampling, and Streamable HTTP are explicitly unsupported for now.
|
|
65
67
|
- `startupResources`: supported startup resource listing for context, skills, prompts, and plugins.
|
|
66
68
|
- `extensionUi`: question bridge support via `ui/question` and `ui/answerQuestion`, plus plugin footer updates via `ui/footer`; other UI primitives are explicitly unsupported.
|
|
67
69
|
- `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
|
-
- `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`.
|
|
70
|
+
- `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`. `security.sandbox` reports the configured command-worker sandbox mode, enforcement backend, filesystem/network capability, and explicitly unsupported session pinning and one-time elevation. See [Command sandboxing](sandboxing.md) for its scope and limits.
|
|
69
71
|
- `export`: supported transcript export formats. Currently `markdown` and `html`; default is `markdown`.
|
|
70
72
|
- `starterPack`: explicitly unsupported (`supported: false`, reason `cliOnlyInstallCommand`). Use `kward init` from the shell.
|
|
71
73
|
- `shell`: explicitly unsupported (`supported: false`, reason `interactiveTuiOnly`) because `/shell` is the local embedded TUI shell.
|
|
@@ -276,6 +278,66 @@ Moves the active branch to the selected tree entry. If the entry is a user messa
|
|
|
276
278
|
|
|
277
279
|
Returns `{ "session": {}, "editorText": "...", "cancelled": false, "aborted": false }`. Fields with no value are omitted.
|
|
278
280
|
|
|
281
|
+
## Plugin chat methods
|
|
282
|
+
|
|
283
|
+
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.
|
|
284
|
+
|
|
285
|
+
### `pluginChats/open`
|
|
286
|
+
|
|
287
|
+
Params:
|
|
288
|
+
|
|
289
|
+
- `typeId`: an opted-in plugin chat type, such as `kward.maria`.
|
|
290
|
+
|
|
291
|
+
Opens the plugin-owned chat in this RPC process and returns its metadata plus normalized transcript.
|
|
292
|
+
|
|
293
|
+
### `pluginChats/transcript`
|
|
294
|
+
|
|
295
|
+
Params:
|
|
296
|
+
|
|
297
|
+
- `chatId`;
|
|
298
|
+
- `limit`: optional bounded page size for plugin drivers that support transcript paging;
|
|
299
|
+
- `before`: optional opaque cursor returned by a preceding page.
|
|
300
|
+
|
|
301
|
+
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.
|
|
302
|
+
|
|
303
|
+
### `pluginChats/subscribe` and `pluginChats/unsubscribe`
|
|
304
|
+
|
|
305
|
+
Params:
|
|
306
|
+
|
|
307
|
+
- `chatId`.
|
|
308
|
+
|
|
309
|
+
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.
|
|
310
|
+
|
|
311
|
+
### `pluginChats/turns/start`
|
|
312
|
+
|
|
313
|
+
Params:
|
|
314
|
+
|
|
315
|
+
- `chatId`;
|
|
316
|
+
- `input`;
|
|
317
|
+
- `attachments`: optional base64 image attachments using the same MIME and size limits as `turns/start`.
|
|
318
|
+
|
|
319
|
+
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.
|
|
320
|
+
|
|
321
|
+
### `pluginChats/turns/cancel`, `pluginChats/turns/status`, `pluginChats/turns/events`, `pluginChats/turns/list`, `pluginChats/turns/listActive`
|
|
322
|
+
|
|
323
|
+
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.
|
|
324
|
+
|
|
325
|
+
## Plugin chat notifications
|
|
326
|
+
|
|
327
|
+
Subscribed clients receive `pluginChat/event` notifications:
|
|
328
|
+
|
|
329
|
+
```json
|
|
330
|
+
{
|
|
331
|
+
"chatId": "kward.maria",
|
|
332
|
+
"turnId": "...",
|
|
333
|
+
"sequence": 1,
|
|
334
|
+
"type": "assistantDelta",
|
|
335
|
+
"payload": { "delta": "text" }
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Known event types are `turnQueued`, `turnStarted`, `reasoningDelta`, `reasoningBoundary`, `assistantDelta`, `assistantMessage`, `toolCall`, `toolResult`, `answer`, `turnCancelRequested`, and `turnFinished`.
|
|
340
|
+
|
|
279
341
|
## Turn methods
|
|
280
342
|
|
|
281
343
|
Turns are asynchronous. A session queues turns sequentially; only one turn runs per session at a time.
|
|
@@ -684,6 +746,16 @@ Params:
|
|
|
684
746
|
|
|
685
747
|
Returns frontend-neutral slash command metadata for configured prompt templates, skills, and plugins. Prompt command names omit the leading slash. Skill command names use `skill:<name>`. Plugin command names omit the leading slash and include `executable: true`. Builtin terminal-only commands are omitted. Prompt commands can be submitted directly to `turns/start` as slash commands or expanded first with `prompts/expand`; plugin commands can be submitted to `turns/start` or run explicitly with `commands/run`.
|
|
686
748
|
|
|
749
|
+
### `skills/captureSessions`, `skills/captureDraft`, and `skills/saveCapturedDraft`
|
|
750
|
+
|
|
751
|
+
Use this two-step workflow to capture a personal skill from a saved session:
|
|
752
|
+
|
|
753
|
+
1. Call `skills/captureSessions` to list available persisted session sources.
|
|
754
|
+
2. Call `skills/captureDraft` with `sessionPath`. Kward sends the selected active branch, including available raw tool output, to the active model provider and returns an editable `SKILL.md` draft. It rejects a source that exceeds the active model context rather than truncating it.
|
|
755
|
+
3. Review and edit `content`, then call `skills/saveCapturedDraft`. Set `overwrite: true` only after explicitly confirming replacement of an existing personal skill.
|
|
756
|
+
|
|
757
|
+
Captured skills are saved under the Kward config directory, are not activated automatically, and no file is written until the final save call succeeds.
|
|
758
|
+
|
|
687
759
|
### `resources/startup`
|
|
688
760
|
|
|
689
761
|
Params:
|
data/doc/sandboxing.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Command sandboxing
|
|
2
|
+
|
|
3
|
+
Kward can optionally apply an operating-system sandbox to model-requested
|
|
4
|
+
`run_shell_command` calls. The sandbox is a technical boundary for the command
|
|
5
|
+
and every process it starts; it is separate from Kward's [permission
|
|
6
|
+
policy](permissions.md), which decides whether Kward should start a tool at all.
|
|
7
|
+
|
|
8
|
+
Sandboxing is **off by default**. When you request a non-off mode and Kward
|
|
9
|
+
cannot enforce it on the current platform, the command is denied rather than
|
|
10
|
+
run without the requested boundary.
|
|
11
|
+
|
|
12
|
+
## Configure a command sandbox
|
|
13
|
+
|
|
14
|
+
Add a `sandbox` section to your user config, normally `~/.kward/config.json`:
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"sandbox": {
|
|
19
|
+
"mode": "workspace_write",
|
|
20
|
+
"network": "deny",
|
|
21
|
+
"writable_roots": [],
|
|
22
|
+
"protect_git_metadata": true
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Available modes are:
|
|
28
|
+
|
|
29
|
+
| Mode | Command filesystem writes |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| `off` | Existing unrestricted command behavior. |
|
|
32
|
+
| `read_only` | Workspace writes are denied. Kward gives the command a private temporary directory for command-local scratch files. |
|
|
33
|
+
| `workspace_write` | Writes are allowed in the active workspace and the private command temporary directory. |
|
|
34
|
+
|
|
35
|
+
`writable_roots` lets you grant additional, existing host paths to commands in
|
|
36
|
+
`workspace_write` mode—for example, a known local build cache. Configure these
|
|
37
|
+
paths only in your user config. Do not add a path merely because a repository
|
|
38
|
+
instruction or model response asks for it. `protect_git_metadata` defaults to
|
|
39
|
+
`true`; this prevents sandboxed commands from changing `.git`, including
|
|
40
|
+
staging and committing changes.
|
|
41
|
+
|
|
42
|
+
`network` controls child-process network access:
|
|
43
|
+
|
|
44
|
+
| Value | Child-process network access |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| `deny` | Denied by the operating-system backend. This is the default. |
|
|
47
|
+
| `allow` | Allowed with the same network reachability as your user account. |
|
|
48
|
+
|
|
49
|
+
## Interactive controls
|
|
50
|
+
|
|
51
|
+
Use `/sandbox` in the terminal UI to inspect or update the global policy:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
/sandbox status
|
|
55
|
+
/sandbox read_only
|
|
56
|
+
/sandbox workspace_write
|
|
57
|
+
/sandbox off
|
|
58
|
+
/sandbox network deny
|
|
59
|
+
/sandbox network allow
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Changes apply to newly created sessions and tabs. Existing turns keep the
|
|
63
|
+
workspace and command runner they started with, so start a new session or tab
|
|
64
|
+
after changing the mode.
|
|
65
|
+
|
|
66
|
+
## Platform support
|
|
67
|
+
|
|
68
|
+
| Platform | Backend | Status |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| macOS | Seatbelt through `/usr/bin/sandbox-exec` | Supported for command workers. Kward checks availability at runtime. |
|
|
71
|
+
| Linux | Bubblewrap | Supported when `bwrap` can create the required namespaces. |
|
|
72
|
+
| Windows | None | Unsupported. A requested non-off policy fails closed. |
|
|
73
|
+
|
|
74
|
+
On Debian or Ubuntu, install Bubblewrap with `sudo apt install bubblewrap`; on
|
|
75
|
+
Fedora, use `sudo dnf install bubblewrap`. A present `bwrap` executable can
|
|
76
|
+
still be prevented from creating namespaces by host policy. In that case,
|
|
77
|
+
Kward fails the command closed instead of running it unrestricted.
|
|
78
|
+
|
|
79
|
+
The macOS `sandbox-exec` utility is deprecated by Apple. Kward therefore treats
|
|
80
|
+
it as a capability-detected backend and verifies enforcement with platform
|
|
81
|
+
integration tests. It is not a promise that future macOS releases will retain
|
|
82
|
+
this interface.
|
|
83
|
+
|
|
84
|
+
## Boundaries and limits
|
|
85
|
+
|
|
86
|
+
The current implementation protects **model-requested command workers only**.
|
|
87
|
+
It does not sandbox:
|
|
88
|
+
|
|
89
|
+
- the Kward Ruby host process;
|
|
90
|
+
- model-provider, search-provider, or RPC traffic;
|
|
91
|
+
- trusted Ruby plugins;
|
|
92
|
+
- MCP servers, lifecycle hooks, `/shell`, `!command`, or `/pty`.
|
|
93
|
+
|
|
94
|
+
Sandboxed command workers receive a minimal environment: Kward preserves only
|
|
95
|
+
basic terminal, locale, and path variables, then supplies a private `HOME` and
|
|
96
|
+
temporary directory. Credentials and runtime-injection variables are not
|
|
97
|
+
inherited. On macOS, Seatbelt also denies reads from common credential locations
|
|
98
|
+
under the host home directory, including `.kward`, `.ssh`, `.aws`, `.gnupg`, and
|
|
99
|
+
selected cloud/CLI configuration directories.
|
|
100
|
+
|
|
101
|
+
This is defense in depth, not complete secret-file read isolation: commands
|
|
102
|
+
still receive system and development-tool reads needed for normal local work.
|
|
103
|
+
On Linux, Bubblewrap provides a read-only view of the host filesystem outside
|
|
104
|
+
its explicitly writable paths; it does not hide every file your account can
|
|
105
|
+
read. For sensitive repositories, use a disposable checkout, VM, or container
|
|
106
|
+
in addition to Kward's command sandbox.
|
|
107
|
+
|
|
108
|
+
The RPC `initialize.capabilities.security.sandbox` payload reports the active
|
|
109
|
+
mode, backend, and whether filesystem and child-network enforcement are active.
|
|
110
|
+
It also reports unsupported features, including session pinning and one-time
|
|
111
|
+
sandbox elevation; those are not available yet.
|
|
112
|
+
|
|
113
|
+
## Related guides
|
|
114
|
+
|
|
115
|
+
- [Security and trust](security.md) explains Kward's broader trust boundaries.
|
|
116
|
+
- [Permissions](permissions.md) controls whether Kward starts a model-requested
|
|
117
|
+
tool; it does not constrain a command after it starts.
|
|
118
|
+
- [Configuration](configuration.md#Command_sandboxing) covers the full config
|
|
119
|
+
section, while [Workspace tools](workspace-tools.md) explains the separate
|
|
120
|
+
file-tool guardrails.
|
data/doc/security.md
CHANGED
|
@@ -6,8 +6,8 @@ This guide explains the trust boundaries and gives you a safe way to start work
|
|
|
6
6
|
|
|
7
7
|
## The short version
|
|
8
8
|
|
|
9
|
-
- Kward and
|
|
10
|
-
- File tools stay inside the active workspace by default
|
|
9
|
+
- Kward and its trusted host-process extensions run with your operating-system permissions.
|
|
10
|
+
- File tools stay inside the active workspace by default. Model-requested shell commands can also use an opt-in OS-enforced command sandbox.
|
|
11
11
|
- Existing files must be read before Kward's file tools can edit or overwrite them.
|
|
12
12
|
- Plugins, MCP servers, command hooks, and HTTP hooks should be configured only from sources and endpoints you trust.
|
|
13
13
|
- Project skills and workspace hooks are disabled until you opt in or trust them.
|
|
@@ -16,6 +16,12 @@ This guide explains the trust boundaries and gives you a safe way to start work
|
|
|
16
16
|
|
|
17
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
18
|
|
|
19
|
+
## Local model endpoints and replacement prompts
|
|
20
|
+
|
|
21
|
+
The Local provider defaults to loopback endpoints. If you set `local_base_url` to another host, Kward can send prompts, selected workspace content, attachments, and tool results to that host. Treat a non-loopback endpoint as a model provider: use TLS and authentication where appropriate, and do not assume a private-network address is harmless.
|
|
22
|
+
|
|
23
|
+
A `system_prompt.file` replacement is model-visible and may be retained in session prompt snapshots. Do not put tokens, credentials, customer data, or other secrets in that file. Replacement mode intentionally removes Kward's normal prompt layers, including workspace guidance and skill descriptions; verify it with `kward sysprompt` before using a permissive local model.
|
|
24
|
+
|
|
19
25
|
## A safe first run in an unfamiliar repository
|
|
20
26
|
|
|
21
27
|
Start with project-provided extensions disabled, which is the default:
|
|
@@ -42,7 +48,7 @@ Before enabling or running anything:
|
|
|
42
48
|
6. Do not add repository-provided Ruby files to `~/.kward/plugins` unless you are willing to run them as your user.
|
|
43
49
|
7. Ask Kward to explain proposed edits and commands before applying them when the impact is unclear.
|
|
44
50
|
|
|
45
|
-
For especially sensitive work, use a disposable checkout, container, virtual machine, or restricted operating-system account.
|
|
51
|
+
For especially sensitive work, use a disposable checkout, container, virtual machine, or restricted operating-system account. Enable [command sandboxing](sandboxing.md) for model-requested shell commands, but remember that its first release does not sandbox the Kward host process, plugins, MCP servers, hooks, or interactive shell features.
|
|
46
52
|
|
|
47
53
|
## Workspace access is a guardrail, not a sandbox
|
|
48
54
|
|
|
@@ -50,8 +56,8 @@ Kward's built-in file tools normally resolve paths inside the active workspace.
|
|
|
50
56
|
|
|
51
57
|
These protections reduce accidental edits. They do not contain the whole process:
|
|
52
58
|
|
|
53
|
-
- `run_shell_command`, `!command`, `/shell`, and `/pty` run with your user permissions.
|
|
54
|
-
- A
|
|
59
|
+
- With `sandbox.mode: off` (the default), `run_shell_command`, `!command`, `/shell`, and `/pty` run with your user permissions.
|
|
60
|
+
- A non-off [command sandbox](sandboxing.md) restricts only model-requested `run_shell_command` workers and their descendants. It does not cover `!command`, `/shell`, or `/pty`.
|
|
55
61
|
- Plugins, command hooks, and MCP servers are local processes with the same general operating-system access.
|
|
56
62
|
- Read-before-edit applies to Kward's file tools, not to arbitrary shell commands or extension code.
|
|
57
63
|
|
|
@@ -69,6 +75,10 @@ Pan mode does not provide a dedicated hook-approval UI. Use `deny` or `warn` for
|
|
|
69
75
|
|
|
70
76
|
See [Lifecycle hooks](lifecycle-hooks.md) for policy examples and [RPC protocol](rpc.md#Tool_approval_bridge) for the approval contract.
|
|
71
77
|
|
|
78
|
+
## Opt-in permission policy
|
|
79
|
+
|
|
80
|
+
`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.
|
|
81
|
+
|
|
72
82
|
## Know what you are trusting
|
|
73
83
|
|
|
74
84
|
### Workspace instructions
|
data/doc/skills.md
CHANGED
|
@@ -42,6 +42,16 @@ The `name` and `description` fields are required. The description matters: Kward
|
|
|
42
42
|
|
|
43
43
|
Skill names should be lowercase letters, numbers, and hyphens, such as `testing`, `code-review`, or `release-checklist`.
|
|
44
44
|
|
|
45
|
+
## Capture a skill from a session
|
|
46
|
+
|
|
47
|
+
Use `/skill capture` after a useful session. Choose any saved session; Kward uses its active branch and asks your active model to draft a reusable `SKILL.md`. Review and edit the draft in the terminal editor, then save it explicitly. Captured skills always go to your personal Kward skill directory and are not activated automatically.
|
|
48
|
+
|
|
49
|
+
The draft request includes the complete persisted branch, including available raw tool output and saved session context. Treat it like any other model request: do not capture a session whose contents you are not willing to send to the active provider. Kward rejects a source that does not fit the active model context instead of silently truncating it.
|
|
50
|
+
|
|
51
|
+
If the reviewed name already exists, Kward requires an explicit overwrite confirmation. Activate a saved draft later with `/skill <name>`.
|
|
52
|
+
|
|
53
|
+
Pan provides the same saved-session picker and editable review flow. RPC clients use `skills/captureSessions`, `skills/captureDraft`, and `skills/saveCapturedDraft`; see the [RPC protocol](rpc.md).
|
|
54
|
+
|
|
45
55
|
## Skill locations
|
|
46
56
|
|
|
47
57
|
User-level skills are available in every project:
|
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
|
|
data/doc/web-search.md
CHANGED
|
@@ -85,7 +85,9 @@ Arguments:
|
|
|
85
85
|
- `max_bytes`: default 16384, capped at 131072.
|
|
86
86
|
- `extract`: optional `auto`, `text`, or `markdown`.
|
|
87
87
|
|
|
88
|
-
In `auto` mode (default), Kward detects HTML content and extracts readable text
|
|
88
|
+
In `auto` mode (default), Kward detects HTML content and extracts readable text while stripping scripts, styles, navigation prose, and forms. It preserves headings, paragraphs, ordered and unordered lists, code blocks, blockquotes, simple tables, and inline link destinations. A bounded `Links` section lists discovered main-content and navigation destinations so an agent can continue through a site without raw HTML. Relative links are resolved against the final fetched URL. Non-HTML content is returned as cleaned text. Use `markdown` to retain Markdown structure, or `text` for plain text with link destinations in parentheses.
|
|
89
|
+
|
|
90
|
+
Kward downloads and parses up to 2 MB of a page before applying `max_bytes` to the extracted result. This lets pages with large scripts or metadata before their main content remain readable while keeping model-facing output bounded. Responses above the download limit are rejected rather than parsed as incomplete HTML.
|
|
89
91
|
|
|
90
92
|
Fetches follow up to 5 redirects and use a 10-second HTTP timeout.
|
|
91
93
|
|
|
@@ -99,4 +101,4 @@ Arguments:
|
|
|
99
101
|
- `max_bytes`: default 16384, capped at 131072.
|
|
100
102
|
- `accept`: optional HTTP `Accept` header.
|
|
101
103
|
|
|
102
|
-
Fetches follow up to 5 redirects and use a 10-second HTTP timeout.
|
|
104
|
+
Fetches follow up to 5 redirects, enforce the requested byte limit while reading the response, and use a 10-second HTTP timeout.
|
data/doc/workspace-tools.md
CHANGED
|
@@ -12,14 +12,14 @@ Kward normally chooses these tools itself. You do not need to know their exact n
|
|
|
12
12
|
|
|
13
13
|
## Guardrails
|
|
14
14
|
|
|
15
|
-
Workspace tools use the active workspace as their boundary. File paths are workspace-relative by default, and file tools are guarded so Kward does not edit arbitrary unread files. Guardrails can be disabled with the `tools.workspace_guardrails` setting — see [Configuration](configuration.md). When disabled, file tools can access paths outside the workspace
|
|
15
|
+
Workspace tools use the active workspace as their boundary. File paths are workspace-relative by default, and file tools are guarded so Kward does not edit arbitrary unread files. Guardrails can be disabled with the `tools.workspace_guardrails` setting — see [Configuration](configuration.md). When disabled, file tools can access paths outside the workspace. These guardrails do not affect shell commands; model-requested commands can instead use the separate, opt-in [command sandbox](sandboxing.md).
|
|
16
16
|
|
|
17
17
|
Important behavior:
|
|
18
18
|
|
|
19
19
|
- Existing files must be read in the current conversation before `write_file` or `edit_file` can change them.
|
|
20
20
|
- Reads are bounded to avoid pulling very large files into context by accident. Files larger than 256 KB cannot be read or edited. Read output is capped at 50 KB or 2,000 lines, whichever comes first.
|
|
21
21
|
- Edits use exact text replacement, so accidental partial or fuzzy changes fail instead of guessing.
|
|
22
|
-
-
|
|
22
|
+
- With sandboxing off (the default), shell commands run as your operating-system user from the workspace. Enable [command sandboxing](sandboxing.md) to apply an OS boundary to model-requested `run_shell_command` workers. Command output is capped at 128 KB.
|
|
23
23
|
|
|
24
24
|
## Reading the workspace
|
|
25
25
|
|
|
@@ -124,7 +124,7 @@ Arguments:
|
|
|
124
124
|
- `command`: command to run.
|
|
125
125
|
- `timeout_seconds`: optional timeout, default 30 seconds.
|
|
126
126
|
|
|
127
|
-
Kward uses shell commands for tests, linters, build checks, and simple repository inspection. Command output is bounded at 128 KB and may be compacted before it is sent back into model context, while the original output remains available in the session record.
|
|
127
|
+
Kward uses shell commands for tests, linters, build checks, and simple repository inspection. When configured, the [command sandbox](sandboxing.md) applies to this tool and its descendants. Command output is bounded at 128 KB and may be compacted before it is sent back into model context, while the original output remains available in the session record.
|
|
128
128
|
|
|
129
129
|
The output format is `Exit status: N` followed by `STDOUT:` and `STDERR:` sections. On timeout, Kward sends SIGTERM then SIGKILL after 0.2 seconds and returns a timeout error. Commands support cooperative cancellation when the session is cancelled.
|
|
130
130
|
|
data/kward.gemspec
CHANGED
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
|
10
10
|
spec.description = "Kward is a Ruby CLI coding agent with local workspace tools, configurable prompts, web search, sessions, and an experimental JSON-RPC backend."
|
|
11
11
|
spec.homepage = "https://github.com/kaiwood/kward"
|
|
12
12
|
spec.license = "MIT"
|
|
13
|
-
spec.required_ruby_version = ">= 3.
|
|
13
|
+
spec.required_ruby_version = ">= 3.4"
|
|
14
14
|
|
|
15
15
|
spec.metadata["rubygems_mfa_required"] = "true"
|
|
16
16
|
spec.metadata["source_code_uri"] = "https://github.com/kaiwood/kward"
|