Ø
Tensorpunk  Labs  // RELAY
On this page
// the fourth question
concept

Before this release, a Relay deposit answered three questions: what was decided, what's still open, and what's being handed off. The receiving session would pull the package and start oriented — on the conclusions.

The missing piece was always context. A decision is more legible when you can see what the previous agent was looking at when they made it. So we added a fourth question: what was being seen. Every deposit can now carry a context_snapshot — a structured inventory of files in the depositing agent's conversation context at deposit time, alongside the decisions and the handoff note.

Why it's a first-class field, not a side feature. Captured context is most useful when it travels with the deposit it produced. A separate observation artifact creates two things to keep in sync; one structured field on the package keeps the protocol coherent and lets the dashboard, cross-Relay federation, and orient bundles all consume it the same way.
// why it matters
design

Three uses where this changes the receiving-agent experience materially.

1. Resume without re-exploring

Picking up a session cold, the receiving agent gets the same files the previous agent had loaded — paths, roles, why each one mattered. No "let me grep around to figure out what we were working on." The snapshot is the map; the agent goes straight to the work.

2. Cross-Relay federation gets richer

When a deposit crosses actors (you deposit into a shared project, another Relay instance picks it up), the receiving actor now sees not just your decisions but the surface area you were considering. Less context loss across the boundary; better follow-up questions.

3. Audit and review

For human reviewers and orchestrator agents alike, "what files were in scope when this decision happened" is a useful signal. A deposit that touches authentication while only having one auth-related file in context reads differently from one that had the full subtree loaded.

// the json shape
schema

A context_snapshot is a JSON object on the package payload. Type definitions live in @relay/core (ContextSnapshot, ContextSnapshotFile, ContextSnapshotRanked).

Minimal example
{
  "session_shape": {
    "files": 8,
    "lines": 1101,
    "dominant_categories": ["instructions", "major-doc"]
  },
  "files": [
    {
      "path": "src/auth/session.ts",
      "role": "edit",
      "category": "source-code",
      "lines": 214,
      "why": "current edit target — refresh token logic"
    }
  ],
  "heavyweights": {
    "biggest": [{ "path": "...", "metric": 270, "note": "..." }],
    "most_touched": [{ "path": "...", "metric": 3, "note": "..." }],
    "stale": [{ "path": "...", "metric": null, "note": "..." }]
  },
  "category_totals": { "instructions": 420, "major-doc": 651 }
}
session_shape

Top-of-the-fold summary. files and lines are coarse counts; dominant_categories ranks the 2–3 categories that dominate the context budget. The dashboard chip renders from these three fields alone.

files[]

Per-file entries with path, role (read / edit / write / session-load / plan / reference), category, approximate lines, and a short why phrase explaining why the file was in context. When 3+ siblings share a directory and extension, they collapse into one row (is_group: true with group_count) — keeps the payload compact for big codebases.

heavyweights

Three ranked lists for fast rendering: biggest (by line count), most_touched (by reference count this session), and stale (loaded early and unused since — candidates for /clear if context pressure is a concern).

category_totals

Total lines per category. Powers the dashboard bar chart without needing to re-walk files[] at render time.

// redaction
safety

Snapshots are paths-only — no file contents are ever transmitted or stored. Even so, path strings themselves can hint at secrets (infra/secrets/prod.key, ~/.aws/credentials). Before any snapshot is persisted, redactSensitivePaths in @relay/core replaces matched paths with the literal string [redacted].

Patterns redacted
# Anything matching these regexes is replaced with [redacted]
.env*                                # dotenv files
credentials*                         # AWS/GCP credentials files
*.key  *.pem  *.p12  *.pfx           # private keys
secrets/                             # any path under a secrets dir
.ssh/                                # SSH config and identity files
.aws/                                # AWS CLI / SDK state
.gnupg/                              # GPG keyring
id_rsa(.pub)                         # SSH RSA identities
Single-sourced. Redaction lives in @relay/core and runs server-side on every deposit path — CLI, MCP, and any future client share identical behavior. The redaction step is idempotent: re-running on an already-redacted snapshot is a no-op. Counts are preserved — a redacted file still appears in files[] and heavyweights as [redacted], so the receiver knows the slot exists even though the path is suppressed.
// attach via the CLI
manual deposit

Pass a JSON file matching the ContextSnapshot shape to relay deposit --context-snapshot <path>. The CLI validates the shape with validateContextSnapshot before constructing the package; a malformed file fails fast with a descriptive error.

# 1. Write the snapshot JSON somewhere
$cat > /tmp/snap.json << 'EOF'
{ "session_shape": { "files": 3, "lines": 412, "dominant_categories": ["source-code"] }, ... }
EOF

# 2. Deposit, attaching the snapshot
$relay deposit \
    --title "[SIG] refactored session token handling" \
    --description "Split refresh logic out of session.ts; tests still failing on expiry edge case" \
    --decisions "Refresh tokens now opaque, not JWT — easier to revoke" \
    --questions "Do we keep the JWT path behind a flag, or remove entirely?" \
    --handoff "Tests: auth.test.ts:128 (expired-token edge case)" \
    --context-snapshot /tmp/snap.json
The flag is optional. Routine deposits without a snapshot still work exactly as before — the column on the package row is simply omitted, which keeps the call forward-compatible with Supabase projects that haven't applied the schema migration yet.
// attach via the relay_deposit MCP tool
agent-driven

