Skip to content

feat: trail init learns from past Claude sessions, and signing in waits - #585

Merged
anirudhkumar-nanonets merged 45 commits into
mainfrom
feat/trail-first-run-learnings
Oct 13, 2026
Merged

anirudhkumar-nanonets merged 45 commits into
mainfrom
feat/trail-first-run-learnings

Conversation

@anirudhkumar-nanonets

@anirudhkumar-nanonets anirudhkumar-nanonets commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Changes from the Oct 13 review of the trail demo. Stacked on #558.

Moves: learnings_committed, the number of clones whose committed learnings went up in the last 7 days. The PostHog query is in daily/project.md. Its value today is 0, because the event ships in this PR.

What changes

  • trail init learns from past sessions, with no questions asked. It reads the person's own messages in the repo's past Claude Code sessions (the checkout and its worktrees). It leaves out tool output, reminders, pasted text and headless runs. Then it asks the person's own Claude Code, headless on Sonnet 5.5, what they told Claude in more than one session. A finding is kept only if the quotes it cites really are in two or more sessions, and secrets are scrubbed. Findings are saved as learnings: the team's in .trail/learnings/, the person's own in ~/.trail. This runs once per repo per machine, while the rest of init runs. On assign it read 92 sessions and saved 5 learnings, and init took 40 s.

  • Standing learnings. Those learnings are rules for every session, not knowledge about one task, so the session-start hook lists them up front. In a new session on assign, Claude opened with "Before I build, here's what I understood" and planned a branch against dev, both from the learnings.

  • One kind of learning, worded by who it's for. Learnings now read "saved for your team" or "saved just for you". trail learn and trail skills still run but are out of help and the skill. Corrections are saved as learnings too.

  • Closing lines, from Shrish's copy. After a team learning, the reply ends with "🌱 Rishabh, Anay and 56 others work in this repo. Commit what you learned and give their agents a 39k-token head start", or "📝 Committed · …" once it is committed. The skill has Claude check git status first. The names are recent authors of the same files. Team learnings left uncommitted get a once-a-day reminder at session start. The reuse credit adds minutes saved.

  • Front matter is YAML only. gray-matter evaluated ---js front matter, and learnings come from teammates' pushed branches. Fixed here and on feat: trail, with learnings in .trail/, a local check, and workspaces #558.

  • Signing in waits. The sign-in link at the end of a reply, and login, logout and workspace, are off unless TRAIL_CLOUD=1 is set, or the machine is already connected.

  • One MCP server. On a machine where graft's MCP server is installed globally, trail init leaves it alone, so repos still wired as graft keep it. It turns graft off for that folder only, in Claude Code's per-folder setting, so a trail repo lists one server. A machine without graft gets trail globally.

  • graft users move to trail.

    • graft upgrade installs trail too (once @trailhq/trail is on npm), then runs trail init in the repo it was run from, with that repo's agents and flags.
    • Every other repo wired as graft moves the next time a Claude session opens in it, once trail is on the machine. That session's refresh rewires it as trail, Claude tells the user once, and the past-session read runs in the background. GRAFT_NO_TRAIL_SWITCH=1 keeps a machine on graft.
    • The update notice now says graft upgrade instead of a bare npm i -g.
    • A teammate with only graft, in a repo that's on trail, gets a per-folder trail server that runs graft mcp. It's removed once they install trail.
  • Events.

    • learnings_committed: at session start, when more learnings are committed on HEAD than at the last session in that clone.
    • cold_start: the result of the first-run read.

    Both are in TELEMETRY.md. No messages or titles are sent.

Tests

  • New: trail-cold-start, which includes a trail init end-to-end test with a stand-in claude on PATH, and trail-learnings-committed.
  • Updated: help, status, note and nudge tests for the new wording.
  • Full suite: 1,491 pass, 0 fail. The graft upgrade → trail init step can't run end to end until @trailhq/trail is published.

@trailhq-graft

trailhq-graft Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

🌱 graft blast radius

5 areas changed → 12 areas can be affected. 84 dependent symbols, depth 2.
Tests: 4 areas updated their tests.
Tag: @shhdwi — 11 of 17 areas · @qoole — Dependency Graph, Context Building · @afeddersen — 3 of 17 areas

