diff --git a/_posts/2026-07-01-your-coding-agent-will-always-tell-you-its-safe.md b/_posts/2026-07-01-your-coding-agent-will-always-tell-you-its-safe.md index a59929f..3e916af 100644 --- a/_posts/2026-07-01-your-coding-agent-will-always-tell-you-its-safe.md +++ b/_posts/2026-07-01-your-coding-agent-will-always-tell-you-its-safe.md @@ -67,9 +67,9 @@ So trust can't come from the agent's account of itself. It has to come from outs ## Why perch exists -That's perch, built to exactly that spec: a macOS notch and menu bar monitor for Claude Code and Codex sessions, watching on two axes. Actions: every tool call is risk-scored offline the instant it fires — when an agent runs something dangerous, a red card drops from the notch with the exact command and why it was flagged, even when the call was auto-approved. The riskiest calls are exactly the ones nobody asks you about. And footholds: a live scan of the persistence surface — config, hooks, memory files, MCP servers, LaunchAgents — read straight from disk, so it also catches what happened before perch launched. That payload from three sessions ago? This is the scan that catches it. Sessions, rate limits, and token usage ride along in the same glance. +That's perch, built to exactly that spec: a macOS notch and menu bar monitor for Claude Code and Codex sessions, watching on two axes. Actions: every tool call is risk-scored offline the instant it fires — when an agent runs something dangerous, a red card drops from the notch with the exact command and why it was flagged, even when the call was auto-approved. The riskiest calls are exactly the ones nobody asks you about. And footholds: a live scan of the persistence surface — config, hooks, memory files, MCP servers, LaunchAgents — read straight from disk, so it also catches what happened before perch launched. That payload from three sessions ago? This is the scan that catches it. Sessions, rate limits, and token usage ride along in the same glance — and a monitoring-health strip applies the same skepticism to perch itself: it won't call an agent's coverage *verified* until a real event from that agent has actually arrived. -![Perch in the notch: security score, a Bash call flagged dangerous, live agent sessions, rate-limit gauges](/assets/img/perch-notch.png) +![Perch in the notch: verified monitoring coverage, security score, a Bash call flagged dangerous, live agent sessions, an Insights shortcut, rate-limit gauges](/assets/img/perch-notch.png) What matters is *where it stands*: outside the agent's process. Agent content reaches it only as data to display: there's no model inside to prompt-inject, and a transcript is something it draws, not something it obeys. And what it shows isn't the agent's story about itself: session state, flagged commands, and token counts come from the harness's own records — which tools actually fired, what they actually ran. The model can narrate whatever it likes; the record is written by the harness, not by the narration. When the agent claims it's idle, the notch either agrees or it doesn't. @@ -83,7 +83,7 @@ Threat model, stated bluntly: perch trusts the local OS account boundary and the At the scale of one person and a handful of sessions, perch is enough. Picture four hundred engineers, each running coding agents all day. One agent going wrong is an incident. A fleet going wrong is a breach. -At fleet scale, the risks worth catching are only visible *across* machines: one agent tripping a curl-pipe-bash rule is noise; nine endpoints tripping it within the hour is a campaign. So the events have to flow somewhere central. That's [crowsnest](https://github.com/theMobiusStrip/crowsnest). Every endpoint ships its tool-decision events — what the agent asked to do, how risky it was, what got approved — to one place, where they land in ClickHouse. Deterministic SQL rules decide what looks suspicious, and a dashboard turns the hits into fleet views and incidents you can drill into. It's local-first: one machine today, multi-endpoint tomorrow, no rewrite in between. +At fleet scale, the risks worth catching are only visible *across* machines: one agent tripping a curl-pipe-bash rule is noise; nine endpoints tripping it within the hour is a campaign. So the events have to flow somewhere central. That's [crowsnest](https://github.com/theMobiusStrip/crowsnest). Every endpoint ships its tool-decision events — what the agent asked to do, how risky it was, what got approved — to one place, where they land in ClickHouse. Deterministic SQL rules decide what looks suspicious, and a dashboard turns the hits into fleet views and incidents you can drill into. It's local-first: one machine today, multi-endpoint tomorrow, no rewrite in between. And perch now meets it halfway: deduplicated detections land in a compact local SQLite record — metadata only, never commands, paths, or prompts, 30 days — behind a [versioned read-only view](https://github.com/theMobiusStrip/perch/blob/main/docs/detection-storage.md) built for a future crowsnest adapter to poll. And yes, crowsnest is a watcher everything phones home to — the difference is whose home: your ClickHouse, your rules, your infrastructure, not a vendor's black box. Same caveat as perch, one level up: a compromised endpoint can go quiet (which the fleet view surfaces) or lie convincingly (which no dashboard fixes). Its LLM triage is optional, advisory, and off by default — the verdict belongs to deterministic rules, because if another LLM gets the final say, you're back to agents supervising agents. diff --git a/assets/img/perch-notch.png b/assets/img/perch-notch.png index 28d4aa9..9d1569c 100644 Binary files a/assets/img/perch-notch.png and b/assets/img/perch-notch.png differ diff --git a/perch/img/icon.png b/perch/img/icon.png index eb7ffad..134f7b1 100644 Binary files a/perch/img/icon.png and b/perch/img/icon.png differ diff --git a/perch/img/insights.png b/perch/img/insights.png new file mode 100644 index 0000000..3afc666 Binary files /dev/null and b/perch/img/insights.png differ diff --git a/perch/img/integrity.png b/perch/img/integrity.png index c3a1e82..c4beb74 100644 Binary files a/perch/img/integrity.png and b/perch/img/integrity.png differ diff --git a/perch/img/notch.png b/perch/img/notch.png index e6815c0..9d1569c 100644 Binary files a/perch/img/notch.png and b/perch/img/notch.png differ diff --git a/perch/img/usage.png b/perch/img/usage.png index bf57f7d..d4135a6 100644 Binary files a/perch/img/usage.png and b/perch/img/usage.png differ diff --git a/perch/img/worktrees.png b/perch/img/worktrees.png index d27b5fe..c72de76 100644 Binary files a/perch/img/worktrees.png and b/perch/img/worktrees.png differ diff --git a/perch/index.html b/perch/index.html index f0fee13..de7b31b 100644 --- a/perch/index.html +++ b/perch/index.html @@ -4,7 +4,7 @@ Perch — the read-only watcher for your coding agents - + @@ -12,8 +12,8 @@ - - + + @@ -181,6 +181,14 @@ } .shot { margin-top: 56px; } .shot + .shot { margin-top: 72px; } + /* The two shots in a pair are rendered at identical aspect ratios, so + equal columns give equal heights and a straight vertical seam. */ + .shot-pair { + display: grid; grid-template-columns: 1fr 1fr; gap: 20px; + margin-top: 56px; align-items: start; + } + .shot-pair .shot { margin-top: 0; } + .shot-pair + .shot, .shot-pair + .shot-pair { margin-top: 72px; } .shot figcaption { text-align: center; font-size: 0.85rem; color: var(--text-dim); margin-top: 12px; @@ -262,6 +270,7 @@ @media (max-width: 720px) { .trust { grid-template-columns: repeat(2, 1fr); } .grid, .install-cols { grid-template-columns: 1fr; } + .shot-pair { grid-template-columns: 1fr; gap: 56px; } header { padding-top: 48px; } nav { flex-wrap: wrap; } nav .links { flex-wrap: wrap; gap: 14px; } @@ -295,13 +304,13 @@

