Contents
Integrating 6diss with Claude
Step by step, two ways — and they are meant to be used together:
- A. The assistant inside 6diss talks to Claude while you work. Select a routine, get names and comments back as a checklist, tick what is right. Small questions, immediate answers, nothing applied until you say so.
- B. Claude Code beside 6diss works on the exported source or on the project file itself. Whole-file passes, cross-file reasoning, "find every place that writes the sprite pointers", scripted edits.
A is for the twenty seconds you would otherwise spend reading a loop. B is for the afternoon.
Both assume Claude Code is reading an export. It does not have to: 6diss listens on a Unix socket, so Claude Code can read the listing as the window is drawing it and apply names straight into the open project — one undo step, redrawn under your caret, nothing saved until you say so. See the control channel, and Step 3 below for where it fits.
And a third way, which is B without the second window: C. Claude Code inside 6diss — the whole CLI, hosted as a subprocess and drawn in a tab beside the listing.
A. The assistant inside 6diss
Step 1 — give it a credential
Three ways, best first:
1. ant auth login. The Anthropic CLI writes a credential to
~/.config/anthropic/credentials, and 6diss finds it with no configuration at all — leave
the key box in the settings dialog empty. Nothing lands in a 6diss file, and one login
serves every tool on the machine.
ant auth login
2. An environment variable. ANTHROPIC_API_KEY (or ANTHROPIC_AUTH_TOKEN) is picked up
the same way:
export ANTHROPIC_API_KEY=sk-ant-...
The catch is where you set it. A desktop launcher does not read your interactive shell's
.bashrc, so a 6diss started from the Cinnamon menu will not see a key exported there — put
it in ~/.profile (read at login), or use option 1, or option 3.
3. Paste it into the dialog. Assistant ▸ Provider settings ▸ API key. It is written
to ~/.config/6diss/settings.json in plain text, which is why it is third.
Step 2 — point 6diss at Claude
Assistant ▸ Provider settings:
| Field | |
|---|---|
| Provider | Anthropic |
| API key | leave blank unless you chose option 3 |
| Model | claude-opus-5 (the default) |
| Reasoning effort | low / medium / high / max — high is the default |
Effort is the cost dial. Naming an obvious loop does not need max; working out what a
compressed jump table is indexing does. Adaptive thinking is on either way — deciding what a
block of 6502 does is the sort of question that benefits from it.
Step 3 — check it took
Open the Assistant tab in the inspector. The top line reads:
Anthropic (claude-opus-5)
If it says — not configured (no API key found), none of the three credential routes
found anything; go back to step 1. If it says No provider configured, the dialog was
cancelled or Provider is still None.
Step 4 — the first pass
- Open a file and put the caret in a routine — or select a range.
- Ctrl+I (Assistant ▸ Analyse selection). A caret on a single line is widened to
the enclosing region, so "explain this" means "explain this routine" rather than "explain
this
lda". - The Assistant tab fills with a prose summary and a checklist: proposed labels, comments, region re-classifications and entry points, each with the reasoning that produced it.
- Untick anything wrong. Apply ticked suggestions.
- Ctrl+Z takes the whole application back as one step.
What lands in the project is tagged as machine-written: assistant labels are shown in teal
in the Labels list, assistant comments are prefixed [ai] in the listing. Six months later
you can still tell what you worked out from what a model suggested.
Step 5 — the whole-file data pass
Assistant ▸ Classify unknown data sends every still-unclassified run in the file with a hex sample of each (the head of every run, plus the tail of the long ones, up to 24 runs) and asks what they are. This is the pass to run after Ctrl+T (the local detector) has taken the easy ones — sizes and alignments are evidence a heuristic uses well, but "this is a SID player's frequency table" needs to have seen a SID player before.
Step 6 — ask it something
Assistant ▸ Ask a question takes free-form text and gives prose back, with the same listing window attached. "What is the table at $2000 indexed by?" "Why does this write $3B to $D011 twice?" Nothing to apply — it goes in the summary pane.
What actually gets sent
Worth knowing before you point it at someone's unreleased disk:
- The rendered listing for the selected range, plus twelve lines either side, capped at 400 lines — the same text you are reading, with the knowledgebase's annotations and the xref lists in it.
- The file's geometry: name, module, load and end address, file type, packer, entry points, your notes.
- The address ranges of the other files in the project — names and ranges only, not their bytes.
- The documented hardware locations the selection touches, with descriptions.
Nothing else. Other files' contents, the disk image, and the rest of the project stay on the machine.
When it declines
Reverse engineering sits close enough to what safety classifiers watch that a request is occasionally refused outright. 6diss reports that as "The model declined this request" with whatever explanation came back, rather than as an error. Re-asking about a narrower range, or asking what the code does rather than how to defeat it, usually gets through.
Instead of Claude: a local model
Provider ▸ Local talks to anything with an OpenAI-compatible endpoint — LM Studio
(http://localhost:1234/v1), Ollama (:11434/v1), llama.cpp, vLLM. List models from this
endpoint proves the connection before you spend an analysis on finding out it was wrong.
Nothing leaves the machine. Expect to untick more.
B. Claude Code beside 6diss
The assistant answers questions about a window of listing. Claude Code can read the whole project, run the assembler, drive an emulator, and write files. The bridge between them is the export.
Step 1 — export the project as source
File ▸ Export project as 6asm source…, pick a directory, and choose Readable (the
byte-identical mode's .byte escapes are for verifying a rebuild, not for reading). You get:
LOADER.asm one per binary
MAIN.asm
MAIN.exports.asm generated, for cross-file labels
MUSIC.bas a file marked "disassemble as BASIC source"
c64.equates.asm every hardware name the disassembly used
build.sh reassembles the lot
Step 2 — point Claude Code at it
cd /path/to/the/export
claude
Everything it needs to reason is in the text: runtime addresses in the comments, hardware
named, cross-file references as MAIN__init. Useful opening asks:
- "Read MAIN.asm and tell me what the routine at $C000 does — it runs from an IRQ."
- "Which routines write to the sprite pointers at $07F8-$07FF?"
- "Propose names for every
sub_label in MAIN.asm. Output a two-column list of address and name, nothing else." - "
build.shfails at line 40 of MUSIC.asm — why?"
Ask for the answer in a shape you can act on. Two columns of address and name is thirty seconds of typing back into 6diss; four paragraphs of prose is not.
Step 3 — get the answers back into the project
Four routes, cheapest first.
Over the control channel. The best one, and the reason the other three are shorter than
they were. 6dcli --live rename MAIN '$c000=irq_handler:raster split at $30' … applies a
whole batch into the running window as a single undo step, with the project open in front of
you. Nothing is written to disk, nothing races your next Ctrl+S, and a batch you dislike is
one Ctrl+Z. See control-channel.md.
By hand. For a dozen names: Ctrl+G the address, N, type the name. Fast enough that
anything more elaborate is procrastination.
Through the assistant. Paste Claude Code's reasoning into Assistant ▸ Ask a question as context for a narrower ask, and take the checklist. You get the review UI and the single-step undo for free.
By editing the project file. A .6diss is one JSON file — deliberately, so it is
diffable and hand-editable. Labels and comments are plain arrays:
{
"items": [{
"module": "MAIN",
"loadAddress": 49152,
"data": "…base64…", // the bytes; leave alone
"labels": [
{ "address": 49152, "name": "irq_handler", "role": "Sub",
"origin": "Assistant", "exported": true, "comment": "raster split at $30" }
],
"annotations": [
{ "address": 49155, "text": "acknowledge the raster IRQ", "inline": true,
"fromAssistant": true }
],
"regions": [
{ "start": 51200, "end": 51711, "kind": "Charset" }
],
"entryPoints": [49152],
"breaks": [51712]
}]
}
Addresses are decimal in the file and hex in the UI. role is Sub / Loc / Data;
origin is Auto / User / Assistant — write Assistant for anything a model produced,
and Auto labels are the ones a re-trace is free to throw away. kind is any of the region
kinds in the manual.
Two rules: close the project in 6diss first (it writes the whole file on save and will overwrite you), and keep a copy — there is no undo across a hand edit. Both are reasons to reach for the control channel instead, which has neither problem.
Step 4 — and then check you were right
Static reading is a hypothesis. build.sh reassembles the export and cmps it against the
original bytes, which proves the disassembly is complete; running it proves the reading
was correct. If you have the VICE MCP server wired into Claude Code, the last step of a
session is usually "set a breakpoint at irq_handler and tell me what the registers are
when it fires" — and a label that turns out to be wrong is one M and one N away from
being right.
C. Claude Code inside 6diss
Assistant ▸ Claude Code in a tab. The same Claude Code as B — your account, your MCP
servers, your skills, bash and all — running as a child process of 6diss and drawn in the
editor tab strip beside the listing. No second window, no export to point it at, and the
6diss MCP tools reach the window it is being read in: a name it applies lands in the
listing under your caret as one undo step.
What you need
Claude Code itself, found in this order: the ClaudeBinary setting, claude on PATH,
~/.claude/local/claude, then the self-contained binary the VS Code extension unpacks. On a
machine with the extension installed, that is nothing to do.
6diss-mcp on PATH, or beside 6diss. Without it the tab still
works, but the conversation cannot see the project; it says so at the top of the transcript
rather than finding out the hard way.
Settings
Assistant ▸ Provider settings has a Claude Code section at the bottom, separate from the provider above it because the two share nothing:
| Claude Code executable | blank finds it automatically; the line underneath says which one it found and its version |
| Model for the tab | blank leaves whatever your Claude Code is already set to — opus, sonnet, haiku, or a full model id |
| Permissions | manual (asks in the tab), acceptEdits, plan, auto, bypassPermissions |
There is no API key here, and the tab never asks for one. It runs the CLI on your own Claude Code login — the same subscription, MCP servers and skills you get in a terminal. The API key in the section above belongs to the in-window assistant (A), which is a different thing entirely.
Which is worth saying because of the number after each turn. The CLI reports
total_cost_usd on every turn whether or not anything is being billed; on a subscription it
is what those tokens would have cost at API list price. 6diss shows tokens instead, and only
prints a dollar figure when the session really is running on an API key.
How it behaves
- It asks first. Permissions are
manual: a tool that needs approval stops and shows you the call and its arguments, with Allow and Deny, in the transcript. What counts as needing approval is your own Claude Code configuration — the tab does not second-guess it. - It runs in the project's directory, so the export, the disk image and your notes are all just there. Save the project first; an unsaved one has no directory and the tab will tell you it fell back to 6diss's own.
- It remembers. One conversation per project, resumed when you reopen the tab.
Restart in the tab's header respawns the CLI and picks the same conversation back up —
that is how a changed setting or a freshly installed
6diss-mcptakes effect. New throws the conversation away and starts an empty one; the old transcript stays under~/.claudewhereclaude --resumecan still reach it. - Slash commands work. Type them into the message box:
/compactwhen the context is full,/clearto empty the conversation without respawning,/context,/model,/usage. They are handled by the CLI before the model sees them, exactly as in a terminal. - It sees only the MCP servers 6diss hands it. The tab is for the open project, so it
gets
6dissand nothing else — not the mail connector, not the lighting rig. Name the ones you do want inClaudeExtraMcpServersin~/.config/6diss/settings.jsonand they are pulled through from your own Claude Code configuration by name, sovicestays configured in one place:
json
{ "ClaudeExtraMcpServers": ["vice", "goattracker"] }
Set "ClaudeStrictMcp": false to go back to the CLI's own idea of which servers exist.
Either way the header note in the transcript says which ones it ended up with. Skills,
CLAUDE.md and your permission rules are always your own — only the server list is
narrowed.
- It zooms. Ctrl+wheel over the transcript, or Ctrl +/- with the tab in front — the same
chords the listing uses, acting on whatever you are looking at, and Ctrl+0 puts it back.
It scales rather than resets to one size, so the ladder that separates Claude's prose from
tool calls from tool output survives. The zoom sticks between sessions.
- Nothing is saved until you save it. Same as every other route into the project: edits
land in the open window, Ctrl+Z takes them back, Ctrl+S is still yours to press.
Worth asking it
Anything you would ask in a terminal, plus the window:
- "Read LIBRARY's jump table at $2DC8 and name the 32 vectors — apply them."
- "Which files write to $D018? Check all of them, not just the one that's open."
- "Set a breakpoint at irq_handler in VICE, run to it, and tell me what A holds."
- "Export the project, run build.sh, and tell me which file doesn't reassemble."
- "Write up what we worked out about the character record as a note."
Where the findings go
Labels and comments hold conclusions; they cannot hold reasoning. "The record is 0x244 bytes, the first fifteen are the name in PETSCII, and the two saved games disagree about byte +$1C" does not fit in a label, and before there was anywhere to put it, it went into the conversation and left with it.
It now goes in a note — a real .md file in <project>.docs/ beside the project,
listed under Notes in the tree and opened in a tab beside the listing. Four tools:
list_docs |
every note, with its path — worth calling early, a previous session may have written down the thing you are about to spend an hour on |
read_doc |
one note, including unsaved edits in the tab |
write_doc |
write or append to one, creating it if there is none of that name |
open_doc |
put it in front of the user, because "I wrote it up" is not the same as showing them |
Two things follow from the notes being ordinary files. The tab watches its file, so a note
appears as it is written rather than when the conversation ends — worth an open_doc
before a long write-up. And a session with file tools can read and edit the .md directly
instead; the paths in list_docs are there for that. What the MCP tools add is the
window: a write through them lands in the open tab and in the tree straight away.
Hex addresses in a note are drawn as links the user can click to put the listing on them,
so write $9e40 rather than "the table at 9e40". Notes are the one thing here that Ctrl+Z
does not take back — they are files, not project decisions.
What it is not, yet
A plain transcript: no markdown, no folded tool output, no diffs. The conversation is inside 6diss with its permissions intact, which was the hard part.
Which one, when
| Assistant in 6diss | Claude Code beside | Claude Code inside | |
|---|---|---|---|
| One routine, right now | ✅ | ✅ | |
| "What is all this data?" | ✅ (whole-file pass) | ✅ | ✅ |
| Reasoning across every file on the disk | ✅ | ✅ | |
| Reading the code and the emulator | ✅ | ✅ | |
| Reviewable, one-click undo | ✅ | ✅ (control channel) | ✅ |
| Editing files, running builds | ✅ | ✅ | |
| Without leaving the window | ✅ | ✅ | |
| A terminal you can pipe and script | ✅ |
The design rule is the same either way, and it is worth stating plainly: the model is a
fast second reader, not an authority. Everything it proposes arrives as something to
accept or reject, tagged with where it came from, and one Ctrl+Z from gone.