flowchart TB
  A0(("Brain Sync<br/>25 symbols"))
  A1(("Dependency Graph<br/>18 symbols"))
  A2(("Impact Analysis<br/>10 symbols"))
  A3(("Build And Review<br/>8 symbols"))
  A4(("Telemetry<br/>6 symbols"))
  AX(("7 smaller areas<br/>17 symbols"))
  classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
  class A0,A1,A2,A3,A4 reached;
  classDef tail fill:#EEF2F3,stroke:#9AA4A9,stroke-width:1px,color:#3A4247;
  class AX tail;
Loading
Can be affected Symbols Nearest hop Reached from
Brain Sync 25 src/brain/autopush.ts:L1-L270 autopush.ts — imports, depth 1 CLI Core, Claude Integration
Dependency Graph 18 src/graph/build.ts:L1-L411 build.ts — imports, depth 1 CLI Core, Session Notes +1
Impact Analysis 10 src/blast/blast-cli.ts:L1-L193 blast-cli.ts — imports, depth 1 CLI Core, test/graft-to-trail.test.ts
Build And Review 8 src/app/brain-build.ts:L1-L428 brain-build.ts — imports, depth 1 CLI Core
Telemetry 6 src/telemetry/identity.ts:L68-L81 installId — calls, depth 1 CLI Core
MCP Tools 4 src/mcp/tools.ts:L247-L329 callSingleTool — calls, depth 1 CLI Core, Session Notes
6 smaller areas 13 Visualization Export, Claude Integration, Code Search, … see below
Who knows this code — 6 people across 17 areas
Area Who knows it
CLI Core · changed @shhdwi — 41 commits, last 2mo ago
Claude Integration · changed @shhdwi — 24 commits, last 2mo ago
Host Configuration · changed @shhdwi — 11 commits, last 2mo ago
Build Scripts · changed @afeddersen — 1 commit, last 1mo ago · @shhdwi — 1 commit, last 3mo ago
Dependency Graph · affected @shhdwi — 20 commits, last 2mo ago · @qoole — 5 commits, last 2mo ago
Telemetry · affected @afeddersen — 1 commit, last 1mo ago · Marcelo Caporale — 1 commit, last 1mo ago
MCP Tools · affected @shhdwi — 14 commits, last 2mo ago
Visualization Export · affected @shhdwi — 1 commit, last 3mo ago
…9 further areas

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 84 dependent symbols, grouped by area

Brain Sync — 25 symbols in 12 files

  • src/brain/autopush.ts:L1-L270 — autopush.ts (imports, depth 1)
    3: * push`, at most once a day, started by the session-start hook.
  • src/brain/autopush.ts:L80-L82 — patchTrailPushState (calls, depth 1)
    80: function patchTrailPushState(repo: string, patch: TrailPushState): void {
  • src/brain/link.ts:L1-L232 — link.ts (imports, depth 1)
    2: * The link between a repo's graft graph and a Trail brain.
  • src/brain/link.ts:L115-L117 — writeRulesCache (calls, depth 1)
    116: writeJsonAtomic(rulesCachePath(dir), cache, true);
  • src/brain/pull.ts:L1-L332 — pull.ts (imports, depth 1)
    2: * `graft trail pull`: one command for both things a trail hands this repo.
  • src/brain/push.ts:L287-L293 — pickedAgents (calls, depth 1)
    289: return [...new Set([...(readStamp(root)?.hosts ?? []), ...wiredHostIds(root)])];
  • src/brain/watch-trail.ts:L1-L395 — watch-trail.ts (imports, depth 1)
    2: * `graft trail watch`: wait until Trail has something for this repo, then say so
  • src/brain/attach.ts:L1-L92 — attach.ts (imports, depth 2)
    2: * Attach a brain's rules to an `ask` answer.
  • src/brain/autopush.ts:L238-L263 — maybeAutopush (calls, depth 2)
    238: export function maybeAutopush(repo: string, deps: AutopushDeps = {}): AutopushDecision {
  • src/brain/autopush.ts:L105-L112 — recordSeenSuggestions (calls, depth 2)
    105: export function recordSeenSuggestions(repo: string, count: number): void {
  • src/brain/autopush.ts:L90-L97 — recordTrailPush (calls, depth 2)
    90: export function recordTrailPush(repo: string, head: string, now = Date.now()): void {
  • src/brain/claude-md.ts:L1-L215 — claude-md.ts (imports, depth 2)
    3: * old name): write the CLAUDE.md changes accepted in Trail into this checkout's
  • src/brain/connect.ts:L1-L111 — connect.ts (imports, depth 2)
    2: * The one command a user runs to attach a brain: parse the handoff value,
  • src/brain/connect.ts:L67-L86 — connectBrain (calls, depth 2)
    68: repo: string,
  • src/brain/context-files.ts:L1-L282 — context-files.ts (imports, depth 2)
    5: * AGENTS.md, a folder's own CLAUDE.md, Cursor rules, Claude skills — and a
  • src/brain/link.ts:L133-L137 — markRulesChecked (calls, depth 2)
  • src/brain/pull.ts:L225-L331 — runTrailPull (calls, depth 2)
    225: export async function runTrailPull(repo: string, link: BrainLink, opts: PullOptions): Promise<number> {
  • src/brain/push.ts:L1-L395 — push.ts (imports, depth 2)
    4: * The server path needs graft's GitHub App installed on the repo, which is an
  • src/brain/push.ts:L248-L279 — buildEarlyDigest (calls, depth 2)
    251: ): Promise<{ digest: RepoDigest; threads: HistoryThread[] } | null> {
  • src/brain/push.ts:L313-L378 — buildLocalDigest (calls, depth 2)
    317: ): Promise<{ digest: RepoDigest; warning?: string } | { error: string }> {
  • src/brain/upload.ts:L1-L255 — upload.ts (imports, depth 2)
    2: * Getting a digest to Trail quickly, and getting it there at all.
  • src/brain/watch-trail.ts:L101-L124 — readTrailSnapshot (calls, depth 2)
    102: repo: string,
  • src/brain/watch-trail.ts:L209-L218 — result (calls, depth 2)
    209: const result = (reason: WatchExitReason, extra: Partial<WatchTrailResult> = {}): WatchTrailResult => ({
  • src/brain/watch.ts:L1-L529 — watch.ts (imports, depth 2)
    4: * `graft trail push` used to end at "it is being mined into rules now — a few
  • src/brain/wire.ts:L1-L148 — wire.ts (imports, depth 2)
    2: * Writing a brain's rules into the instruction file each coding agent already

Dependency Graph — 18 symbols in 10 files

  • src/graph/build.ts:L1-L411 — build.ts (imports, depth 1)
    2: * `graph` — build `.context/graph.json` from a code repository.
  • src/graph/extract-cache.ts:L1-L224 — extract-cache.ts (imports, depth 1)
    2: * Per-file memo for Tier-1 extraction — `<outDir>/.cache/extract.json`.
  • src/graph/extract-cache.ts:L213-L223 — writeExtractCache (calls, depth 1)
    217: writeJsonAtomic(path, cache, true);
  • src/graph/fingerprint.ts:L1-L197 — fingerprint.ts (imports, depth 1)
    2: * The cheap "has the working tree moved?" probe that gates the pre-query rebuild.
  • src/graph/fingerprint.ts:L87-L103 — writeFingerprint (calls, depth 1)
    97: writeJsonAtomic(fingerprintPath(outDir), record, true);
  • src/graph/root.ts:L1-L46 — root.ts (imports, depth 1)
    2: * Where "here" is when a query names no directory. An agent session — or a plain
  • src/graph/seed.ts:L1-L229 — seed.ts (imports, depth 1)
    2: * `seedGraph` — give a linked git worktree the graph its parent checkout already has.
  • src/graph/traverse-cli.ts:L1-L243 — traverse-cli.ts (imports, depth 1)
    4: * One command, one implementation: resolve a symbol via `resolveSymbol`, walk
  • src/graph/workspace-cli.ts:L88-L97 — runWorkspaceAsk (calls, depth 1)
    92: opts: { limit?: number; source?: boolean; full?: boolean; in?: string; json?: boolean },
  • src/graph/workspace-cli.ts:L1-L145 — workspace-cli.ts (imports, depth 1)
    12: import { formatAsk } from "../ask/ask.js";
  • src/graph/workspace.ts:L1-L725 — workspace.ts (imports, depth 1)
    3: * more immediate git-repo children and has no source graph of its own. Instead
  • src/graph/build.ts:L151-L410 — buildGraph (calls, depth 2)
    159: // including the repo's persisted directory and submodule choices.
  • src/graph/load.ts:L1-L116 — load.ts (imports, depth 2)
    2: * mtime-keyed in-process cache over the two readers `ask()` calls on every
  • src/graph/map.ts:L325-L350 — formatRepoMap (calls, depth 2)
    327: const header = `repo map — ${totals.files} files · ${totals.symbols} symbols · ${totals.edges} edges · ${totals.languages.join(", ")}`;
  • src/graph/traverse-cli.ts:L166-L242 — runCallersCommand (calls, depth 2)
    171: console.error(`✗ no graph found at ${contextDir} — run \`graft build\` first`);
  • src/graph/traverse-cli.ts:L71-L78 — quoteFor (calls, depth 2)
    72: hit: EdgeHit,
  • src/graph/workspace.ts:L240-L558 — federateAsk (calls, depth 2)
    245: ): AskResult {
  • src/graph/workspace.ts:L659-L695 — federateCallers (calls, depth 2)
    670: const blocks: string[] = [];

Impact Analysis — 10 symbols in 7 files

  • src/blast/blast-cli.ts:L1-L193 — blast-cli.ts (imports, depth 1)
    4: * Kept out of cli.ts (argument wiring only) so the diff → seeds → walk → render
  • src/blast/evidence.ts:L93-L106 — referenceLine (calls, depth 1)
    95: span: string,
  • src/blast/modules.ts:L1-L99 — modules.ts (imports, depth 1)
    2: * Module labels for the blast diagram — the "what part of the system is this?"
  • src/blast/name.ts:L1-L303 — name.ts (imports, depth 1)
    5: * The point is scope. Getting labels from `build --deep` means summarising every
  • src/blast/blast-cli.ts:L168-L192 — exportRadius (calls, depth 2)
    184: repoName: repoLabel(root),
  • src/blast/blast.ts:L1-L542 — blast.ts (imports, depth 2)
    2: * Blast radius of a diff: what else in the repo depends on the lines this change
  • src/blast/evidence.ts:L1-L193 — evidence.ts (imports, depth 2)
    4: * `blast` knows which lines changed (git's hunks) and which symbols reach them
  • src/blast/evidence.ts:L122-L154 — impactedEvidence (calls, depth 2)
    125: read: (path: string) => string[] | null,
  • src/blast/render.ts:L1-L452 — render.ts (imports, depth 2)
    8: * GitHub renders Mermaid natively in comments, so there is nothing to host.
  • src/blast/viz.ts:L1-L223 — viz.ts (imports, depth 2)
    6: * can never answer the reviewer's next question: which symbols, at which lines,

Build And Review — 8 symbols in 7 files

  • src/app/brain-build.ts:L1-L428 — brain-build.ts (imports, depth 1)
    5: * repository URL, and a minute later they are looking at rules mined from their
  • src/app/review.ts:L1-L174 — review.ts (imports, depth 1)
    5: * the caller uses to publish it. Everything runs in-process against the same
  • src/app/brain-build-process.ts:L1-L152 — brain-build-process.ts (imports, depth 2)
    2: * Running a repository read somewhere it cannot stop the App answering.
  • src/app/brain-build-worker.ts:L1-L83 — brain-build-worker.ts (imports, depth 2)
    2: * The process one repository read runs in.
  • src/app/review-process.ts:L1-L269 — review-process.ts (imports, depth 2)
    2: * Running a review somewhere it cannot stop the App answering.
  • src/app/review-worker.ts:L1-L110 — review-worker.ts (imports, depth 2)
    5: * `reviewPullRequest` the server used to call directly, and reports back. Nothing
  • src/app/review.ts:L102-L133 — exportPage (calls, depth 2)
    120: repoName: job.repo,

…23 further symbols not listed.

Test signal per changed area — 4 ✓ · 1 –

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.

  • ✓ CLI Core — 57 of 219 reached · 12 test files changed here: test/brain-signup.test.ts, test/front-matter.test.ts, test/graft-to-trail.test.ts, test/telemetry-contract.test.ts, test/trail-check-diff.test.ts, test/trail-check-local.test.ts, test/trail-cloud.test.ts, test/trail-name.test.ts, test/trail-notes.test.ts, test/trail-nudge.test.ts, test/trail-skills.test.ts, test/upkeep.test.ts
    • not reached: commandOnPath, inBrand, setBrand, trailOnPath, readPackageName, runUpgrade, grouped, queryRoot, …154 more
  • ✓ Claude Integration — 18 of 40 reached · 13 test files changed here: test/claude-init.test.ts, test/claude-settings-merge.test.ts, test/claude-shim-resolve.test.ts, test/claude-shim-template.test.ts, test/claude-statusline.test.ts, test/graft-to-trail.test.ts, test/hosts-claude-global.test.ts, test/trail-cold-start.test.ts, test/trail-learnings-committed.test.ts, test/trail-name.test.ts, test/trail-note-ask.test.ts, test/trail-notes.test.ts, test/trail-prompt-notes.test.ts
    • not reached: retrievalBody, b, teamNotesDirective, hookTimeoutIn, askForNote, trackRepoSeen, trailAtStart, main, …14 more
  • ✓ Session Notes — 34 of 113 reached · 8 test files changed here: test/front-matter.test.ts, test/trail-cloud.test.ts, test/trail-cold-start.test.ts, test/trail-home.test.ts, test/trail-note-ask.test.ts, test/trail-note-mentions.test.ts, test/trail-notes.test.ts, test/trail-nudge.test.ts
    • not reached: attachNotes, pointerFile, branchesStale, cachePath, commonGitDir, defaultRef, firstName, git, …71 more
  • ✓ Host Configuration — 10 of 16 reached · 3 test files changed here: test/claude-shim-template.test.ts, test/graft-to-trail.test.ts, test/hosts-claude-global.test.ts
    • not reached: mergeJsonKey, removeJsonKey, isGraftCmd, stripClaudeSettings, stripCodexHooks, targets
  • – Build Scripts — no function, method or class changed here
81 test suites also reference this code

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

  • test/app-review-process.test.ts
  • test/ask-fusion.test.ts
  • test/ask-index.test.ts
  • test/ask.test.ts
  • test/blast-name.test.ts
  • test/blast-viz.test.ts
  • test/brain-context-files-pull.test.ts
  • test/brain-early-upload.test.ts
  • test/brain-push-agents.test.ts
  • test/brain-trail-watch.test.ts
  • test/brain-upload.test.ts
  • test/brain-watch.test.ts
  • test/claude-format.test.ts
  • test/claude-hooks.test.ts
  • test/claude-md-pull.test.ts
  • test/claude-skill-template.test.ts
  • test/claude-state.test.ts
  • test/claude-tally.test.ts
  • test/cli-meta.test.ts
  • test/cli-picker.test.ts
  • …61 more

⚠️ 6 changed files not in the graph (.claude/helpers/graft-hooks.cjs, .claude/helpers/graft-statusline.cjs, .gitignore, README.md, TELEMETRY.md) — no parser claims the extension, or the index predates the file.

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

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

@anirudhkumar-nanonets
anirudhkumar-nanonets changed the base branch from feat/trail-cloud to main October 13, 2026 13:52
github-actions Bot added a commit that referenced this pull request Oct 13, 2026
@anirudhkumar-nanonets
anirudhkumar-nanonets merged commit 8dc7a63 into main Oct 13, 2026
7 of 8 checks passed
github-actions Bot added a commit that referenced this pull request Oct 13, 2026
shhdwi added a commit that referenced this pull request Oct 14, 2026
…ft updating (#595)

* chore(package): point repository, homepage and bugs at trailhq/Trail-Code

The repo was renamed. npm provenance checks the repository URL against the
GitHub repo that runs the publish, case included, so a release from Actions
needs the exact name.

* fix(trail): tell someone typing trail when a graft-era repo can't reach it

graft 0.21 and older committed hook shims that look for @nanonets/graft
alone, and registered a bare `graft mcp` server. On a machine with trail
and no graft, those hooks run and do nothing and the server never starts,
so the session start that moves a repo to trail never happens.

trail init in the repo moves it, as does a session under the hooks trail
init writes to ~/.claude. For someone who has done neither, trail now
prints one line in such a repo saying to run trail init there. Only for a
person at a terminal; agents, pipes, CI and graft never see it.

* chore: publish trail as @trailhq/trail-code

The package takes the product's name; the command stays `trail` and
@nanonets/graft is unchanged. Hook shims also still find @trailhq/trail,
the name builds from source had before anything was published.

* fix(hooks): answer each Claude Code event once, not from both copies

init registers the hooks in the repo and in ~/.claude, and Claude Code
runs both, so every prompt got its learnings twice and the ask to save one
came twice. The repo's copy now stands down for an event the ~/.claude copy
answers, when that copy can find trail. Cursor and Codex shims never do.

* feat(hooks): on graft without trail, the agent tells the person how to get it

A person typing graft already sees that graft is now trail. Most people
only meet graft through their agent, which was told nothing. Once a week,
in a repo graft set up, the session start now asks the agent to say in one
line that `graft upgrade` adds trail and graft keeps working.

* release: 0.22.0

* fix: hints and footers name trail's commands under trail

A trail-only install has no graft binary, so a hint that told the agent to
run graft ask, or a blast header tagged [graft], cost a failed tool call.
The saved-tokens tally now also counts "trail saved".

* docs: the Trail-code README, up to date with trail init's first read

Rewrites the README around Trail-code's two parts: the graft map and
learnings. Adds the how-it-works diagram and drops the old graft assets;
TELEMETRY, SECURITY, CREDITS and docs/github-app.md use the new name.

Matches what main does since #585: trail init reads past sessions once,
corrections are saved as learnings, skills and the workspace commands are
out of help and marked soon, and the save lines read "saved for your team".
Says how a repo graft set up moves to trail.

* docs(readme): the package is @trailhq/trail-code; claims match what ships

* docs(readme): benchmark, languages, build and CLI claims match the code

* fix(hosts): wire other agents under trail's names when the repo uses trail

trail init wrote graft-branded files for every agent but Claude Code:
AGENTS.md "## Graft", .cursor/rules/graft.mdc and the rest told the agent
to run graft ask/grep/callers, which a machine with only
@trailhq/trail-code doesn't have, and their MCP entries pulled
npx -y @nanonets/graft.

The other agents now follow the repo's name the way Claude Code's wiring
does (hostWiringName, read from the repo, so a teammate on graft never
flips it back). Under trail:
- instruction text is graft's in trail's spelling (trailSpelling, shared
  with the Claude skill: graft check -> trail build --check)
- owned files carry the name (.cursor/rules/trail.mdc,
  .adal/skills/trail/SKILL.md, .cursor/hooks/trail-hooks.cjs,
  ~/.gemini/skills/trail/SKILL.md) and graft's copy goes
- shared files get a <!-- trail:start --> block that replaces a graft-era
  block in place, never beside it
- MCP servers are `trail` (trail mcp / npx -y @trailhq/trail-code mcp) and
  graft's entry is dropped; a graft repo leaves a machine-wide trail
  server alone rather than add graft's beside it

The session-start move to trail (upkeep toTrail) now moves these hosts
too, upkeep finds them under either name, and uninstall removes either
name, Cursor's hooks included. Under graft the output is unchanged.

* fix(cloud): queue workspace activity only while connected, for workspace repos

Every trail ask/check that showed a learning appended the search text,
files and names to ~/.trail/outbox.jsonl even with no workspace
connected, and connecting sent all of it, for every repo, including
repos the person never picked.

recordActivity now writes only while this machine is connected and only
for a repo in the workspace, so nothing is queued with cloud features
off. Connecting empties the outbox first, and a send drops anything from
before the connection or for a repo outside the workspace (what an older
trail queued).

* fix(hooks): Cursor's and Codex's hooks speak trail in a repo wired for it

Their hooks run the same entry as Claude's, but the name check only looked
at .claude, so a repo with only Cursor or Codex on trail got graft's words.

* fix(init): the dry run lists a shared AGENTS.md once

* docs(readme): agent wiring outside the repo, as trail init writes it

* test: the handover check clears CI, where the line stays quiet by design

---------

Co-authored-by: Shrish Dwivedi <shrish@nanonets.com>
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