Your coding agents will say they're fine.
Perch lets y

Apple silicon (M1+) · macOS 14+ · MIT license

- Perch notch panel: security score 75, a Bash call flagged dangerous with the exact command and why, live agent session list, and rate-limit gauges + Perch notch panel: monitoring verified for Claude Code and Codex event delivery, security score 75, a Bash call flagged dangerous with the exact command and why, live agent session list, an Insights shortcut for 24-hour, 7-day, and 30-day trends, and rate-limit gauges
Read-onlyno approve/deny code path exists
-
Open sourceMIT · ~13k lines of Swift, zero deps
-
Local-onlyzero network calls, zero upload
+
Open sourceMIT · ~18k lines of Swift, no third-party deps
+
Local-onlyzero telemetry — nothing observed leaves your Mac
Freeno tiers, no account
@@ -313,7 +322,7 @@

What your agents are doing — and leaving behind

@@ -324,6 +333,14 @@

Writing to the agent's brain

Footholds — what's left behind

A separate notch page scans the persistence surface straight from disk: agent config and hooks, MCP servers, plugins, CLAUDE.md and memory files, LaunchAgents, shell profiles. No hook required — it covers changes made before Perch launched — and a flag stays up until you acknowledge it.

+
+

Monitoring you can verify

+

A coverage strip checks the deployed bridge, the local event socket, Claude wiring, and Codex hook trust — then refuses to report verified until a real event from each configured agent actually arrives. Its state colors the collapsed notch and the menu-bar bird, and a guided setup installs or repairs the integrations.

+
+
+

Local Insights, zero setup

+

Offline caution/danger trends for this Mac: 24-hour, 7-day, and 30-day timelines, plus findings grouped by code, agent, tool, and session (menu bar → Insights…). Built on a metadata-only local record — never commands, paths, or prompts — that records what Perch observed, not whether a request ran.

+

Worktree housekeeping, read-only

Agent sessions mint git worktrees and leave them behind. Perch audits them across every project — tiered reclaimable / review / active / orphaned, with disk sizes — and its git calls never write; even status runs lock-free. Perch never deletes.

@@ -333,26 +350,34 @@

Rate limits and token usage

