scoot 0.10.0
The second release from the outside review of 0.8.1: the findings that change what a repository can make scoot do. The yolo default stays.
- A cloned repository cannot reconfigure you (R02). A project
.envcould set anySCOOT_*variable, including a provider base URL, which sent your own API key to a host of the repository's choosing on the first request, in every approval mode. The project layer now has a narrower allowlist: it may choose the model, effort, and terminal settings, but not base URLs, proxies, the approval mode, the scope, the root, hooks, or scoot's config and state directories. Those keys are ignored from a project file and named in a notice at start; your global~/.config/scoot/.envand the environment still set them. Breaking for anyone who kept a base URL or a proxy in a project.env: move it to the global file. - Project hooks need your trust (R01).
.scoot/hooks.jsonran shell commands at session start in an unfamiliar checkout, before any approval. It now runs only after you review it and run/hooks trust; the trust is a digest of the file, so an edited file asks again, and/hooks untrustwithdraws it./hookssays whether the project file is trusted, and an untrusted one is named at start (REPL, one-shot, and a headlessnotice). Adenyfrom any hook now wins over anallowfrom another (an early projectallowused to hide a globaldeny), a project hook'sallowno longer waives the denylist confirmation (a hook in your own global config still does, so an editor or phone bridge that approves on your behalf keeps working), and provider API key variables are removed from every hook's environment, as the module always claimed. - The README says what is true (R03). The security section no longer claims shell tools are sandboxed: file tools are scoped,
run_shellruns as you, and the denylist is an accident guard. The denylist now recognisesrm -r -f,rm --recursive --force,git -C repo push, andgit --git-dir=x push. - Search cannot read outside the workspace (R07). Without ripgrep, the fallback followed symlinks and scanned hidden files, so a link inside a repository disclosed an external file through an auto-approved tool, and
.envwas searchable. It now walks like ripgrep does by default: no hidden files or directories, no symlinks, regular files only. The workspace map skips symlinks too. - Redaction reaches everything it can (R13). Saved sessions masked key-shaped strings only in top-level message text; tool arguments, list-shaped content, and the text copies inside provider replay items kept them. Redaction is now recursive, and stops only at signed or encrypted replay fields, which the provider rejects when changed. The README states that limit and that streamed output is not filtered.
- Headless answers name their request (R20). An
approvemessage without anid, or with another request's id, used to be accepted, so a queued answer could approve whatever came next. It is now a protocol error and ignored. [A]works (R20). The approval and scope menus advertised uppercaseAfor the session-wide choice, but every keypress was lowercased, soAmeant "once".Anow keeps its case; every other key is still case-insensitive.--rootdecides which.envapplies. The project.envwas searched from the launch directory, then the root was switched, soscoot --root ~/othercarried the launch directory's settings into the other project. The search now starts at the root.- Bounded reads (R15).
read_filerefuses FIFOs and devices, which would block, and reads the cap plus one byte instead of the whole file; an oversized image is rejected by size before it is read. - The user's prompt stands out. A submitted prompt is echoed as a full-width reverse-video band instead of a bold line, so it reads as clearly separate from the assistant's answer. Reverse video swaps the terminal's own colours, so it fits any theme; the band uses the current terminal width, so a resize shows on the next prompt; a multi-line or wrapped prompt becomes stacked bands. Without a TTY, under
NO_COLOR, or with--no-labelsit falls back to a plain❯line. - Session ids are file names (R17).
/forget ../xcould delete a JSON file next to the sessions directory. Ids are validated as basenames at every entry point, a malformed saved record is skipped when listing instead of breaking startup, and records are shape-checked on load.
Install: pipx install scootcli && pipx ensurepath, or curl -fsSL https://raw.githubusercontent.com/sergenes/scootcli/main/install.sh | bash, or download scoot.pyz below. Upgrade: pipx upgrade scootcli.