Concepts
Sessions and worktrees
How Duscode sessions work. Each has its own chat, git worktree, branch and preview port, is saved in the project, and is finished without losing work.
A session is one line of work with Dus: its own chat, plan, cost and, in a git project, its own copy of the code. You can run several sessions at once, for example one fixing a bug while another builds a feature.
Main and isolated sessions
| Main | New sessions in a git project | |
|---|---|---|
| Works in | Your project folder (the main checkout) | <project>/.worktrees/<name>, a git worktree |
| Branch | Whatever is checked out | duscode/<name>, created from your current commit |
| Can be finished | No | Yes |
| Merge from the workspace | — | Merge into your base branch |
Main is always at the top of the session list. It works directly in your project folder.
New session (in the sidebar, or Alt+N) creates an isolated session if the project is a git repository. In a folder without git, a new session shares the project folder with Main.
Isolated sessions are separate checkouts of the same repository. Dus can change files, install packages and run tests in one without touching your main checkout or the other sessions. Duscode hides .worktrees/ from git status through .git/info/exclude, so your .gitignore is left alone.
Names
A new session opens at once. Your first message gives it a name. The fast model then refines that name into a short title. While the session's branch has no commits of its own, the branch follows the name.
To rename a session, use Rename… in the session menu (click its title in the top bar, or right-click it in the sidebar). Names are cut to 60 characters, and main and master are reserved.
Live preview
Each session can run your app's dev server on its own port. The Preview tab shows it inside Duscode, so you see the session's changes live as Dus edits. See Live preview.
Saved across restarts
Duscode keeps each session in your project, in .duscode/sessions/:
| File | What it holds |
|---|---|
<id>.log.jsonl |
The whole session, in order: every message you sent, every reply, every tool call and its full result, every file edit, error and compaction. Duscode only ever adds to it. |
<id>.json |
A small snapshot (title, plan, cost, the latest part of the chat and Dus's current context) so the session opens quickly. |
<id>.recall.idx |
A search index of the log, rebuilt from the log if it goes missing. |
Everything is written as it happens, and a session's snapshot within about two seconds of any activity and when a task ends. Close Duscode, start it again, and pick up where you left off. A task that was running when Duscode stopped comes back as interrupted. If Duscode stops mid-write, at most the last line of the log is cut short, and Duscode ignores it.
Sessions saved by older versions of Duscode (one <id>.json file each) move into the log automatically the first time you open the project. Nothing in them is dropped.
Saved chats are personal and can quote code. Secrets from the vault are masked as [secret:NAME] before anything is written. Duscode adds /.duscode/sessions/ to .git/info/exclude in every repository where it saves a session, so the files stay out of git.
A session never forgets
A session keeps everything until you delete it.
- The whole chat. Scroll up and older messages load a page at a time, back to the session's first message. A quiet Earlier in this session marks the edge (click it, or keep scrolling); Start of this session shows when you reach the beginning. If a page can't load, Try again fetches it.
- Dus's context. A model can only read so much at once, so a long conversation is compacted. The older turns leave Dus's context, but not the log. Dus keeps a session brief at the top of its context. It lists your goals, what you said about how to work (preferences and constraints), decisions and their reasons, files touched and why, open problems, and what was tried and failed. Each compaction adds to the brief rather than replacing it. When the brief gets long, its oldest low-value lines drop out of it, but not out of the log.
- Recall. Dus can search the whole log with its
recall_sessiontool, by keywords, kind (your messages, its answers, tool results, file edits, errors), task and time. It reads earlier records word for word. It's told to recall before assuming what was said or done. Recall is read-only, so it works in every mode, Plan included. When you ask about another session, Dus can search the project's other sessions too. - Rewind anywhere. Rewind works on any of your messages, even ones from before a compaction. Duscode rebuilds Dus's context as it was at that point from the log, and puts the files back from the checkpoints.
Archiving a session keeps all of it: the log, the snapshot, the index and the undo checkpoints. Deleting a session (session menu → Delete…) is the only way to make Duscode forget it. It removes the log, snapshot, index and checkpoints, including archived copies.
A session's life
Every session moves through the same stages. The Projects dialog groups a project's sessions by them.
| Stage | What it means |
|---|---|
| Working | Dus is running a task. |
| Needs you | Dus is waiting for an approval or an answer, its checks failed, a requirement isn't met, or Finish stopped and says why. |
| In progress | Nothing is running and nothing is waiting. You can send the next message. |
| Done | The last task was verified by its checks, or you said Looks good. |
| Finishing | Finish is running: bringing the base branch in, testing, then merging or opening a pull request. |
| Finished | Merged into its base branch, or its pull request was opened. |
| Discarded | You threw its work away on purpose. |
| Archived | Hidden from the sidebar by you. |
Duscode tells you when a session becomes Done, Needs you or Finished, and when Finish fails, with the reason and the fix. These go to the bell, and to desktop, Slack or Teams if you turned them on (Settings → Integrations, the "A session is done, needs you, finished…" switch). Done and Needs you only go outward while you're away from Duscode.
Finishing a session
When a session is Done, a strip above the message box offers Finish…. You can also pick Finish… from the session menu at any time. Duscode first shows what it will do, then you choose:
- Bring the base branch in. The latest commits of the branch the session started from (usually
main) are merged into the session's branch, so the next step tests what the merge will produce. If they conflict, Dus resolves them as a task in the session. When its checks pass, Finish runs again by itself. If the conflicts come back, Finish stops and asks you instead. - Test end to end, on the merged result. Every check of the project runs in the session's worktree (the same commands as the verification gate). If the project has a preview, Duscode also loads the app in a headless browser and fails on a blank page or a page error.
- Merge or open a pull request. Choose Finish and merge into main or Finish and open pull request. Duscode remembers your choice for the project. Merging is done in your main checkout. It must be clean and on the base branch, and Duscode says so if it isn't.
- Clean up. After a merge, the session's worktree and branch are removed. After a pull request, they stay until the pull request is merged. Duscode checks with
gh(GitHub) orglab(GitLab) when you open the session list, and every ten minutes. Then it removes them.
The session stays in the list as Finished. Its chat, log and checkpoints are kept, and Dus can still recall them, but its files are gone. Opening it shows the chat with New session here in place of the message box.
If Finish stops, the strip says what happened and lists the steps to fix it. It offers Ask Dus to fix it and Finish again. Nothing is merged while a check fails.
A session with nothing to merge (no commits of its own) is offered Close session instead: its worktree goes, its branch and record stay.
Discard… (session menu) removes the worktree and branch without merging and keeps the record as Discarded. If there is unmerged work, Duscode lists it first and asks again.
Duscode never force-pushes, resets or stashes.
Cleanup
Worktrees take disk space, so Duscode removes the ones no longer needed. This happens when a project opens, every six hours, and when you press Clean up now in Project details. It removes the worktrees of Finished, Discarded and Archived sessions.
It never removes a worktree with work that exists nowhere else. That means uncommitted changes, or commits that are on no other branch and no remote. Those sessions show Has unmerged work in the Projects dialog, with Finish, and Project details lists them as kept, with the reason.
Sessions left idle for the days set in Settings → Sessions → Auto-archive are archived. If they have no changes of their own, their worktrees are cleaned too. Pinned sessions are never touched.
Project details shows how much disk space cleanup has given back.
Links to projects and sessions
Every project and session has a local link that keeps working after a restart:
| Link | Opens |
|---|---|
http://localhost:4317/code?p=<project> |
The project |
http://localhost:4317/code?p=<project>&s=<session> |
That session in the project |
http://localhost:4317/code?open=/path/to/folder |
A folder. If it isn't one of your projects yet, Duscode asks before adding it. |
Copy link is in the session menu, and in the Projects dialog for each project and each session. duscode open <folder> prints the project's link and opens it. Links only work on the computer running Duscode.
Sessions and git
Each isolated session is an ordinary git branch, so all your usual tools work on it. The Git dialog handles the common steps for you: review, commit, push, open a pull request, and merge after the checks pass. See Git, commits and pull requests.