Start a conversation

Sentinel The window your coding agents report to.

I run several Claude Code sessions at once, and the important parts kept scrolling away: a question waiting on me, a plan, a lesson it had learned, a dev server left running. Sentinel keeps all of it in one window on the Mac, and gives the agents a direct line to keep it current. It is free to everyone in my network, and you get the version I use every day.

Platform
macOS
Runs
On your Mac, no server
Talks to agents over
MCP and hooks
Price
Free to my network
Receipts
15 commits · 68 test files · since 9 October
Overviewharbour-api4ledger-web2field-notesops-scriptsRefreshTaskLearningRecall
Home1Inbox4Plan1Brain41Stack1Running6Learnings3ActivitySettings

harbour-api

~/code/harbour-api

Waiting on you

Inbox

4asks1 blocking
  • Run the migration that drops charges.legacy_ref?harbour-api · claude · 3f9a1c2e4m
  • Create the read replica and paste its URLharbour-api · claude · 3f9a1c2e18m
  • Keep v1 webhooks for one more release?harbour-api · claude · a71c0d941h
Open inbox
Gates

Last results agents reported

1failing
  • typecheckharbour-api · 2 errors in src/charges/replay.ts6m
Ports

Claimed so other repos, and Claude, stay off them

:8420 api:8421 docs:5433 postgres:9230 inspector
Plan

harbour-api

73%
11 of 15 done

Payments v2 · Webhook retries · Rate limits

  • Idempotency keys on POST /chargespayments · 70%
  • Retry schedule with full jitterwebhooks · 35%
2 doing1 blockedOpen plan
Running

What the process monitor sees

6processes1 to end
  • vitest --watchWatcher · 3 h 12 min · its session ended0%
  • pnpm devDev server · 2 h 4 min14%
  • tsc --watchWatcher · 48 min3%
Open running
Machine

Last 15 minutes · read every 5 s

Tight
  • Memory 78% for 3 min, budget 85%
46%
CPU · budget 80%
14:0514:20
78%
Memory · budget 85%
14:0514:20

This repo's sessions: 31% CPU · 3.4 GB

Open machine
Agents at work

The brain

4at work now1 in conflict
6 agents joined in the last 24 h
  • webhooksWorker · Retry schedule with full jitter40s
  • leadLead · Wiring the shared files1m
  • paymentsWorker · Idempotency keys on POST /charges2m
Open brain
Store connectedAuto-kill: SuggestCaffeinate4 open asks · 1 blocking9 processesharbour-api
One repo at a glance. What it is waiting on you for, how far the plan has got, which agents are at work and whether any collide, the last gate results, and the machine against its budget.
Free to my network

Get Sentinel, free

It’s maintained and updated, so you’ve always got the same tools that I have. Join my network and Sentinel is yours, free, from its first release, with every update after it.

Joining means I’ll occasionally be in touch: new tools, new guides, the odd invitation. Leave whenever you like.

Agents are fast. Keeping up with them is the job now.

With one session you can read the terminal. With four, the question that blocks one of them is buried under the output of the other three, two of them are about to edit the same file, the laptop fan is roaring because nobody stopped a watcher, and the correction you gave yesterday has been forgotten. None of that is a coding problem. It is a coordination problem, and the terminal is the wrong place to solve it.

One local store, and the agents write to it directly.

Sentinel is not a dashboard scraped from log files. One SQLite store on your Mac sits behind everything, and the app, a command line, an MCP server and Claude Code hooks all write through the same layer, which validates and audits every change. The hooks hand each session what it needs at the start and only what changed after that, so an agent does not have to remember to ask. Nothing listens on a port, and nothing leaves the machine.

Overviewharbour-api4ledger-web2field-notesops-scriptsRefreshTaskLearningRecall
Dashboard1Inbox6MachinePairingLearnings3Activity

Inbox

11 asks, 1 blocking a session

OpenAnsweredDoneDismissedAll
  • Run the migration that drops charges.legacy_ref?harbour-api · claude · 3f9a1c2eBlocking4m
  • Create the read replica and paste its URLharbour-api · claude · 3f9a1c2e2/518m
  • Keep v1 webhooks for one more release?harbour-api · claude · a71c0d941h
  • Drop the sandbox signing certificateharbour-api · claude · a71c0d942h
  • Default prices to en-GB or en-US?ledger-web · claude · 0be4f7a23h
  • Claude is waiting for permission to run pnpm buildledger-web · hook · 0be4f7a25h
  • Which region should the replica live in?harbour-api · claude · 3f9a1c2edone25m
  • Squash the webhook commits before the PR?harbour-api · claude · a71c0d94done3h
  • Add the staging signing secret to the secret storeharbour-api · claude · a71c0d94done4/41d
  • Drop last month’s export so the importer can be testedledger-web · claude · 0be4f7a2done2d
  • Rename the field-notes repo to notes?field-notes · claude · 91d3e5c0dismissed4d
Action · harbour-api · 18m ago
Create the read replica and paste its URL
open

The reporting queries are slowing the primary at month end. A read replica takes them off it. I can do everything else, but creating it needs your account.

Steps

  • Open the database console for harbour-prod
  • Create a read replica in the same region, at the smallest size
  • Wait until it shows Available, about ten minutes
  • Copy its connection string
  • Paste it below. Claude writes it to .env.local, never to git

Answer

Reply to Claude
ApproveSend answerAttach
DoneDismiss
Asked by
claude · 3f9a1c2e
Asked
15 Oct, 14:02
Session
3f9a1c2e-7b41-4e0c-9d2a-51c86e0f3b17
Store connectedAuto-kill: SuggestCaffeinate6 open asks · 1 blocking9 processesAll repos
The inbox. Questions, approvals, file requests and step-by-step actions, blocking ones first. Tick the steps, answer, and the session reads it on its next turn.
Overviewharbour-api4ledger-web2field-notesops-scriptsRefreshTaskLearningRecall
Home1Inbox4Plan1Brain41Stack1Running6Learnings3ActivitySettings

Plan

harbour-api · 3 parts · 15 tasks · 73% done

12 h2 dWeekFitPart
TaskStatusOwner
Payments v264 of 6 doneDoing
Charges that are safe to retry, end to endEdit partTask
idempotency_key column on chargesDonepayments
Store the key before the provider callDonepayments
Replay a stored response on a repeat keyDonepayments
Expire keys after 24 hDoneclaude
Idempotency keys on POST /chargesDoing 70%payments
Contract tests for repeat requestsTo dopayments
Webhook retries31 of 3 doneDoing
No event lost when a customer's endpoint is downEdit partTask
Verify signatures on the raw bodyDonewebhooks
Retry schedule with full jitterDoing 35%webhooks
Dead-letter after eight attemptsBlockedwebhooks
Rate limits66 of 6 doneDone
done in progress projected from estimates blockedDotted outline: no estimate, drawn as an hour.
Store connectedAuto-kill: SuggestCaffeinate4 open asks · 1 blocking9 processesharbour-api
The plan. Parts and tasks as a dependency graph crossed with a timeline: solid bars for what happened, outlines for what is projected from estimates.
Overviewharbour-api4ledger-web2field-notesops-scriptsRefreshTaskLearningRecall
Home1Inbox4Plan1Brain41Stack1Running6Learnings3ActivitySettings

Brain

harbour-api · 4 agents at work · what they have shared

Post
Agents

4 active agents · 1 left

  • leadLeadseen 1m

    Planning Webhook retries; wires the shared files after each worker

    joined 2 h ago

    src/server.tspackage.json
  • paymentsWorkerseen 2m

    Idempotency keys on POST /charges

    joined 1 h ago · worktree payments-v2

    src/charges/**tests/charges/**
  • webhooksWorkerconflictseen 40s

    Retry schedule with full jitter

    joined 48m ago · worktree webhook-retries

    src/webhooks/**src/charges/events.ts
  • docsWorkerseen 6m

    Changelog and the v2 migration guide

    joined 20m ago

    docs/**
  • Left1
1 agent in conflict
Context

7 entries, pinned first, then newest

AllFindingsDecisionsInterfacesWarningsHandoffsSearch the context
  • chargeWithKey(key, input): Promise<Charge> is idempotent for 24 hInterface · payments · 12msrc/charges/**
  • The test database is shared: never truncate it outside the fixtureWarning · lead · 1htests/**
  • Does chargeWithKey store the key before or after the provider call?Question · webhooks → payments · 9m
  • Before, in the same transaction. A crash replays safely.Answer · payments → webhooks · 7m
  • Retries back off 2ⁿ seconds with full jitter, capped at ten minutesDecision · lead · 25msrc/webhooks/**
  • The gateway already sets the rate-limit headers; do not add a second setFinding · limits · 41m
  • Rate-limit middleware done; every gate green at 4c1e9abHandoff · limits · 35m
Store connectedAuto-kill: SuggestCaffeinate4 open asks · 1 blocking9 processesharbour-api
The brain. Parallel agents in lanes, each with the paths it has claimed. An overlap shows in red before two agents edit the same file.
Overviewharbour-api4ledger-web2field-notesops-scriptsRefreshTaskLearningRecall
Home1Inbox4Plan1Brain41Stack1Running6Learnings3ActivitySettings

Learnings

What Claude should not get wrong twice. Claude proposes; you accept.

Learning
webhook retriesAllProposed3Accepted14Retired2Every kind

Recall for “webhook retries”: 8 found, ranked as Claude would see them, accepted above proposed, this project above the rest.

  • Retries back off with full jitter, never a fixed intervalPattern · harbour-api · retriestext+vector · 0.0322d
  • Staging sends webhooks from two addresses; allow bothFact · harbour-api · webhooks, stagingtext · 0.0166d
  • Webhook handlers answer 200 at once and queue the workPattern · harbour-api · webhookstext · 0.0161w
  • Queue consumers must be idempotent: a message can arrive twicePattern · every projectvector · 0.0163w
  • Log the request id, never the request bodyPreference · every project · logging, privacyvector · 0.0152w
  • Use the repo’s pnpm, not npx: npx fetches another CLI versionPreference · every project · toolingvector · 0.0141w
  • Verify webhook signatures on the raw body, then parse itTrap · harbour-api · webhooks, securitytext+vector · 0.033Proposed9mAcceptRetire
  • The test database is shared across worktrees: never truncate itTrap · harbour-api · testsvector · 0.015Proposed1hAcceptRetire
Trap · harbour-api
Verify webhook signatures on the raw body, then parse it
Proposed

Proposed by Claude

Nothing is told to Claude until you accept it.

AcceptRetire

Body

Every staging event failed verification. The framework had parsed and re-serialised the body before the handler saw it, so the bytes no longer matched the signature. Read the raw body with req.arrayBuffer(), verify, and only then parse.

Tags

webhookssecurity
Recorded by
claude · a71c0d94
Recorded
15 Oct, 14:11
Recalled
0 times
Store connectedAuto-kill: SuggestCaffeinate4 open asks · 1 blocking9 processesharbour-api
Learnings. Corrections and traps Claude proposes, waiting for a yes. Recall ranks them by words and by meaning, the way the next session will see them.

Screens drawn with dummy data. No real customer, client or account appears.

What it does

An inbox for what agents need from you

Questions, approvals, file requests and step-by-step tasks with boxes to tick. Blocking ones come first, with a notification and a Dock badge. Your answer reaches the session on its next turn.

One plan per repo

Parts and tasks with dependencies, drawn as a graph beside a timeline. Agents update their own tasks as they go, so the plan on screen is the plan they are working to.

Learnings you approve

When you correct an agent, it proposes a learning. Nothing is told to future sessions until you accept it. Recall searches by words and by meaning, entirely on your Mac.

A brain for parallel agents

Each agent joins, claims the paths it will edit and posts findings, decisions and interfaces for the others. Overlapping claims are refused or flagged before two agents touch one file.

The machine on a budget

CPU, memory and swap read every five seconds against limits you set, with every process a session started and a verdict on each. Over budget, agents are told, and can be stopped from starting builds.

Ports and the stack

One registry of ports so two repos never fight over one. Each repo’s components, commands and gates are declared, with the last result every agent reported for each gate.

TypeScriptElectronReactSQLiteMCPClaude Code hooksLocal embeddings