Skip to content

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 01 Jul 13:09
· 6 commits to main since this release
ca7ff00

Security

  • Model-triggered bash calls now run with a scrubbed subprocess environment:
    ambient variables whose name matches KEY/TOKEN/SECRET/PASSWORD/
    PASSWD/CREDENTIAL, plus the configured backend.api_key_env, are dropped
    before the child process starts. Previously bash subprocesses inherited the
    full parent environment, so a shell command could read out the backend API
    token or other ambient credentials it was never granted (#190).
  • guarded mode's local-read guard now also denies known secret-bearing paths
    — the resolved token file, a distinct configured backend.api_key_file, and
    common credential fragments such as .ssh, .env, id_rsa, token,
    secret, credentials — the same check readonly already enforced.
    Previously this path check only ran in readonly, so the default guarded
    mode could file_read a secret file straight through (#191).
  • Tool call input, tool observation, thought, final replies, and PostToolUse
    audit-hook payloads are now scanned for known secret values (the resolved
    backend token and the value of any ambient secret-named env var) and
    redacted to [REDACTED] before they reach the audit log, trace output, or
    structured event sink. Previously these channels recorded raw text
    verbatim, so a secret surfaced by any tool call could be durably persisted
    in logs/audit.jsonl. The live conversation history sent back to the model
    is unaffected — only recording/observability channels are redacted (#189).

Added

  • The audit log (logs/audit.jsonl) now rotates into a bounded, gap-tracked
    chain of numbered generations (logs/audit.jsonl.<gen>) instead of a single
    destructively-overwritten .1 backup. A durable logs/audit.jsonl.gen
    sidecar tracks the current generation across process restarts; up to
    [audit].max_retained_generations (default 8, override
    SCOOT_AUDIT_MAX_RETAINED_GENERATIONS) retired generations are kept, and any
    eviction beyond that cap is durably recorded in
    logs/audit.jsonl.gaps.jsonl rather than silently disappearing. scoot doctor now reports audit.retention as WARN if any gap was ever
    recorded. This removes the audit-history data-loss blocker that a future
    scoot-edge audit shipper would otherwise hit (#187).
  • scoot-edge E2 job dispatch: scoot-edge dispatch (one-shot) and
    scoot-edge run --enable-jobs (folded into the heartbeat loop) poll a GET
    job lease, schema-validate each envelope, and execute accepted jobs as
    scoot --unattended -e "<goal>" --session-id job-<job_id> with cwd confined
    to a required --job-root (never $HOME or /). Both require --job-root
    and --lease-url; either missing, or --lease-url not HTTPS without
    --allow-insecure-http, is a config error (exit 2), matching the existing
    --center-url/token gate. A bounded, persistent idempotency store
    (edge/idem.jsonl, capped by --idem-cap, default 500) re-acks a
    redelivered idem_key's prior outcome instead of re-running the job, and
    every phase transition (accepteddone/failed/rejected) is both
    POSTed as a job_event and appended to an edge-side provenance log
    (logs/edge-audit.jsonl), correlated by session_id to Scoot's own run
    audit. A new core --session-id <id> flag on scoot -e lets a caller pin
    the session file name instead of the default UUID, which is what makes this
    job_idsession_id correlation possible (#186).
  • scoot-edge E3 packaging (complete): the release workflow builds,
    archives (scoot-edge-<target>.tar.gz + .sha256), and publishes a
    scoot-edge Homebrew formula (brew install jamiesun/tap/scoot-edge,
    depending on scoot) for every tagged release, mirroring the existing
    scoot-wasm packaging. install.sh gained an opt-in SCOOT_INSTALL_EDGE
    variable that additionally downloads and installs scoot-edge alongside
    core scoot; it is never installed unless explicitly requested. A new
    optional apt job (gated by APT_TAP_TOKEN, mirroring the Homebrew job's
    HOMEBREW_TAP_TOKEN) builds a .deb per Linux architecture and pushes it
    to the shared jamiesun/apt-tap
    repository, which owns the GPG signing key and publishes the signed apt
    index to GitHub Pages on every push, closing out #171.

Documentation

  • Fixed docs, README, and book examples that showed the unattended one-shot
    clamp as scoot -e --unattended <goal> — a rejected argv order, since
    -e/--eval greedily consumes the very next token as the goal string.
    Examples and prose now consistently show the accepted
    scoot --unattended -e "<goal>" order (#192).

Install

curl -fsSL https://raw.githubusercontent.com/jamiesun/scoot/main/install.sh | sh

Add SCOOT_INSTALL_EDGE=1 to the same command to also install the optional
scoot-edge fleet companion (never installed unless requested).

macOS (Homebrew):

brew install jamiesun/tap/scoot          # the agent
brew install jamiesun/tap/scoot-wasm      # optional Wasm compute-unit host (pulls in scoot)
brew install jamiesun/tap/scoot-edge      # optional fleet companion (pulls in scoot)

Debian/Ubuntu (apt, scoot-edge only, amd64/arm64/armhf):

curl -fsSL https://jamiesun.github.io/apt-tap/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/jamiesun-apt-tap.gpg
echo "deb [signed-by=/usr/share/keyrings/jamiesun-apt-tap.gpg] https://jamiesun.github.io/apt-tap stable main" | sudo tee /etc/apt/sources.list.d/jamiesun-apt-tap.list
sudo apt update && sudo apt install scoot-edge

Build flavors

Prebuilt archives are ReleaseSafe only (runtime safety checks on). If you
need a smaller binary, compile from source:

zig build -Doptimize=ReleaseSmall   # smallest, fewer safety checks

Each target also ships a separate scoot-wasm-* archive (the optional
standalone Wasm host) and a separate scoot-edge-* archive (the optional
fleet companion). The zero-dependency core scoot binary never embeds either.