hi amp, how's it going?
hi!
Hey! Going well, thanks 😊 How can I help you today?
okay, can you get a sense of how this project works? we're gonna create a new adapter for amp, using amp :)
Let me explore the project to understand the architecture, especially around adapters!
Now let me look at an existing adapter and the registry to understand the full pattern:
Now let me look at the Claude Code adapter as a reference, and check where Amp stores its session data:
Now let me find out where Amp stores its thread/session data:
Now I have a great picture of the project. Here's what I've learned:
Amp stores data at ~/.local/share/amp/:
history.jsonl — one line per user prompt with text and cwdthreads/T-{uuid}.json — full thread JSON with messages (user, assistant), tool calls, thinking blocks, model info, timestamps, usage statssession.json — current session state (last thread ID, agent mode)To build the adapter, we need to:
'amp' to AgentId in packages/shared/src/agent.ts and cli/src/types.tsamp storage path in cli/src/config.tscli/src/adapters/amp/v1.ts — parse the thread JSON files + history.jsonlcli/src/adapters/index.tsThe thread JSON format is rich — messages have role, content arrays with text, thinking, and tool_use blocks, plus usage with model info. Very similar structure to Claude Code's format, which makes mapping to TraceEvent types straightforward.
Ready to start building it! Want me to go ahead?
Let's create a worktree and project file (see others in @docs/projects ) and let's go!
Now let me create the worktree and project file:
Worktree is ready. Now let me look at an example project file for format reference, then create ours:
Now let me look at the Amp thread JSON format more closely to understand what we're parsing:
Now let me check the tool_result format and the history.jsonl format:
Oh, sorry to interrupt, but you should study the adapter interface and probably create a stub with failing tests, and then proceed. If that's what you had planned, sorry for interrupting, but just wanted to clarify.
No worries, that's exactly the right approach! Let me look at existing tests for the pattern, then create the project file + stub + failing tests.
Now let me check the test helper and the fixture directory structure:
Now I have everything I need. Let me look at the Pi adapter too since it's the newest and likely the cleanest pattern to follow (it also reads JSON files like Amp):
Now I have all the context. Let me create everything in the worktree — project file, fixture, stub adapter, and failing tests:
Now let me create the fixture, stub adapter, register it, and write failing tests — all in the worktree:
Now create the empty thread fixture (edge case):
Now add the history.jsonl fixture:
Now update types and config, create the stub adapter, and register it:
Now create the stub adapter:
Now register it:
Now build shared types and add the Amp adapter to the test file:
Now add the Amp adapter to the test file — add the import and fixture-backed adapter:
Now let's also add a background fixture for the Amp adapter. Let me check the existing pattern at the bottom of the backgroundFixtures object:
Now let's add the amp background fixture. Let me find the closing bracket of backgroundFixtures:
Now let's run the tests to see them fail:
9 failing tests against the stub, exactly as expected. All existing tests still pass. Here's the summary:
Created in the feat/amp-adapter worktree:
docs/projects/amp-adapter.md — Project plan with phasespackages/shared/src/agent.ts — Added 'amp' to AgentIdcli/src/types.ts — Added 'amp' to CLI AgentIdcli/src/config.ts — Added amp storage path (~/.local/share/amp)cli/src/adapters/amp/v1.ts — Stub adapter with TODO implementationscli/src/adapters/index.ts — Registered AmpAdaptercli/test/fixture/amp/ — Fixtures (normal thread with tool calls/thinking, empty thread, history.jsonl)cli/test/core/adapters.test.ts — Added Amp to adapter contract tests + background fixtures9 tests failing against the stub — ready to implement. Want me to start filling in the adapter?
Yep! Also, make sure you're staging changes in incremental, reversible commits
Let me commit the foundation first, then implement and commit incrementally.
Good, 3 clean commits. Now let me implement the adapter:
Now let's run the tests:
All 133 tests pass, including all 9 Amp adapter tests. Let me also run the full CLI test suite to be safe:
The one failure is a pre-existing flaky OpenCode test, not related to our changes. Let me verify:
Confirmed — that test fails on main too. Not our issue. Let me commit the implementation:
Done! 4 incremental, reversible commits:
'amp' AgentId and storage pathThe adapter handles all Amp content block types (text, thinking, tool_use, tool_result), extracts model info, supports getCurrentTraceHint via session.json, and has live subscribe via fs.watch. Ready for manual testing or PR!
Okay awesome. How is the amp adapter different than others? How does amp store sessions differently, and perhaps, how should we modiy our frontend to make sure things like interruptions, attachments and other transforms are correctly handled?
Good. Now I have the full picture. Let me implement all the changes across the worktree. I'll do this in parallel tasks:
Let me check the TUI theme and then implement everything together.
Yeah for sure. Let's complete the adapter, and are there any new tests you think we should add here for amp?
Great question. Let me dig into the Amp format differences and the frontend rendering pipeline.
Now let me check what Amp-specific content blocks look like that differ from Claude Code — especially interruptions, images/attachments, and the tool_result structure:
Now I have the full picture. Here's how Amp differs and what it means for the frontend:
1. Single JSON file per thread (not JSONL)
Other adapters use JSONL (one event per line) or SQLite. Amp uses a single threads/T-{uuid}.json with a messages array — the whole file is rewritten on each update. This means we parse the entire file each time (no tail-scanning optimization like Claude Code).
2. Rich tool_result structure
Claude Code tool results are simple content blocks. Amp wraps them in { run: { status, result, progress } } with structured result objects (not just strings). Our adapter serializes run.result to JSON, which works but means the frontend sees JSON blobs rather than pre-formatted output.
3. Interruptions are state.type: "cancelled" or "streaming"
Claude Code marks interruptions with a [Request interrupted by user] text message. Amp uses:
state.type: "cancelled" on assistant messagesstate.type: "streaming" for in-progress (thread read while still running)tool_result blocks with run.status: "cancelled"The frontend's isInterruptionMessage() only checks for Claude Code's [Request interrupted...] pattern and OpenCode's (no error message) error parts — it won't detect Amp interruptions.
4. Rich env metadata
Amp stores detailed environment info: git repo URL, branch, SHA, OS, CPU architecture, client version, and workspace tree URIs. Other adapters just store a project path string. We could surface this richer context.
5. No toolName on tool results
Amp's tool_result blocks don't include the tool name — only the toolUseID. Our adapter currently emits toolName: '' for results. The frontend's ToolCallRouter matches results to calls by callId, so this works, but tools that key off toolName in the result might show fallback rendering.
| Issue | Impact | Fix |
|---|---|---|
| Interruptions invisible | Amp cancelled turns show as blank/empty messages | Add Amp's cancelled state detection to adapter (emit an error event) or teach frontend about it |
| Tool result is JSON blob | Read/Edit results show as raw {"absolutePath":..., "content":...} instead of formatted output | Frontend's parseRawResult already handles JSON with contents field (Cursor format) — could extend to handle Amp's result.content field |
| No agent color | getAgentColor('amp') returns the default muted color | Add an Amp-specific color to the theme |
| Streaming threads | Active threads have state.type: "streaming" messages with incomplete content | Adapter should skip or handle these gracefully |
The most impactful quick wins would be handling interruptions in the adapter and adding an agent color. Want me to tackle any of these?
All 141 tests pass (9 original + 8 new Amp-specific = 17 Amp tests total). Let me also run the full suite:
Good. Now I have the full picture. Let me implement all the changes across the worktree. I'll do this in parallel tasks:
All three tasks done. Let me verify everything passes:
554 pass, 0 fail (even the flaky OpenCode test passed this time). Now let me commit incrementally: