Today · Session briefing
Read where you stand before a session starts
RepoOps puts nine signals it already computes on one screen and shows you, ahead of time, which errors and decisions the next Claude Code session will load into its context. You set how many. The ranking is two numbers you can read, and the tab prints the score beside each row.
For: the engineer who starts a session in a tracked repository and wants to know what it will know, and the owner who reads the team's report on the hosted dashboard
What it does, and why it helps
The Session briefing tab is a fan-in. It calls five reads the app already serves and lays their top rows out as cards: Next best action, Spend & budget and Ship readiness from the Today model; Approval queue from the held-action queue; Active sessions from the live snapshot; Cross-repo lessons and Running cost from the continuity read; and Relevant errors and Relevant decisions from the briefing preview. Every card header is a link to the tab that owns the data, and every row that has a home opens it. The tab computes nothing new and calls no model.
The two relevance cards are the part worth understanding. The preview parses the dated headings of the repository's errors.md and decisions.md into rows, collects the backticked file paths under each heading, and scores each row as file overlap times 0.7 plus recency times 0.3, with a 60-day half-life on recency. The top rows, up to the Session-load depth, are the ones the SessionStart hook will write into the next session's reminder under the heading Most relevant right now. The tab prints the score beside each title so you can check the order rather than take it on trust. When the tab has no open-file set to compare against, the overlap term is 0 and the order is recency alone; the hook supplies the set from git, so the injected list can differ from the preview.
The pain. The errors a repository has already made and the decisions it has already taken sit in two markdown files. A new session does not open them. The person starting it opens six tabs to find out where things stand, or does not, and the session repeats a mistake the file already records.
The point of view. What a session will load should be visible before it loads, bounded by a number the person chose, and ranked by a formula short enough to print. A recall system you cannot inspect is one you cannot correct.
What gets easier. Orienting. One screen shows the next action, the spend, the readiness, what waits for approval, who is working where, the lessons that arrived from sibling repositories, the running cost, and the exact errors and decisions the next session will carry, each with its score.
When it helps. At the start of a working day or before opening a session in a repository with a populated brain. The two relevance cards need dated headings in errors.md or decisions.md; the other seven need the sources they read (telemetry, a queue, live sessions, a cost ledger) to hold data.
Its limits. The tab ranks by recency alone because it passes no open files; only the hook has the overlap signal. The preview shows errors and decisions, not lessons: the tab sends no lesson corpus and no audit events, so the lesson list and the recent-promotion list the module can produce are empty on this surface. Nothing here stops a repeat on its own; the briefing shows a row, and whether the session acts on it is recorded separately as an engagement.
Understand it in 30 seconds
Read the narration
- 0:00 A session starts cold.
- 0:02 Last week's errors sit in a file nobody reopens.
- 0:06 RepoOps ranks errors and decisions against the files in flight.
- 0:10 You see the list first.
- 0:13 Each row shows its score.
- 0:15 Set the depth, zero to fifty; the same number bounds what your next session loads.
- 0:23 Check the ranking before you trust it.
- 0:25 The guide names the two terms.
Synthetic example. Read the guide
Where to find it
Where to find it
- Desktop:
localhost:4000, then Today in the sidebar, then Session briefing under All tools. - Hosted:
repoops.ai/team/briefing, from Today in the sidebar, then Session briefing under All tools. - Keyboard: ⌘ K, then type “Session briefing”.
When to use it
Checking what the next session will load
Situation. You are about to start a session on a branch that touches the telemetry parser. The repository's errors.md holds a dated entry about that parser from five weeks ago.
What you do. Open Session briefing for the repository. Read Relevant errors and Relevant decisions. If the parser entry is missing, lower nothing yet: check whether its heading is dated and whether it backticks the file path, because both are what the corpus reader keys on.
What you see. Each row shows its title and a score such as score 0.54. The count of rows never exceeds the depth in the number field. A repository whose brain has no dated headings shows No relevant errors.
What it establishes. You know which rows the reminder will carry and why they outrank the others. You do not know whether the session will use them; that is what the briefing-shown and engagement rows record afterwards.
Bounding the reminder
Situation. The SessionStart reminder has grown long and the relevance section is repeating rows the team already knows by heart.
What you do. Set Session-load depth to a smaller number and press Apply. The status line reads saved (depth N). Set it to 0 to drop the section from the reminder altogether.
What you see. The two relevance cards re-render at the new depth. The value survives a reload because it is stored per account in account-settings.json, not in the page. A value above 50 is stored as 50; a non-number is refused with a 400 and the status line says why.
What it establishes. The next session's reminder carries at most N errors and N decisions, and at most N personal-brain items, capped further by the session interruption budget (default 5).
Reading the team report
Situation. You own a team whose desktops stream events to the hosted dashboard, and you want the month in one paragraph.
What you do. Open /team/briefing. It is narrowed to the repositories your membership can see.
What you see. One card of sentences over the last 30 days: what the team spent and measured on autonomous work, how many outcomes measured a positive benefit, how many pull requests merged and the median time to merge. Each sentence links to the surface behind it. A team that has streamed nothing sees Nothing to brief yet.
What it establishes. A figure marked with a floor sign is a lower bound because the read hit its row budget (5,000 rows for pull requests); the page says so on the number itself rather than rounding it up.
Before you start
- Supported versions
- RepoOps desktop v0.3.1, the release this guide was read against. The SessionStart hook runs where Claude Code runs, wired in .claude/settings.json by repoops adopt or by hand.
- Where it runs
- Local: Today in the sidebar, then Session briefing under All tools. Hosted: Today in the sidebar, then Briefing under All tools (/team/briefing), the team situation report, which reads a different source (the team event store) and shows different lines; it does not mirror the nine cards.
- Permissions
- Reading the tab needs no credential. Changing the depth takes a request from the app's own origin (the local-origin gate), so a cross-site page cannot change it; it is the lighter of the two write gates because the depth is a number and nothing executes. The hosted page is session-authenticated and team-scoped by membership.
- Connections
- None for the tab itself. Seven of the nine cards read sources that need their own setup: Running cost shows a billed figure only when the Anthropic Admin API is configured; Cross-repo lessons needs cloud sync or an aggregator root; Spend & budget needs app-LLM call records.
- Plan
- No plan gate on the tab or the hook; the pricing capability map has no briefing row. The hosted report follows the hosted dashboard tiers.
Configure it
- Give the corpus something to read.
The relevance cards come from dated headings in the repository's .claude/brain/errors.md and decisions.md, in the form of a level-two heading that starts with a date, then a colon or a dash, then the title. A row's files are the backticked paths under that heading. A heading without a date is invisible to the ranker, and a row that names no file can never score on overlap.
- Set the depth.
On the tab, Session-load depth (top-N errors/decisions) takes a whole number from 0 to 50 and Apply stores it per account. The default is 5. The same number bounds what the SessionStart hook injects, and 0 removes the section from the reminder.
- Decide whether personal-brain pages join the list.
Pages under .claude/brain/wiki/personal and the priorities file .claude/brain/priorities/me.md are ranked by the same formula and capped by the session interruption budget. The account setting briefingPersonal (default true) removes them from the preview when false; it has no control on the tab. REPOOPS_BRIEFING_PERSONAL=0 removes them from the hook.
- Leave the engagement hook on unless you have a reason.
A PostToolUse hook records one engaged row when a session edits a file that a shown item pointed at. That is the only signal the ranker's offline learner has. REPOOPS_BRIEFING_ENGAGEMENT_OFF=1 turns it off.
- Widen the session window if the last canonical session is older than two weeks.
The hook loads the most recent dated session file within REPOOPS_BRIEFING_WINDOW_DAYS (default 14). Older sessions stay searchable through Ask; they are not auto-loaded.
| Setting | Where | A sensible choice | Why it matters |
|---|---|---|---|
briefingDepth | Session briefing tab, Session-load depth, then Apply | 5 (the default); 0 to switch the section off | Bounds the errors and decisions the tab shows and the hook injects. Stored per account; clamped to 0 to 50 on write and on read. |
briefingPersonal | account-settings.json; no desktop control | true (the default) | false removes personal-wiki pages and the priorities file from the preview. |
REPOOPS_BRIEFING_PERSONAL | the data directory's .env, read by the hook | unset (on) | 0 removes personal-brain items from the injected reminder. |
REPOOPS_BRIEFING_WINDOW_DAYS | the data directory's .env | 14 (the default) | How far back the hook looks for the last dated session file. A non-positive or non-numeric value falls back to 14. |
REPOOPS_AGGREGATOR_ROOT | the data directory's .env | the aggregator checkout that holds the account rollup | Without it the hook's sibling-repository lessons section is empty. |
REPOOPS_BRIEFING_ENGAGEMENT_OFF | the data directory's .env | unset (on) | 1 stops the PostToolUse hook from recording engaged rows; showings are still recorded. |
REPOOPS_EVENTS_RETENTION_DAYS | the data directory's .env | 30 (the default) | Raw days of the events store, where briefing-shown rows live, before the daemon gzips a month into events/archive. Archive, not delete. |
What you should see
A populated brain, default depth
Configuration. errors.md and decisions.md with dated headings that backtick file paths; depth 5; the hook wired.
Expect. Relevant errors and Relevant decisions each show up to five titles with a score. The next session's reminder carries the same section heading, Most relevant right now, with up to five of each, ranked with the open-file set from git status and the branch's commits.
Verify. Compare the tab's rows with the reminder. The order may differ, because the tab scored with overlap 0 and the hook did not. A briefing-shown row with the shown items and the weights lands in .claude/brain/events/<today>.jsonl.
Depth 0
Configuration. Session-load depth set to 0 and applied.
Expect. The status line reads saved (depth 0). Both relevance cards read No relevant errors and No relevant decisions. The reminder has no relevance section; the rest of the briefing (last session, activity, pending questions) is unchanged.
Verify. GET /api/briefing/config returns briefingDepth 0. A reload keeps 0 in the number field.
A brain with no dated headings
Configuration. A repository whose errors.md and decisions.md use undated or free-form headings.
Expect. Both relevance cards read their empty state at any depth. This is the honest result, not a fault: the corpus reader keys on the date, and a heading such as a bare title never becomes a row.
Verify. Add a dated heading with a backticked path, press Refresh, and the row appears with a score near 0.30, the recency term alone for a same-day row.
Data and cost
- What is captured
- The tab stores one number, briefingDepth, in the account settings file. The hook appends a briefing-shown row per non-empty briefing (the item ids, titles, files, ranks and the weights used) and the engagement hook appends an engaged row when a session edits a shown item's file. Both land in the repository brain's events/<YYYY-MM-DD>.jsonl. The tab also keeps the last-known-good response for two of its reads in browser storage so a reload paints before it fetches.
- Who can see it
- Local. The tab reads the local server; the depth is per account on this machine. The hosted report is a separate read over events the team's desktops chose to stream, narrowed to the repositories the viewer's membership covers.
- How long it is kept
- Briefing-shown and engaged rows share the events store: raw for 30 days (REPOOPS_EVENTS_RETENTION_DAYS), then rotated into a gzipped monthly archive that reads stay able to reach. The depth persists until changed. The hosted report reads a rolling 30-day window.
- What leaves the machine
- Nothing leaves the machine from the briefing tab or the hook. The reads it fans in have their own egress (the Admin API billed figure is fetched from Anthropic when configured; cloud sync carries lessons), and each is documented on its own tab.
- What it costs
- No model call anywhere in the briefing path. The ranker is arithmetic over two files; the hook is a Node script that runs once per session start and must exit 0 whatever happens.
When the result differs
| Symptom | Likely cause | Next action |
|---|---|---|
| Relevant errors reads No relevant errors on a repository with a long errors.md. | The headings are not in the dated form the corpus reader parses, or the depth is 0. | Check the number field. Then check that entries begin with a level-two heading of the form date, separator, title. |
| A row the session should have seen is not in the reminder, though the tab shows it. | The hook ranks with an open-file set and, when a promotion has landed, with promoted weights; the tab ranks with neither. | Compare the score on the tab with the weights recorded on the briefing-shown row for that session. |
| The status line reads could not save. | The request did not come from the app's own origin, the repository could not be resolved, or the settings store failed to write; the message names which. | Open the tab through the dashboard with a repository selected and apply again. |
| A value of 80 saved as 50. | clampBriefingDepth pins the write to 0 to 50, and the settings allowlist pins it again on read. | None; 50 is the ceiling. |
| The cards paint old data on reload, then change. | Two reads paint their last-known-good from browser storage before fetching. | Wait for the status line to clear, or press Refresh. |
| Running cost shows only the tracked figure. | No Anthropic Admin API key is configured, so there is no billed figure to show. | Configure the Admin API on the Continuity or Settings tab if you want the billed line. |
| The hosted page says Nothing to brief yet. | No desktop in the team has streamed action or pull request events under opt-in telemetry, or the viewer's repository narrowing excludes those that did. | Turn on telemetry streaming on a desktop, then reload. |
- Disable
- Set the depth to 0 for the relevance section; unset or set the engagement flag for the engaged rows; remove the hook line from .claude/settings.json for the whole reminder.
- Roll back
- Not provided, and not needed: the only stored setting is one number. Set it back. The ranking weights change only through the offline replay gate's promotion log in the repository brain, and the hook falls back to the incumbent weights when that log is absent.
- Revoke access
- Not provided. The tab holds no credential and grants none; the depth write is gated by request origin, not by a token.
- Delete
- Not provided. No route deletes briefing-shown or engaged rows; they sit in the repository brain's events/<YYYY-MM-DD>.jsonl and, after rotation, in events/archive/<YYYY-MM>.jsonl.gz. The depth can be reset but the settings file keeps the key.
Related tasks
Maintenance evidence
- Feature id
briefing(spine leafbriefing)- Owner
- Phase K9 cross-awareness program (K9.A.3, K9.A.5 and its followup; the brain self-awareness plan wired the open-file and lesson inputs). Hosted report: Hosted UI parity, W5. Guide: LDG-0717.
- Supported product version
- RepoOps v0.3.1
- Last verified
- 2026-09-15, read against origin/main at 52366bb6d; labels read from the served tab source (public/session-briefing.html) and the hosted page source; no live instance was started for this guide.
- Example fixtures
- No fixture file; the corpora are inline in lib/brain/briefing-preview.test.mjs (the heading forms, the token rules, the clamp) and lib/routes/briefing-config.test.mjs (the depth round trip, the clamp on write, the personal opt-out default). lib/brain/session-briefing.test.mjs covers the score; lib/brain/briefing-relevance.test.mjs covers the injected section; lib/brain/briefing-personal.test.mjs covers the personal corpus.
- Source references
public/session-briefing.html,lib/routes/briefing.mjs,lib/brain/briefing-preview.mjs,lib/brain/session-briefing.mjs,lib/brain/personal-briefing.mjs,lib/brain/briefing-relevance.mjs,lib/brain/open-files.mjs,lib/account-settings.mjs,lib/brain-events.mjs,lib/brain-cron.mjs,lib/session-briefing.mjs,scripts/cc-session-briefing.mjs,scripts/cc-briefing-engagement.mjs,public/lib/repoops-tab.js,website/app/team/(home)/briefing/page.tsx- Documentation review
- Independent review requested on the slice pull request; not yet recorded.
- Video review
- Story script written 2026-09-15; render and review pending in the same slice.
Last updated