The relay_deposit MCP tool gains a top-level context_snapshot parameter. Agents pass the object directly — no file roundtrip. The tool runs the same validator and the same redactor as the CLI path; malformed input is rejected with a structured error response so the agent can correct and retry.

# Inside the agent (Claude Code, Cursor, any MCP-aware client)
relay_deposit({
  title: "[SIG] refactored session token handling",
  description: "...",
  decisions: ["Refresh tokens now opaque, not JWT"],
  open_questions: ["JWT path: flag or remove?"],
  handoff_note: "Tests still failing on auth.test.ts:128",
  context_snapshot: {          // top-level — not nested in description
    session_shape: { ... },
    files: [...],
    heavyweights: { ... },
    category_totals: { ... }
  }
})
Watch the parameter discipline. context_snapshot is a top-level argument on the tool call. Some agents have a habit of stuffing structured data inside the description string as XML-like tags — that path leaks the raw markup into the package's description field and leaves context_snapshot empty. Pass the object as a proper argument; the validator will tell you immediately if the shape is off.
// in the dashboard
timeline

On the Relay dashboard at relaymemory.com/dashboard, every package row in the live timeline that carries a snapshot picks up a small phosphor-green chip:

# What the chip looks like on a timeline row
⌗ 8 files in context · ~1,101 lines · instructions, major-doc

Hover the chip and the tooltip surfaces the biggest file in scope at deposit time. A future iteration (queued for the next dashboard PR) expands the chip into a full "Context at deposit" panel — sortable file table, category bar chart, heavyweights side panel — mirroring the standalone visualizer aesthetic shipped with the /tpl-context-report skill.

Backward compatible. Packages predating the migration simply render with no chip. The dashboard's filtering and search remain unchanged; the snapshot is additive signal, not load-bearing for any existing view.
// try it locally today
claude code

The /tpl-context-report Claude Code skill is the live-mode preview of what a deposit's context_snapshot field carries. Run it during a session and it inventories every file in the agent's conversation context, renders a self-contained dark-mode HTML visualizer, and (with --deposit) emits the JSON in the exact shape Relay expects.

Install the skill
# macOS / Linux
$mkdir -p ~/.claude/skills
$cp -r skills/tpl-context-report ~/.claude/skills/

# Windows (PowerShell)
>Copy-Item -Recurse -Force skills\tpl-context-report "$HOME\.claude\skills\"

Restart Claude Code so the skill registry reloads, then invoke it.

Preview the snapshot (no deposit)
/tpl-context-report

# Output:
# - Markdown table of files in context (grouped)
# - Self-contained HTML visualizer opens in your default browser
# - Heavyweights panel: biggest, most-touched, stale
Emit JSON for deposit
/tpl-context-report --deposit

# Writes:
#   %TEMP%\tpl-reports\context-snapshot-<timestamp>.json  (Windows)
#   $TMPDIR/tpl-reports/context-snapshot-<ts>.json         (macOS/Linux)

# Then you can deposit:
$relay deposit --title "..." --context-snapshot "<path-above>"

With --deposit --inline, the JSON also prints to chat so you can paste it directly into the relay_deposit MCP tool's context_snapshot parameter without writing a file.

The skill is bundled with this repo. Find it at skills/tpl-context-report/ alongside using-relay and tpl-handoff. See github.com/Tensorpunk-Labs/relay/tree/main/skills.
// auto-deposits via PostToolUse hook
passive capture

The stop-hook auto-deposit runs after the agent has exited, so it can't ask the agent for an inventory. The solution is passive observation: a PostToolUse hook fires for every file tool call (Read, Edit, Write, Glob, Grep, NotebookEdit, MultiEdit) while the agent is still running and appends a record to .relay/context-log.jsonl in the project's working directory. When the stop hook then runs relay deposit --auto, the CLI reads the log, synthesizes a ContextSnapshot from it (de-duped, categorized, ranked), attaches it to the package, and truncates the log so the next session starts clean.

Wire it up

Add a single block to your global ~/.claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Read|Edit|Write|Glob|Grep|NotebookEdit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "relay hook log-tool"
          }
        ]
      }
    ]
  }
}

The handler is defensive — it never throws, never blocks the agent's tool loop, never returns non-zero. If anything goes wrong (no stdin, malformed JSON, disk error), it exits silently and the next auto-deposit just falls back to git-state-only.

What gets captured. Per file: path (absolute), the strongest role observed (write > edit > read > reference), touch count, and the tools that touched it. Roll-up: heavyweights by line count, by touch count, and "stale" entries (loaded early, untouched since). Category inferred from extension. All paths flow through the same redaction step as manual snapshots before persistence.
// what's not in this release
roadmap

One remaining follow-up, called out so you know what's coming.

Full "Context at deposit" dashboard panel

The current dashboard surface is the timeline chip (file count, lines, top categories, biggest-file tooltip). Next pass expands it into a panel matching the standalone visualizer: sortable file table, category bar chart, heavyweights, live filter. Schema and data are already in place; this is a rendering follow-up.

Backfill is not planned. Old packages legitimately have no snapshot — the column is nullable and the dashboard handles null gracefully. We don't try to reconstruct context after the fact; the field starts from the moment a session opts into capturing it.