Skip to content

Report repo skill runs from coding agents - #680

Merged
shhdwi merged 1 commit into
mainfrom
feat/skill-runs-from-code
Oct 23, 2026
Merged

shhdwi merged 1 commit into
mainfrom
feat/skill-runs-from-code

Conversation

@shhdwi

@shhdwi shhdwi commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

Claude Code loads repo skills on its own, so Trail never heard about those runs. On the Skills page, a skill the team uses every day said "Not used yet".

What changes

  • The tool-savings PostToolUse hook now also matches Skill. When the agent loads a skill, the hook queues a skill use.
  • The prompt hook does the same when the person types /name.
  • trail init updates the matcher on machines that already have Trail installed.
  • Uses go through the existing activity outbox as a new kind, skill. They're sent with the next sync and retried on failure, and nothing is sent unless the machine is connected.

What counts as a use

  • Only skills the repo keeps at .claude/skills/<name>/SKILL.md. Personal and plugin (plugin:name) skills don't count.
  • The same skill twice in one session within 2 minutes is one use, so typing /name and the agent then loading it isn't counted twice.
  • A use is only sent once this machine has uploaded that skill to the workspace. Until then it's dropped at send time.
  • Most tool calls and prompts aren't skill uses, and they return before reading any file.

Privacy: only the skill's name is sent. Never the task, the prompt or the arguments; the tests check this.

The server side is trailhq/trail-cloud#31 (merged).

Tested

  • test/trail-skill-use.test.ts: parsing, queueing once per run, only repo skills in workspace repos, and the send-only-after-sync rule.
  • Full suite: 3999/4009 pass. The 2 failures are the known graft-to-trail tests that only fail on this machine.
  • End to end on a sandbox laptop:
    • The real ~/.claude hook shim fired on a Skill PostToolUse and on a /cut-a-release 4.3 for the Acme invoice fix prompt.
    • The outbox held the name only, with no args.
    • _trail-sync sent both uses, and the local server stored 2 coding-agent runs.
    • The skill page reads "Used 2×".

🤖 Generated with Claude Code

When Claude Code loads one of the repo's skills (the Skill tool, or the
person typing /name), the hook queues a skill use in the activity outbox:
the skill's name only, never the task, prompt or arguments. Only a skill
the repo keeps in .claude/skills/<name>/ counts, once per run in a
session, and only once the workspace has that skill. The PostToolUse
matcher gains Skill; trail init updates it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@trailhq-graft

trailhq-graft Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

🌱 graft blast radius

2 areas changed → 3 areas can be affected. 8 dependent symbols, depth 2.
Tests: 2 areas updated their tests.
Tag: @anirudhkumar-nanonets — 5 of 5 areas · Rushabh Nagda — Workspace Activity Sync, Pair Session Setup

flowchart TB
  A0(("Pair Session Setup<br/>4 symbols"))
  A1(("CLI Entry Point<br/>3 symbols"))
  A2(("Trail Initialization<br/>1 symbol"))
  classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
  class A0,A1,A2 reached;
Loading
Can be affected Symbols Nearest hop Reached from
Pair Session Setup 4 src/cloud/lookup-activity.ts:L28-L57 recordLookup — calls, depth 2 Workspace Activity Sync
CLI Entry Point 3 src/cli.ts:L2139-L2213 workspaceCommand — calls, depth 2 Workspace Activity Sync
Trail Initialization 1 src/claude/init.ts:L194-L245 runTrailInit — calls, depth 2 Prompt Hook Processing
Who knows this code — 2 people across 5 areas
Area Who knows it
Workspace Activity Sync · changed Rushabh Nagda — 2 commits, last 2d ago · @anirudhkumar-nanonets — 1 commit, last 10d ago
Prompt Hook Processing · changed @anirudhkumar-nanonets — 22 commits, last yesterday
Pair Session Setup · affected Rushabh Nagda — 1 commit, last 2d ago · @anirudhkumar-nanonets — 1 commit, last 10d ago
CLI Entry Point · affected @anirudhkumar-nanonets — 61 commits, last yesterday
Trail Initialization · affected @anirudhkumar-nanonets — 11 commits, last 8d ago

Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no @ has no GitHub handle in its commit email — tag them by hand, or add a .mailmap entry. A suggestion from history, not a CODEOWNERS rule.

All 8 dependent symbols, grouped by area

Pair Session Setup — 4 symbols in 4 files

  • src/cloud/lookup-activity.ts:L28-L57 — recordLookup (calls, depth 2)
    28: export function recordLookup(r: AskResult, repo: string, cloud: Cloud | null = readCloud(), savedTokens?: number): void {
  • src/cloud/nudge.ts:L269-L323 — waitForConnect (calls, depth 2)
    285: const repos = pickerRepos(pending.repo, env);
  • src/cloud/other-repos.ts:L102-L135 — setUpPicked (calls, depth 2)
  • src/cloud/pair.ts:L263-L321 — finishPair (calls, depth 2)
    263: export async function finishPair(state: string, repo: string, opts: FinishOptions = {}): Promise<"uploaded" | "expired" | "timed_out" | "failed"> {

CLI Entry Point — 3 symbols in 1 file

  • src/cli.ts:L2139-L2213 — workspaceCommand (calls, depth 2)
    2143: .option("--json", "output as JSON")
  • src/cli.ts:L2378-L2427 — runTeamCheck (calls, depth 2)
    2378: async function runTeamCheck(dir: string, opts: { base?: string; json?: boolean }): Promise<void> {
  • src/cli.ts:L1-L2588 — cli.ts (calls, depth 2)
    5: * graft/ and a clone has the graph. A workspace parent (≥2 git children)

Trail Initialization — 1 symbol in 1 file

  • src/claude/init.ts:L194-L245 — runTrailInit (calls, depth 2)
    224: else warnings.push(notPlainJson('.claude/settings.local.json', "trail's status line and allowlist"));
Test signal per changed area — 2 ✓

Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.

  • ✓ Workspace Activity Sync — 1 of 6 reached · 1 test file changed here: test/trail-skill-use.test.ts
    • not reached: repoSkillName, rememberSent, readSent, onlySent, activityEvent
  • ✓ Prompt Hook Processing — 4 of 6 reached · 1 test file changed here: test/trail-skill-use.test.ts
    • not reached: main, hookBlocks
8 test suites also reference this code

8 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.

  • test/claude-hook-timeouts.test.ts
  • test/claude-pre-bash-wiring.test.ts
  • test/trail-cloud.test.ts
  • test/trail-connect.test.ts
  • test/trail-init-layout.test.ts
  • test/trail-prompt-activity.test.ts
  • test/trail-upload-names.test.ts
  • test/trail-upload-safety.test.ts

graft blast · origin/main...HEAD · depth 2 · 10 changed files

Open the interactive graph → — click an area to see its dependent symbols at file:line.

github-actions Bot added a commit that referenced this pull request Oct 23, 2026
@shhdwi
shhdwi merged commit 3c94753 into main Oct 23, 2026
10 of 11 checks passed
github-actions Bot added a commit that referenced this pull request Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant