Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
- Added launch contributors (`launch:contribute`): a trusted plugin service can declare launcher options (boolean, select, text) shown under **Advanced** in the agent launcher. For launches where the person chose the plugin, and their restarts and restores, CanvasTTY asks the service to prepare the launch and adds its environment variables, secret variables resolved from the plugin's own secrets (masked in text other agents and the control CLI read), arguments and per-run files. Contributors merge in plugin-id order; a refusal, a 5 s timeout, a conflict, a reserved name or an approval/conversation argument refuses the launch with the reason on the card, and a restored card whose plugin is unavailable comes back stopped. The chosen values are saved with the session. A contributor may also declare `launch.policy`: it is then asked before every launch of its agents where the person did not choose it (`chosen: false`), may only refuse, and no answer refuses too. Examples: `examples/plugins/launch-env`, `examples/plugins/yolo-guard` (a launch policy).
- Added session environments (`environment:provide`): a trusted plugin service can offer places a card runs in (a git worktree, a container, a remote host), chosen under **Where** in the launcher's Advanced section; terminals get the same launcher while such an environment applies to them. The service prepares the place once, then wraps every start (validated: an absolute program path or a bare name resolved on PATH, never a shell string; launch-contributor env rules; plugin secrets masked) while CanvasTTY keeps spawning the PTY. The opaque ref is saved with the card; restore resumes environments first, then parents before children, and a missing, disabled or untrusted plugin, a stopped environment or a timeout brings the card back stopped with the reason, never run locally. Closing such a card asks once "Keep environment data?" and releases it accordingly. Launch contributors and policies are told the card's environment (`environment` in `canvastty.launch.prepare`). Example: `examples/plugins/env-worktree` (one git worktree per card).
- Added base protection and decision hooks. Base protection (Settings → Agents, on by default, the person can turn it off) refuses, before a local Claude Code, Codex, Qwen Code or OpenCode tool call runs (YOLO included), sudo and other elevation, curl | sh and download-and-run, disk and format commands, fork bombs, and writes or deletes outside the working folder (`/tmp` and the home folder included, and deleting the folder itself; the agent's own plan and memory folders excepted), telling the model what to do instead. A trusted plugin service can declare `decide` (`decision:provide`) and answer `canvastty.decide` with deny, ask or allow: base protection runs first, any deny wins, a timeout or error asks the person, and an allow counts only after a separate **May allow agent actions** confirmation. A service may declare `decide.timeoutMs` (1–60 s, 3 s by default): CanvasTTY waits that long, tells the service its `budgetMs`, and sizes each card's hook, helper and gateway deadlines at launch for the longest budget that applies (the default keeps today's deadlines). Example: `examples/plugins/deny-rm`. Every text one agent reads from another (`observe_agent`, `get_agent_result`, the control CLI's screen, result and failure details) is now masked for vault keys, launch secrets, values a service registers (`redaction.register`) or reads (`secrets.get`), keys wrapped over lines, and common key shapes.
- The decision hook now fails closed. While base protection is on or a decision plugin applies, a Claude Code, Codex, Qwen Code or OpenCode shell or file-writing call that CanvasTTY cannot check (the socket is missing or refused, no answer in time, an unreadable answer, the gateway's own failure where the CLI cannot ask, hook input it cannot read) is refused with "CanvasTTY safety check unavailable" instead of running unchecked. With base protection off and no decision plugin nothing changes, and answered calls take no extra time.
- Base protection now reads more command forms: a command after `do`, `then`, `else`, `if`, `while`, `until` or `!`; `env -i`/`-u`/`-C`/`-S`, `stdbuf`, `busybox`/`toybox` applets and `script -c` / `script file cmd`; `perl -i` and `ruby -i` in-place edits; `find -L`/`-H`/`-P`/`-O2`/`-f`; `cp`/`mv`/`install`/`ln -t DIR`; `tar -C DIR -x…` and `--directory=`; `unzip -o … -d DIR`; bundled `curl -fsSLo FILE`, `--output=`, `--output-dir` before or after `-O`/`-o` (a relative `-o` lands in it), the cookie jar, header dump, trace, `--stderr`, `--libcurl`, `--etag-save`, `--hsts`, `--alt-svc` and `-w '%output{FILE}'` files in every spelling, `wget -qO`/`-qP`, its log (`-o`/`-a`/`--output-file`/`--append-output`), `--save-cookies`, `--rejected-log` and `--warc-file`; `-o /dev/null` and `-D -` write no file and are no longer refused. Each is refused outside the project exactly like the plain command, a download run in the same command is download-and-run however its output flag is written, and the same forms inside the project stay allowed (`find -L dir -exec rm {} +` inside the project is no longer refused).
- Added plugin agent tools, session events and card badges and actions. A trusted service can offer `tools` (`tools:agents`) that appear in `canvastty_agents` as `<pluginId>__<tool>` (dots in the id as `_`, the tool-name shape Anthropic and OpenAI accept) for the session roles they list (orchestrator, agent, subagent; Claude Code, Codex, Qwen Code, OpenCode); calls carry the caller's session id, and answers are masked, capped at 32 K characters and 15 s. A service can subscribe to card events (`sessions:events`: created, restored, status, exited, closed, with folders and the environment ref; the end of the output only with `sessions:read-screen`, masked), start cards through the normal launch pipeline (`sessions:launch`), and type into or close only the cards it started (`sessions:control`; ownership is saved with the card, so it survives a restore). With `cards:decorate` it sets plain-text badges on cards and adds actions to the card menu of matching cards (provider, environment kind, role); the answer shows as a toast on the card. Example: `examples/plugins/collect-demo` (**Show changes** on worktree cards and `collect-demo__diffstat` for orchestrators).
- Reworked "Windows after restart" into one "Agent sessions after restart" model: **Don't save**, **Reopen windows** (new conversations), or **Continue conversations** (the old "on" migrates here). Claude Code and OpenCode now resume their own conversation by the id their lifecycle hook reported, as Codex does (`claude --resume`, `opencode --session`); two cards of one CLI in one folder no longer continue the same conversation. Finished agents come back stopped with Restart / Continue instead of rerunning, the card options menu has **Don't restore this card**, and session records (v2, read-compatible with v1) keep no scrollback, prompts or secrets.
- Made the agent orchestration endpoint an explicit setting (Settings → Agents → "Agent orchestration endpoint", `agentControlEnabled`, off by default; `--agent-control` / `CANVASTTY_AGENT_CONTROL=1` still force it on for one launch) that starts and stops the endpoint at runtime, and added an **Orchestrator** role to the launch dialog next to the normal/YOLO profile: the session keeps the provider you opened the dialog for, gets `CANVASTTY_CONTROL_CONNECTION` and `CANVASTTY_CONTROL_CLI` in its environment so the bundled CLI works without setup, shows an "Orchestrator" badge, keeps its role across restore, and the dialog offers to enable the endpoint first when it is off instead of enabling anything silently. The endpoint's `create` now accepts every agent provider (`codex, claude, qwen, kimi, opencode, hermes, grok, omp, pi`) and reports `capabilities { result, menus }` per worker on `create` and `list`: both are `true` for Codex only; other providers' `screen` has no menu interaction, `choose`/`dismiss` fail with `NOT_SUPPORTED`, `send` relies on the idle status alone, and `result` completes as `no_result`.
Expand Down
Loading
Loading