Vectrum
Sign In
79 lines · 4.6 KB

Tabs, worktrees and sessions

ctrl+t — or /new — opens a second conversation in a tab. A tab is a whole session: its own agent, its own history, its own approvals, its own subagents and its own file under .codey/sessions. Nothing crosses between them but the model you are on and the terminal they share, so a turn running in one tab is not interrupted, approved or compacted by anything you do in another.

1 ◍ fix the parser  2 ● read the spec  3 new session

The strip appears when there is more than one tab and goes away when there is not: a single session looks exactly as it did before, down to the row count. A tab is named after the first thing asked of it. ◍ means something is running in there; ● means it said something while you were somewhere else.

A new tab starts in the working root of the one you opened it from, so a second conversation about a worktree is in that worktree. alt+w or /close closes a tab — it refuses while something is still running there, and closing the last one leaves Codey.

/worktree branches the work off into a git worktree under ~/.config/codey/worktrees. It reads its argument three ways, and which one you get is visible in what you typed:

/worktree dark-mode                 a name — made and moved into, nothing else
/worktree add a dark mode toggle    a task — named for you, then started on
/worktree resume                    a chooser of the trees that already exist

One word is a name and is used as typed, so the quick case never waits on a network call. A phrase is a description of the work: a small model turns it into a name, the tree is made, and the agent is then set to work on it in the new directory. Whatever the model answers is slugified and bounded before it reaches the filesystem, and if the naming call fails the task's own opening words are used instead — a name is not worth failing the command over.

The tree is made by ~/.config/codey/worktree.sh, which is written once with a default and is yours to edit afterwards. Codey never overwrites it, so a script taught to copy a .env or install dependencies keeps doing so. The contract is two lines wide: the name arrives on stdin, and the absolute path of the tree is the last line of stdout. The script decides where the tree lands, so moving them somewhere else is an edit to that file and nothing more.

What moves is the work — what the tools read and write, where ! commands run, and where subagents are spawned. What stays is the session: the conversation is still filed in the checkout you started in, alongside the event log, so one directory holds the whole history of what was done from it rather than a trail scattered across worktrees. The tree is recorded in the session, so reopening that conversation — with /resume or -resume — puts the work back in it. If the tree has since been deleted, Codey says so and carries on in the main checkout.

/worktree resume goes the other way: into a tree that already exists, with a new chat in it. Bare, it opens a chooser of every worktree this repository has — git is asked, so a tree the script put somewhere unusual is still found — most recently touched first, with the branch checked out in each. Typing narrows the list: the match is fuzzy, so dkmd finds dark-mode, and a branch name finds its tree too. /worktree resume <name> skips the chooser.

The checkout you started Codey in is offered alongside the trees, marked as such, because once the work has moved there has to be a way back. What you get in the tree is a new conversation, not the old one: the chat on screen is saved first and stays where it is, and the next turn is filed under a new session that records the tree — so /resume can go back to either. Reach for /worktree resume when you want to work in a tree again, and for /resume when you want a particular conversation back.

/resume switches to an earlier conversation without leaving Codey. Bare, it opens a chooser: one row per saved session, named by the first thing you asked it, newest first, with how long ago it was and what it ran on. /resume <id> goes straight there. Either way the conversation on screen is written out first, the chosen one is replayed into the transcript, and the next turn saves into it.

The list is scoped to the working root, and so is -resume: a session recorded in /home/joni/test cannot be opened from /home/joni/test2. Sessions are filed under the root they were made in to begin with, and the root each one records is checked again on the way out, so a session file copied between checkouts is refused rather than resumed into a tree where none of the paths it discusses exist.