AugmentClaude

Activity Dashboard

View recent team sessions, handoffs, and open work at a glance.

Installation

  1. Make sure Claude is on your device and in your terminal.

    Skills load from ~/.claude/skills/ when Claude Code starts up β€” so you need it on your machine first. If you don't have it yet, install it once with the command below, then run claude in any terminal to verify.

    One-time setup
    npm i -g @anthropic-ai/claude-code

    Already have it? Skip ahead.

  2. Paste into Claude Code or into your terminal.

    This copies the whole skill folder into ~/.claude/skills/activity-egregore-labs/ β€” the SKILL.md plus any scripts, reference docs, or templates the skill ships with. Safe default: works for every skill.

    Faster alternative (instruction-only skills)

    Skips the clone and grabs only the SKILL.md file. Don't use this if the skill ships Python scripts, reference markdowns, or asset templates β€” they won't be downloaded and the skill will fail when it tries to load them.

    Quick install (SKILL.md only)
    Sign up to copy
  3. Restart Claude Code.

    Quit and reopen Claude Code (or any other agent that loads from ~/.claude/skills/). New skills are picked up on startup.

  4. Just ask Claude.

    Skills auto-activate when your request matches the skill's description β€” no slash command needed. Trigger phrases live in the skill's own frontmatter; you can read them in the β€œWhat this skill does” section above.

Prefer to read the source first? Open on GitHub.

When Claude uses it

Claude activates this skill based on the context of your request.

What this skill does

See what's happening across the team β€” recent sessions, handoffs, and open work.

Display it immediately β€” no preamble, no narration, no reasoning text. The rendered box must be the FINAL text of the turn β€” never follow it with AskUserQuestion in the same turn. The harness hides text that precedes a tool call, so a box rendered before AskUserQuestion is never seen by the user.

When to invoke

User says: "catch me up", "what's going on", "show dashboard", "where did I leave off", "what happened", "any updates", "what did I miss" Not this: if user wants to do something specific, route to that command instead

Topic: $ARGUMENTS

Step 1: Fetch data

Quiet fetch β€” never print the raw JSON. The payload runs to several hundred lines; since this command renders inline (terminal-render, undelegatable), a bare bash bin/activity-data.sh dumps that JSON into the user's terminal before the board β€” burying the thing this command exists to show. Write it to a temp file and read only compact slices, in ONE command:

DATA="${TMPDIR:-/tmp}/egregore-activity-$$.json"
bash bin/activity-data.sh > "$DATA" 2>/dev/null
jq -c '{me, org, date, graph_status, graph_reason, todos_merged, knowledge_gap, orphans, trends}' "$DATA"
jq -c '.handoffs_to_me[] | {topic, date, author, status, sessionId, filePath, response}' "$DATA"
jq -c '(.pending_questions[] | {setId, topic, from, created}), (.answered_questions[] | {topic, answeredBy})' "$DATA"
jq -c '(.my_sessions[:6][] | {date, topic, id}), (.team_sessions[:6][] | {date, topic, by}), (.checkins[:5][] | {date, by, summary})' "$DATA"
jq -c '(.quests[:5][] | {quest, artifacts, daysSince}), (.prs[:6][] | {number, title, author}), {pr_count: (.prs | length)}' "$DATA"
jq -c '(.focus_history[:3][] | {selected, dismissed}), {disk: .disk}' "$DATA"
rm -f "$DATA"