Claude 5h/7d and Codex 5h/weekly windows with reset countdowns and an 80% warning — the Claude gauges are fed by terminal sessions (the desktop app doesn't report them). Token totals for today / 7 days / 30 days, and a full per-day, per-model, per-project dashboard.

-

A security score you can glance

-

A rolling 0–100 posture score in the notch and menu bar: −25 per danger, −5 per caution over the last hour. A quiet hour heals it back to 100.

+

A security score you can glance — and audit

+

A rolling 0–100 posture score in the notch and menu bar: −25 per danger, −5 per caution over the last hour; a quiet hour heals it back to 100. Open the strip for the formula and retained recent detections — dismissing an alert card doesn't erase its history, and the score survives an app restart.

Every session, one glance

Live list of all Claude Code and Codex sessions — running / waiting / idle, last message, context gauge, red badge on any session that just ran something dangerous.

-
- Perch Footholds page: the agent persistence surface — config, hooks, MCP servers, memory, LaunchAgents, shell profiles — with recent-change flags -
Footholds — the persistence surface scanned straight from disk; a non-Perch hook stays flagged until you acknowledge it.
-
-
- Perch Worktrees window: count, total size, and reclaimable tiles; per-project rows with reclaimable, review, active, and orphaned tier badges; a Copy cleanup commands button — read-only, Perch never deletes -
Worktrees — stale agent worktrees across every project, tiered conservatively; the only button copies commands for you to run.
-
-
- Perch token usage dashboard with daily stacked chart and per-agent, per-model, per-project breakdowns -
Token usage — today / 7-day / 30-day totals with per-day, per-model, and per-project breakdowns.
-
+
+
+ Perch Footholds page: the agent persistence surface — config, hooks, MCP servers, memory, LaunchAgents, shell profiles — with recent-change flags +
Footholds — the persistence surface scanned straight from disk; a non-Perch hook stays flagged until you acknowledge it.
+
+
+ Perch Worktrees window: count, total size, and reclaimable tiles; per-project rows with reclaimable, review, active, and orphaned tier badges; a Copy cleanup commands button — read-only, Perch never deletes +
Worktrees — stale agent worktrees across every project, tiered conservatively; the only button copies commands for you to run.
+
+
+
+
+ Perch Insights window: caution and danger totals, a 24-hour stacked detection timeline, findings grouped by stable code, detections by agent and tool, and sessions with finding clusters +
Insights — 24-hour / 7-day / 30-day trends read locally from the metadata-only record; observed requests only, never commands, paths, or prompts.
+
+
+ Perch token usage dashboard with daily stacked chart and per-agent, per-model, per-project breakdowns +
Token usage — today / 7-day / 30-day totals with per-day, per-model, and per-project breakdowns.
+
+
@@ -402,9 +427,9 @@

Download the app

  1. Open the .dmg and drag Perch into Applications.
  2. First launch: Perch is open-source and signed locally rather than notarized, so macOS asks once. macOS 15+: Privacy & Security → Open Anyway. macOS 14: right-click → Open.
  3. -
  4. Menu bar → Install Claude Hooks… / Install Codex Hooks… (existing settings are parse-merged and backed up).
  5. -
  6. Restart running sessions, then verify with Doctor. Codex hook trust is recorded automatically during install; only if that fails (an old Codex CLI) run /hooks once in the terminal codex TUI.
  7. -
  8. Allow notifications when macOS asks — danger alerts arrive as banners. Tip: in System Settings → Notifications → Perch, keep banners on but turn the sound off; you want to see every flag, not get pinged by it.
  9. +
  10. Complete the guided setup that opens on a fresh install — or menu bar → Monitoring Setup… — to install Claude Code and/or Codex monitoring (existing settings are parse-merged and backed up).
  11. +
  12. Start or restart each configured agent, then watch Live verification confirm a real hook event arrived. Run Doctor checks bridge, socket, hook wiring, and trust. Codex hook trust is recorded automatically during install; only if that fails (an old Codex CLI) run /hooks once in the terminal codex TUI.
  13. +
  14. Allow notifications and choose which event categories interrupt you, right in the setup window. Tip: turn off Play notification sounds — you want to see every flag, not get pinged by it.
@@ -423,7 +448,8 @@

Build from source

FAQ

Does it slow my agents down? No. Hooks call a bridge that forwards the event over a local socket in ~10 ms and exits — fire-and-forget. Approvals never route through Perch. If Perch dies, your agents don't even notice.
-
What exactly does it read? The session records the agents already write — hook events, transcripts, usage files — plus, for the Footholds scan, the agent-config and persistence surfaces themselves: ~/.claude settings and plugins, ~/.claude.json, CLAUDE.md and memory files, LaunchAgents, shell profiles (some checked by timestamp only). All read-only; nothing leaves your machine — Perch makes zero network calls.
+
What exactly does it read? The session records the agents already write — hook events, transcripts, usage files — plus, for the Footholds scan, the agent-config and persistence surfaces themselves: ~/.claude settings and plugins, ~/.claude.json, CLAUDE.md and memory files, LaunchAgents, shell profiles (some checked by timestamp only). All read-only; nothing Perch observes ever leaves your machine.
+
Does it keep a history of what my agents ran? No. Deduplicated caution/danger detections write metadata-only rows to a local SQLite file with a 30-day retention: event, endpoint, and tool identifiers, risk level, and stable finding codes. Never commands, tool payloads, paths, prompts, or outcomes — and a row never claims a request was approved or executed. Insights reads that store in-process; there is no uploader. The versioned read contract is in Detection storage.
Can it block or approve anything? No, by design. There is no approve/deny code path in the source. A monitoring tool should have zero authority over the thing it monitors.