Repos and worktrees
A repo is a git checkout you register with a workspace. A worktree is a git worktree of that repo: one branch, one directory, one dev-server port, one set of sessions. Most of Strado is machinery around that pair.
Adding a repo
Give Strado a path to a checkout and it derives the rest. It finds the git
root, reads package.json for a name and a start command, guesses the
dev-server port, reads origin's clone URL, and lists the .env files it
finds as environment profiles. You review a prefilled form instead of typing
one.
| Detected | How |
|---|---|
| Start command | npm run dev, then npm start, then npm run serve — the first script that exists |
| Port | A --port or PORT= in that script; failing that, 5173 for Vite, 3000 for Next or Create React App |
| Env profiles | Every .env and .env.* file, minus .example, .sample and .template |
| Clone URL | git remote get-url origin, or nothing for a repo with no remote |
In the desktop app you can pick the folder rather than paste its path. You can also add a repo by clone URL, which clones it onto whichever machine is running the server and then registers it — that is how a repo gets onto a runner without you SSHing in.
Where worktrees live
By default, a repo's worktrees go in a sibling directory named after it: a repo
at ~/code/acme gets ~/code/acme.worktrees. Strado creates it the first time
it needs it.
Heads up
This is a layout convention the app relies on. Ownership checks, deletion and
node_modules linking all resolve a path against the repo's own directory
and its worktrees directory — anything outside both is refused. Move
worktrees by changing the setting, never by moving directories on disk: git
records a worktree by absolute path.
There are two escape hatches. A workspace can set a worktree root, in which
case new worktrees go to <root>/<repoId> instead of beside each repo. And a
single repo's worktrees directory stays editable for the cases neither default
fits — a repo on another volume, say. Both only affect worktrees created after
the change.
Creating a worktree
From the + that appears next to a repo in the sidebar on hover, or that
repo's kebab menu. You give a title and, optionally, a ticket id; those become
both the branch name and the directory name, joined with an underscore and
stripped of anything git would object to.
| Ticket | Title | Branch and directory |
|---|---|---|
FD-12 | fix header | FD-12_fix_header |
| none | fix header | fix_header |
You also choose the branch it starts from, and the worktree whose
node_modules it should link. Both default to the repo's main worktree.
Creation runs as a job with named steps, so you watch it rather than a spinner:
Create the git worktree on the new branch.
Link node_modules from the source worktree.
Finalize — record the worktree, reserve a dev-server port, store its environment.
The port is the repo's default, moved up past ports other worktrees have already reserved, unless the repo is pinned to a fixed port.
Adopting an existing worktree
A worktree that git knows about but Strado does not still shows up on the
board, marked untracked. It has no ticket, no title, no port and no settings
until you adopt it: open its settings, give it a ticket id and a title, and it
becomes an ordinary row.
A repo's own main worktree is adopted for you the moment the repo is registered. Strado owns the repo, so it owns the repo's primary worktree.
Linking node_modules
Linking replaces a worktree's node_modules with a symlink to another
worktree's, so a new branch is usable immediately instead of after a full
install. Link, relink and unlink all live in the worktree's settings.
Three behaviours worth knowing:
- If the target already has a
node_modules, linking refuses unless you ask it to replace, in which case the existing directory is renamed aside rather than deleted. - After linking, the two
package-lock.jsonfiles are compared. A mismatch is reported as a warning — the link still happens, but the dependencies are not the ones this branch declares. - Unlinking refuses to remove a real
node_modulesdirectory. It only ever removes a symlink.
On the board, a worktree with neither a linked nor an installed node_modules
carries an unlinked badge.
Deleting a worktree
Deletion is a job too, with three steps: stop this worktree's processes and
kill its terminal sessions, unlink node_modules, then remove the git
worktree.
Two checkboxes:
- Force — needed when the worktree has uncommitted changes, because
git worktree removerefuses otherwise. - Also delete branch — off by default. Removing a worktree leaves its branch behind; this deletes it as well.
Everything Strado knows about the path goes with it: its state entry, its tracked time, its activity watcher.