Skip to content

Collomia v0.1.8

Choose a tag to compare

@github-actions github-actions released this 26 Jul 22:19
· 116 commits to main since this release
d1a2249

What's Changed

Collomia v0.1.8 narrows the command sandbox's network boundary from a single all-or-nothing switch to a per-host allowlist on macOS, and removes the two things that most often make a first session go badly: a provider key that has to live in a dotfile, and an agent that reads your code by grepping for names.

Configuration stays at schema_version: 1. No config file is rewritten by upgrading, and nothing in this release changes behavior by default — the one new containment setting ships off and no preset selects it.

Scoped egress (macOS)

Per-host command networking. sandbox_allow_network is all-or-nothing, which makes it the first thing you turn off the moment a build needs a package registry. permissions.sandbox_egress: "scoped" is the narrower alternative: the OS sandbox denies direct remote traffic while leaving loopback reachable, and commands are routed through a Collomia-owned loopback proxy that dials only the hosts your allow rules name.

{
  "permissions": {
    "sandbox": "auto",
    "sandbox_egress": "scoped",
    "rules": [
      { "action": "allow", "host": "proxy.golang.org", "reason": "Go module proxy" },
      { "action": "allow", "host": "*.githubusercontent.com", "reason": "raw file fetches" }
    ]
  }
}

No second list to maintain. The allowlist is built from the same host rules the permission layer already matches, through the same matcher — so a host a rule allows and a host a command can reach cannot drift apart.

No TLS interception. An approved tunnel is spliced byte for byte. No certificate is substituted and nothing decrypts your traffic. It is also why no SNI inspection is involved: the broker dials the host it was handed, so a command cannot name one destination and reach another.

It covers everything, including background processes. Foreground commands, start_process, and delegated-agent verification are brokered on the same terms, with a background process's broker living as long as the process rather than the tool call that started it.

Refusals tell you what to add. A blocked connection fails with the host and the exact rule that would permit it, and collo policy check forecasts which of a command's endpoints would be allowed before you rely on a run. collo doctor and the Session tab show the effective posture and allowlist size, and warn when scoped is on with no host rule — a valid but almost always accidental state where every connection is refused.

macOS only, and deliberately so. This is enforcement only where the sandbox can deny remote traffic while keeping loopback reachable. Seatbelt can; the other two genuinely cannot, for different reasons:

  • Linux (Landlock) filters TCP by port and never by address. Allowing the broker's port would allow every remote host on that port — and the exfiltration adversary this exists to stop picks its own port. Rather than ship an allowlist that the thing it guards against can step around, Collomia ships none and says why.
  • Windows (AppContainer) blocks loopback to unpackaged local services, so a sandboxed command cannot reach the broker at all. The documented workaround needs administrator rights and leaves persistent machine state, which the no-install Windows backend deliberately does not take.

On both, scoped is refused under "sandbox": "require" and degrades visibly under "auto", leaving sandbox_allow_network in charge — which AppContainer in particular enforces more completely than either Unix backend, covering UDP and DNS. With "sandbox": "off" no broker starts anywhere: without OS-level denial a proxy is a convention any program can ignore, and Collomia will not present that as a boundary.

Provider credentials in the OS keychain

collo auth set | list | status | rm | import keeps provider API keys in the macOS Keychain or Windows Credential Manager instead of a dotfile. Keys are prompted for without echo, never placed in an argument or your shell history, and never printed back.

Your environment still wins. The store is consulted only after api_key, api_key_env, and a provider family's own variable, so an exported variable keeps working exactly as before and no existing configuration changes meaning.

No keychain dialog if you don't use it. A machine that has never stored a credential makes no credential-manager call at all — a local name index is checked first, and its absence ends the lookup.

No Linux backend, by design. Secret Service needs a desktop session headless hosts don't have, and a passphrase-protected file would only move the problem. collo auth and collo doctor state the absence rather than degrading quietly; Linux hosts use api_key_env.

