workspaces #
a session's workspace is the directory its python kernel, run jobs, memory,
skills and AGENTS.md resolve against. /cd in the tui moves a session to
another folder; the folder picker browses through the daemon, so it only ever
offers folders the daemon itself can see (and works the same once the daemon
is remote).
moving a session #
POST /sessions/:id/workspace {"workspace": "/abs/dir"} answers the session's
info. the session must be idle and the target an existing absolute directory.
the kernel is dropped (python variables start fresh), the transcript stays,
and a note records the move.
every descendant of the session (children, their children; open or closed) whose workspace was the same folder follows it. an idle descendant moves at once; a running one moves when its current turn ends. descendants that were working somewhere else keep their own folder. if the session itself cannot move, nobody moves.
browsing #
all three routes take path: absolute, or starting with ~, which expands
to the daemon's home. anything else is a 400; a path that is not an existing
directory is a 404. errors are {"error": "..."}. /health lists
workspace_browser when these routes exist.
GET /fs/list?path=P #
the directories directly inside P, for the picker's list.
{"path": "/Users/dawn/proj", "home": "/Users/dawn", "truncated": false,
"entries": [{"name": "albedo", "modified": 1790618149, "hidden": false, "vcs": "jj"}]}
pathis P expanded and normalised (no trailing slash, except/).- only directories, symlinks to directories included; sorted by name,
case-insensitively. at most 2000;
truncatedsays there were more. modifiedis the directory's mtime in unix seconds.hiddenis a leading dot. the picker hides these unless the query asks.vcsis"jj"when the entry itself contains.jj, else"git"when it contains.git(file or directory), elsenull. a stat, never a process.
GET /fs/repo?path=P #
the repository P is in, for list rows: {"repo": Repo | null}.
{"kind": "git", "root": "/Users/dawn/proj/tangled", "branch": "master",
"commit": "4fd0f30", "changed": 3, "touched": 1790610000}
{"kind": "jj", "root": "/Users/dawn/proj/albedo", "change": "nznu",
"bookmark": {"name": "main", "ahead": 2}, "changed": 1, "touched": 1790618150}
- the nearest enclosing root wins, walking up from P. at one level
.jjbeats.git: a colocated repo's git reports a detached HEAD. - git:
branchis null when HEAD is detached;commitis the short HEAD id, null in an unborn repo.changedcountsgit status --porcelain=v2entries, untracked included.touchedis the last commit's time. - jj:
changeis@'s shortest change id (at least 4 characters).bookmarkis the bookmark@works on and how many changes@is past the fork, the newest change in@'s history a bookmark contains (heads(::@ & ::bookmarks())), or null. the name is one at the fork itself, local or remote (a colocated repo'sname@gitcounts), else the newest bookmark that grew from the fork. the nearest bookmark behind@would often be an old backup of a bookmark that has since moved on.changedis the files@changes. jj runs with--ignore-working-copy, so browsing never snapshots or writes an operation:changedis as fresh as the last jj command. - every vcs command has a short deadline. a field whose command failed or
timed out is null;
kindandrootare always there.
GET /fs/preview?path=P #
everything the preview pane shows for P.
{"path": "/Users/dawn/proj/tangled", "repo": Repo,
"languages": [{"name": "Go", "color": "#00ADD8", "share": 0.71}],
"tree": [{"name": "spindle", "dir": true, "changed": 3, "more": 0,
"children": [{"name": "engine", "dir": true, "changed": 0}]},
{"name": "flake.nix", "dir": false, "language": "Nix", "changed": 0}],
"more": 11}
languages: the tracked files under P (git ls-files/jj file list), bytes per language, counting only linguist'sprogrammingandmarkuptypes, as github's language bar does. largest first, at most 4;shareis of all counted bytes. empty outside a repository.coloris linguist's own hex (or null): the tui adapts it to the terminal.tree: two levels. directories first, then files, each by name; dot entries left out. inside a repository only tracked or changed paths show, so build output and other ignored files stay out of the way. at most 12 top-level entries (morecounts the rest); a top-level directory lists at most 4 children (itsmorecounts the rest) and deeper directories list none.languagenames a file's linguist language, or null.changedcounts the changed files at or under an entry.- language data is github linguist's
languages.yml, shipped inpriv/linguist/and read once. a file is matched by exact filename, then by its longest extension. an extension several languages claim goes to a fixed ranking that favours linguist's popular languages and their primary extensions (popular.yml), so.mdis Markdown and.his C++. shareis unrounded.
the picker #
/cd opens it full screen; /cd <path> moves at once. an empty query lists
recent folders (the workspaces of your sessions, ranked by how often and how
recently they were used). typing a path lists that folder's directories,
filtered by the last segment. tab enters the highlighted folder, shift+tab goes
up, enter moves there, esc goes back. the same picker replaces the plain text
box shown when a session's workspace has gone missing.
in the sessions view, ctrl+f (or ~ or / typed into an empty search) opens
the same picker to browse sessions by folder: enter starts a new session in
the highlighted folder instead of moving one. in either mode → steps into the
highlighted folder's sessions, where enter opens one and ← goes back.
the preview keeps its sessions on screen: the tree fits around a third of the pane kept for them, showing fewer children per directory, then only the top level, then fewer top entries, and the sessions fill whatever the tree leaves.