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.

DetectedHow
Start commandnpm run dev, then npm start, then npm run serve — the first script that exists
PortA --port or PORT= in that script; failing that, 5173 for Vite, 3000 for Next or Create React App
Env profilesEvery .env and .env.* file, minus .example, .sample and .template
Clone URLgit 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.

TicketTitleBranch and directory
FD-12fix headerFD-12_fix_header
nonefix headerfix_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:

1

Create the git worktree on the new branch.

2

Link node_modules from the source worktree.

3

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.json files 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_modules directory. 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 remove refuses 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.

Where to go next