Skip to content

Juggle and resume sessions

You’re three turns deep into fixing feedmill’s Atom parser — the agent has read internal/parse/atom.go, you’ve approved one edit, and you’re about to look at the failing test — when the cron alert fires: a second feed is now coming back empty, and it’s a JSON feed, a completely different code path. Your instinct is to just type the new problem into the same prompt. Don’t. The thread you’re in is loaded with Atom context — the file the agent read, the plan it proposed, the half-applied fix — and pouring an unrelated JSON-feed investigation on top of it muddies both. The agent starts reasoning about one problem with the other’s context still in the window, and you lose the clean thread you’d want to come back to.

OpenCode keeps each line of work in its own session, and the whole point of living in the TUI is that switching between them is a two-key move — no terminal tabs, no losing your place.

Open the session list with the leader key followed by l — by default that’s ctrl+x l, which fires the /sessions command:

> [ctrl+x l]
╭─ Sessions ──────────────────────────────────────────────╮
│ ● fix atom parser dropping <updated> dates 2m ago │
│ onboard the hckrnews json feed 1h ago │
│ dedupe key collision on guid yesterday │
╰──────────────────────────────────────────────────────────╯

That list is every session in this project, most-recent first. Your Atom fix is sitting right there at the top, frozen exactly as you left it. But you don’t want to resume anything — you want a fresh thread for the JSON feed. Start a new session with ctrl+x n (the /new command), and you’re at an empty prompt with a clean context window:

> [ctrl+x n]
> the hckrnews json feed started returning an empty queue this morning.
it parsed fine last week. find out what changed.
• Read internal/parse/json.go, internal/feed/registry.go (2 files)
The JSON parser keys on `items[].id`, but this feed renamed that
field to `objectID` in a recent format change, so every item now
parses with an empty id and gets dropped as a duplicate of the last
empty-id item. I'll match both field names and add a test pinning
the new shape.

Now you have two live sessions: the Atom fix and the JSON investigation, each with only its own context. When the second one reaches a stopping point, ctrl+x l takes you straight back to the Atom thread, picking it up mid-fix exactly where you stepped away. No re-explaining, no cross-contamination. The session list is the difference between juggling two problems and tangling them.

Sessions outlive the terminal. When you close feedmill for the night, both threads are saved — and the next morning you don’t start cold. From the CLI, --continue (short -c) drops you back into the most recent session:

$ opencode --continue
↳ resuming "fix atom parser dropping <updated> dates"

That’s the right move when “yesterday’s work” means the last thing I touched. But the most recent session isn’t always the one you want — maybe you closed the laptop in the middle of the JSON feed but it’s the Atom fix you need to finish first. Point at a specific session by id with --session (short -s):

$ opencode session list
ID TITLE UPDATED
ses_8f2a… onboard the hckrnews json feed 14h ago
ses_3c91… fix atom parser dropping <updated> 15h ago
$ opencode --session ses_3c91 -c
↳ resuming "fix atom parser dropping <updated> dates"

opencode session is the CLI surface for managing sessions outside the TUI — opencode session list prints them, and it speaks --format json when you want to feed the list to a script rather than read it yourself:

$ opencode session list --format json
[
{ "id": "ses_8f2a…", "title": "onboard the hckrnews json feed", "updated": 1749… },
{ "id": "ses_3c91…", "title": "fix atom parser dropping <updated>", "updated": 1749… }
]

Resuming continues a thread in place — the session grows by one more turn. Sometimes that’s wrong: you’ve got a working context built up on the Atom parser and you want to try two fixes from that same starting point — tolerate the malformed <updated> dates, versus reject the feed outright and alert — without one experiment polluting the other. That’s --fork. Instead of continuing the session, it branches it: the accumulated context comes along, but the new turns grow in a separate thread, leaving the original untouched.

$ opencode --session ses_3c91 --fork
↳ forked from "fix atom parser dropping <updated> dates"
> instead of tolerating the bad dates, reject the whole feed and
log a warning. let's see how invasive that is.

Now you have two children of the same context, evolving independently. Try the strict approach in the fork; if it sprawls, you abandon that thread and the tolerant version in the original session is still sitting there, exactly as you left it. It’s the same logic as the git-floor habit applied to context instead of code: cheap to branch, so you can take a bigger swing knowing the original line is safe. --fork works with both --continue (fork the latest) and --session <id> (fork a specific one).

Two fires, two clean threads, both waiting for you tomorrow — and a way to branch either one when you’re not sure which approach wins. That’s the day-to-day rhythm of working in the TUI without losing your place.

Sessions pile up turns, and eventually a thread gets long enough that the context window starts to strain — or you make a change you wish you hadn’t. Next: undo, redo, and compaction.