Tern LogoTern

Catch code drift.

You asked for one thing. The agent shipped it. Probably.

Read the docs
Tours

Read what your AI just built.

Tours walk you through the code your agent just generated. Tern mines your Claude Code logs and markdown plans, then attaches each change to the prompt or plan that asked for it. Code with no match? Left unattached. Draw your own conclusions.

ternhq/tern#2685Ship the PR-review tour on the web25 files +2776 −998
0
OVERVIEW
About this PR
1
CLI ENTRY POINT
New tern pr-review command launches the browser-based tour
2 directives
2
AGENT ENDPOINTS
Local agent proxies GitHub PR metadata and generates commit tours
1 directive
3
APP-SERVER PERSISTENCE
CRUD endpoints and SQL queries for commit tour records
no directive
4
FRONTEND DATA LAYER
React Query hooks and service functions wire the page to agent + server
1 directive
5
REVIEW PAGE UI
PR review page with tour rail, scroll tracking, and diff stream
1 directive
1New tern pr-review command launches the browser-based tourcli entry point
Directives that shaped this stop
  • Add a `tern pr-review` subcommand that opens a browser-based tour for a GitHub PR.(session 7a2b9c4f#4)
    What the user said
    Add a `tern pr-review` subcommand. It should take a GitHub PR URL, resolve my org, and open the review page in the browser.
    Context
    • [assistant #3]I can wire this as a new top-level cobra command. Should the org be inferred from the current repo or passed explicitly?
  • Use exec.Cmd.Run instead of Start so the URL handler exits cleanly.(session 7a2b9c4f#12)
cmd/tern-agent/cmd_auth.go
388 return fmt.Errorf("unsupported platform")
389 }
390
391 return cmd.Start()
391+ // Run (not Start): the URL handlers all
392+ // exit quickly after handing off to the OS.
393+ return cmd.Run()
394 }

From agent stop to tour in thirty seconds.

1Claude finishes.

The agent says it's done. You have to check.

Your agent shipped a PR. 23 files, +614 lines. The summary at the top says it's done.

"Done" is the agent's word. The diff is the record. Did the second thing actually do what the first thing asked for?

The summary won't tell you. The diff would, but reading 23 files of unfamiliar code is the part everyone skips.

claude ~/repos/tern
> Add OAuth login. Use the same session middleware we use elsewhere.
● Adding OAuth login flow.
Edited src/auth/oauth.ts (+182)
Edited src/auth/callback.ts (+74)
Edited src/middleware/session.ts (+12 −3)
Added tests/oauth.test.ts (+118)
…17 more files
✓ Done.
Summary
• OAuth login flow + GitHub provider
• Callback handler, session wiring
• Token storage refactored
• Tests + fixtures
23 files changed +614 −47
2You /tour from Claude Code.

One slash command. Tern does the mining.

/tour, from inside the Claude Code session you ran the work in. Tern reads your recent Claude Code logs and any markdown plans in the repo.

It pulls out the directives you typed and matches each one against the changed files. Six stops: five with matching directives, one without.

claude ~/repos/tern
23 files changed +614 −47
/tour
▶ Reading Claude Code logs (4 sessions, 11 prompts)
▶ Reading plans/oauth.md
▶ Matching changes to directives…
6 stops · 5 with directives · 1 without
↳ src/admin/legacy_session.ts: no directive found
▶ Opening browser →
https://app.tern.sh/tours/8f3a…
3Tern reads it with you.

Read by intent, not by file.

The tour opens in your browser. Each stop is one group of changes — the OAuth flow, the session wiring, the test fixtures — with the directive that asked for it quoted at the top.

You're not scrolling 23 files of unfamiliar code. You're reading six directives, each followed by the code that did it. When the code matches the directive, you move on. When it doesn't, you don't.

app.tern.sh/tours/8f3a…
1CLI entry point
cmd/tern-agent/cmd_pr_review.go:16–91
16+func mkPRReview() *cobra.Command {
17+ var orgSlug string
18+ cmd := &cobra.Command{
19+ Use: "pr-review <url>",
20+ Short: "Open a PR review tour",

Install Tern.

30 seconds. No email. No code leaves your machine.