One compact line per record β€” everything the render needs, nothing else. If a later step needs a field not sliced above (e.g. /activity quests wants all quests, or a handoff's all_handoffs row), re-fetch and run another targeted jq β€” never cat the file, never run the data script bare.

Returns JSON with these fields. Arrays are arrays of objects (NOT {fields, values} format).

Arrays of objects:

  • my_sessions β€” [{date, topic, id, filePath, handedTo}, ...]
  • team_sessions β€” [{date, topic, by}, ...]
  • quests β€” [{quest, title, artifacts, daysSince, score}, ...]
  • pending_questions β€” [{setId, topic, created, from}, ...]
  • answered_questions β€” [{setId, topic, answeredBy}, ...]
  • handoffs_to_me β€” [{topic, date, author, filePath, sessionId, status, intent, ageDays, lifecycleReason, nudgedAt, response}, ...]. Open handoffs are returned regardless of age, stale-first; terminal items are limited to the last seven days.
  • all_handoffs β€” [{topic, date, from, to, filePath}, ...]
  • checkins β€” [{id, summary, date, by, total}, ...]
  • focus_history β€” [{shown, selected, dismissed, date, topic}, ...]

Flat objects:

  • todos_merged β€” {activeTodoCount, blockedCount, deferredCount, staleBlockedCount, lastCheckinDate}
  • knowledge_gap β€” {gapCount}
  • orphans β€” {orphanCount}
  • trends.resolution β€” {avgDays, resolved}
  • trends.throughput β€” {created, completed}
  • trends.capture β€” {total, captured}

Other:

  • trends.cadence β€” [{weeksAgo, sessions}, ...]
  • me β€” string (person name)
  • org, date β€” strings (added client-side)
  • prs β€” [{number, title, author}, ...] (from git, client-side)
  • disk β€” {handoffs, decisions} (from filesystem, client-side)

The response includes graph_status ("connected" or "offline") and graph_reason (one of: missing_config, unreachable, auth_error, server_error, invalid_response).

Mode detection

Read mode from egregore.json:

MODE=$(jq -r '.mode // "connected"' egregore.json 2>/dev/null)

Local mode (mode === "local")

Do NOT show graph status, graph_reason, or any "/connect", "/setup", "/env" messaging. Read everything from filesystem:

  • Recent sessions from memory/handoffs/index.md (last 5-10 entries)
  • Active quests from memory/quests/index.md
  • Recent decisions from memory/knowledge/decisions/ (last 3 by date)
  • PRs from prs field (git-based, always available)
  • Footer: "Local mode β€” showing activity from memory"

Connected mode β€” graph offline

Only applies when mode === "connected" (or mode not set):

  • graph_status: "connected" β†’ normal dashboard
  • graph_status: "offline" β†’ fall back to reading memory/ files. Add (offline) after ✦ in header. Show the reason in footer:
    • unreachable β†’ Graph unreachable β€” check your network connection
    • auth_error β†’ Graph auth failed β€” run /env to check API key
    • server_error β†’ Graph server error β€” try again shortly
    • missing_config β†’ Graph not configured β€” run /setup
    • invalid_response β†’ Graph returned unexpected data β€” try again

Step 2: Render dashboard

Output the TUI box directly. 72 chars wide. Use these frame lines (copy exactly):

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Content rows: β”‚ {text padded with trailing spaces} β”‚

DO NOT count characters or show reasoning. Approximate padding is fine β€” the frame is decorative, not pixel-perfect. Go straight from data to rendered output.

Topic display rules (MANDATORY)

When displaying a session topic anywhere in the activity view:

  • If topic is non-null: show it as-is
  • If topic is null/empty: show the branch slug humanized (drop the dev/author/ prefix, replace hyphens with spaces). E.g. dev/oz/session-naming-bug β†’ session naming bug
  • If branch is also null or is develop/main/master: show the session date as fallback (e.g. Feb 24 session)
  • NEVER show "untitled", "current session", "quick session", or any invented label

Sections (separated by β”œβ”€β”€β”€β”€β”€)

Header: {ORG} EGREGORE ✦ ACTIVITY DASHBOARD left, {me} · {date} right

Insight (1-3 lines): Synthesize what's happening. Warm, concise, connective.

  • Use trends data when available to enrich synthesis. Compare this week's cadence vs last week ("session cadence up 40%"), note capture ratio ("capture ratio at 75%"), mention throughput ("3 todos created, 5 completed this week"). Only mention trends that are notable β€” don't list all metrics.
  • If todos_merged.staleBlockedCount > 0: {N} todos blocked for 3+ days. /todo check to review.
  • If no check-in in 3+ days (check todos_merged.lastCheckinDate) AND todos_merged.activeTodoCount >= 3: {N} active todos, no check-in in {days}d. /todo check to review.

Handoffs & Asks (skip if all empty):

  • Handoffs (status=pending) β†’ [N] ● β‡Œ {from} β†’ you: {topic} ({when})
  • Handoffs (status=read) β†’ [N] ◐ β‡Œ {from} β†’ you: {topic} ({when})
  • Handoffs (status=claimed) β†’ [N] β—† β‡Œ {from} β†’ you: {topic} ({when})
  • Handoffs (status=done) β†’ β—‹ {from} β†’ you: {topic} (done). If response field is non-null, append on next line: "{response truncated to 50 chars}..."
  • Handoffs (status=expired) β†’ Γ— {from} β†’ you: {topic} (expired)
  • Append {ageDays}d Β· {intent} when present. After the list show: Actions: /activity done N Β· /activity expire N Β· /activity reopen N, followed by Type a number to act, or keep working.
  • Pending questions β†’ [N] {from} asks about "{topic}" ({when})
  • Answered questions β†’ βœ“ {name} answered "{topic}"
  • Other handoffs β†’ {from} β†’ {to}: {topic} ({when})
  • Numbered items (● and ◐) first, blank line, then β—‹ + others.

Sessions β€” ALWAYS render. NEVER skip:

  • β—¦ YOUR SESSIONS β€” iterate my_sessions array. Each object has .date and .topic. Show top 5: {date} {topic}. If array is empty: (none yet).
    • Interleave check-ins from checkins (where .by matches me) in chronological order: {date} Check-in: {summary}
  • β—¦ TEAM β€” iterate team_sessions array. Each object has .date, .topic, .by. Show top 5: {date} {by}: {topic}. If array is empty: (none yet).
    • Interleave check-ins from checkins (where .by differs from me) in chronological order: {date} {by}: Check-in: {summary}
  • my_sessions and team_sessions are independent arrays. One can be empty [] while the other has data.
  • Blank line between sub-sections.

Quests & PRs (skip if both empty):

  • βš‘ QUESTS (N active) β€” top 5 by score. {quest-id} left, {N} artifacts Β· {N}d ago right.
  • β†’ OPEN PRs β€” #{number} {title} ({author})
  • Blank line between sub-sections. Omit either if empty.

Footer (separated by β”œβ”€β”€β”€β”€β”€):

  • If orphans.orphanCount > 0: {N} artifacts unlinked to quests β€” /quest suggest
  • If knowledge_gap.gapCount > 0: {N} sessions without captured insights β€” /reflect to extract
  • Else: /todo check to review Β· /ask a question Β· /quest to see more
  • If packages/egregore-artifacts/ exists: Open in browser? /view activity
  • Always end with: What's your focus?

Date formatting

Today β†’ Today (9 chars) Β· Yesterday β†’ Yesterday Β· Older β†’ Mon DD (9 chars). 2-space gap before topic.

Time ago: <1h Nm ago Β· 1-23h Nh ago Β· 1d yesterday Β· 2-6d Nd ago Β· 7d+ Mon DD

Data freshness

Compare my_sessions for today vs disk.handoffs for today. If disk has more files than graph has sessions for today, show in footer: {N} sessions on disk not in graph β€” /save to sync

Step 3: Session orientation

Sequencing (MANDATORY): end the turn with the dashboard as your final text. Do NOT call AskUserQuestion (or any tool) after rendering it β€” the harness hides text that precedes a tool call, which swallows the entire box. The box's closing line What's your focus? IS the question; stop there and wait.

When the user replies, route their answer via the "After selection" table below. Only if their reply is genuinely ambiguous between concrete next steps, present 2-4 options via AskUserQuestion in that NEXT turn:

header: "Focus"
question: "What would you like to focus on?"
multiSelect: false

Generating options β€” model-driven, not table-driven

Generate 2-4 options by reasoning over ALL available data. There is no fixed priority table. You have:

  • handoffs_to_me β€” pending, read, and done handoffs with status
  • pending_questions β€” unanswered questions from teammates
  • my_sessions β€” recent work showing what the user has been doing
  • team_sessions β€” what others are doing (collaboration opportunities)
  • quests β€” active quests with scores and recency
  • prs β€” open PRs that may need review
  • focus_history β€” what the user chose and dismissed in recent sessions
  • The full conversation context of this session (what they've already been working on)

Use focus_history to adapt. This is the key signal:

  • If an option was shown but not selected across 2+ recent sessions β†’ deprioritize it. The user has seen it and chosen not to engage. Don't keep pushing it to the top.
  • If the user consistently selects work stream continuation over handoffs β†’ lead with work streams, not handoffs.
  • If the user typed "Other" with custom text β†’ that tells you what they actually wanted. Use it to inform future option generation.
  • If focus_history is empty (first session or new user) β†’ fall back to surfacing pending handoffs and questions first, then work streams.

Use current session context to adapt. If the user has already been working on something in this session before running /activity, the options should reflect continuation of that work, not ignore it.

Work stream detection: Cluster recent sessions by theme. Name specifically β€” not "Continue recent work" but "Query optimization + batch endpoints" or "Pricing strategy refinement." Hint at what's next, not what's done.

Constraints:

  • Minimum 2 options, maximum 4. "Other" is automatic (provided by AskUserQuestion).
  • Every option must be grounded in actual data β€” no generic labels.
  • Handoffs with status done are excluded from options entirely.
  • Handoffs with status read are lower priority than pending but not excluded β€” the user may want to revisit.

Recording the selection β€” CONNECTED MODE ONLY

Skip this entire section in local mode. Do not run bin/graph-op.sh or show "Remembering..." indicator. Proceed directly to the action.

After the user selects, record what happened for future sessions:

  ✦ Remembering...

Compute the dismissed options (shown minus selected) and record:

bash bin/graph-op.sh record-focus "$SESSION_ID" '$SHOWN_JSON' "$SELECTED" '$DISMISSED_JSON'

Where $SESSION_ID is the most recent session from my_sessions, $SHOWN_JSON is the array of option labels shown, $SELECTED is the chosen label, and $DISMISSED_JSON is the array of labels not chosen. If the user typed custom text via "Other", use their text as the selected value. If the user answered the dashboard's What's your focus? in prose (no menu was shown), record their reply as $SELECTED with [] for both shown and dismissed.

This runs silently β€” do not show output. Proceed immediately to the action.

After selection

SelectionAction
HandoffRead filePath from data. Display content + entry points. Connected mode only: mark as read: output ✦ Remembering... then run bash bin/graph-op.sh mark-read $sessionId. In local mode: skip the mark-read call and the indicator β€” just display the content. Then proceed β€” no follow-up question.
QuestionsLoad QuestionSet, present via AskUserQuestion.
Work streamRead most recent handoff from cluster. Show Open Threads / Next Steps. Mention relevant knowledge artifacts.
PRgh pr view #N --json title,body,additions,deletions,files. Summarize.
New / OtherAsk: "What are you working on?"

Argument filtering

  • /activity quests β€” expand quests, show all with full counts
  • /activity @name β€” filter to that person's sessions
  • /activity done [N], /activity expire [N], /activity reopen [N] β€” fetch activity data and map N to handoffs_to_me[N-1]. In connected mode, output ✦ Resolving..., then run bash bin/activity-action.sh <done|expire|reopen> "$sessionId". Report the resulting state. The script enforces that the handoff is addressed to the current user and that the transition is legal. In local mode, show that graph-backed lifecycle actions are unavailable in this configuration.
  • /activity analytics β€” Run bash bin/analytics-data.sh instead of the normal data script. Render full org health using all 10 metrics (cadence, resolution, quest velocity, collaboration density, todo health, throughput, capture ratio, question response, check-in frequency, issue lifecycle). Same TUI box, 72-char frame. Model decides layout β€” no rigid template. Group metrics by theme (velocity, collaboration, health). Highlight notable patterns, comparisons between people, and week-over-week changes.

Rules

  • bash bin/activity-data.sh for ALL data β€” never call graph.sh directly for reads
  • Quiet fetch only β€” the data script's raw JSON must never appear in the terminal (temp file + compact jq slices, see Step 1)
  • Use bash bin/graph-op.sh <operation> for all graph writes (mark-read, mark-done, etc.) β€” never raw Cypher β€” connected mode only
  • Before any graph write, output a thinking indicator: ✦ Remembering... or ✦ Resolving... β€” connected mode only
  • In local mode: do NOT run any bin/graph-op.sh calls or show thinking indicators. All graph write operations are skipped silently.
  • No sub-boxes β€” only outer frame β”‚ and β”œβ”€β”€β”€β”€β”€ separators
  • DO NOT output reasoning, character counting, or analysis β€” render directly

Related skills