collo auth status and collo doctor report where each provider's credential came from, and mark an entry the OS no longer holds as missing rather than implying it works.

Code intelligence

find_definition and find_references on the existing language-server client — real type-aware navigation instead of lexical search. Located by file, line, and the symbol's own text, because the protocol counts columns in UTF-16 code units and asking a model to count them buys confident answers about the wrong token.

format_file applies the language server's own formatting as an ordinary tracked, undoable write, and refuses to write if the file changed while the server was formatting it.

Missing capabilities are explained, not relayed. format_file used to fail with the raw string Unhandled method textDocument/formatting. A method-not-found answer is now a configuration answer naming the server, the missing capability, and the setting to change.

You can tell a slow index from a hang. The four language-server tools stream starting <server>… and <server> ready in <time>, so a cold server indexing a large repository no longer looks identical to a stall.

Code actions are deliberately not implemented yet: organize-imports and quick fixes need codeAction/resolve round trips and workspace edits spanning files, and a half-working mutation path is worse than an absent one.

Terminal UI

Word wrap is fixed when the context rail is open. The rail is composited over the transcript row by row, so any line wider than the body was being cut at the rail's left edge instead of wrapped — answers, prompts, system and error lines, tool output, and panels all measured themselves against the terminal rather than the space they actually had. They now measure against the body width, prose word-wrapped and tool output hard-wrapped inside its gutter.

alt+m releases and reclaims the mouse mid-session. Mouse reporting and your terminal's own drag-selection are mutually exclusive by protocol, so copying text used to mean restarting with options.mouse off.

options.dim_background makes the modal scrim optional. Dropping color behind a dialog is right for using the tool and wrong for photographing it, and product documentation is made of screenshots. The cleared gutter around a dialog is deliberately not part of the option — reading a modal must never depend on the dimming.

A composed first screen. The identity line under the logo ran past a hundred columns, and because a centred block is centred by its widest line, that one line dragged the whole header off-axis and left the wordmark hanging. It is now two short centred lines, with a five-row wordmark and the blossom beside it. Build detail moved to the Session tab and collo version.

Upgrade notes

This is a quiet upgrade — there is no behavior change to absorb. Two things are worth knowing:

  1. Three new tools are available to the model. find_definition, find_references, and format_file. format_file writes, so it goes through the normal approval path and is tracked and undoable like any other write. Note that pyright — the auto-detected Python default — navigates but cannot format; pylsp does all three and type-checks less well.
  2. Adopting sandbox_egress: "scoped" needs an allowlist first. A build that fetches from a registry no rule names will fail until you add one. Run collo policy check "<your command>" to see which endpoints would be refused before relying on it, and remember that a project .collomia.json does nothing until collo trust.

Also in this release

collo policy check gained a sandbox_egress posture line and a per-endpoint egress forecast. collo doctor and the Session tab report the effective egress stance. The capability matrix carries a scoped-egress row reflecting what the current platform can actually enforce rather than what the setting accepts.

Internally, command-runner construction was collapsed to a single site — delegated verification previously built its own, which is how a containment setting ends up applied in your main session and silently absent for delegated agents — with a test that now fails on a second one. Install documentation uses vX.Y.Z placeholders instead of concrete versions, so install examples can no longer go stale, enforced by an inverted guard that fails on an ordinary push rather than mid-release.

The roadmap's last remaining P0 outside Phase 8 was reclassified to P1 on the evidence that the enforced network boundary it was meant to add already existed on all three platforms; scoped egress is a usability improvement over that enforced control, not a hole being closed. See ROADMAP.md.

Install

curl --proto '=https' --tlsv1.2 -fsSL \
  https://raw.githubusercontent.com/robert-mcdermott/collomia/main/install.sh |
  COLLO_VERSION=v0.1.8 sh

See INSTALLING.md for Windows, per-user directories, and upgrade behavior.

Full changelog: v0.1.7...v0.1.8