Repository navigation
Releases
v0.8.0
What's Changed
- Split the README into docs/ for ws.fomin.space; license MIT OR Apache-2.0 by @anton-fomin in #5
- Release 0.8.0 by @anton-fomin in #6
Full Changelog: v0.7.0...v0.8.0
v0.7.0
What's Changed
- Install prebuilt releases on any Linux or macOS with install.sh by @anton-fomin in #1
- Document the agent skills setup by @anton-fomin in #2
- Launch a task into its own workspace with /ws by @anton-fomin in #4
Full Changelog: v0.6.0...v0.7.0
v0.6.0
v0.5.0
v0.4.1
v0.4.0
v0.3.0
A new branch now comes ready to work in: its dependencies are installed from the lockfile, starting from hard links to the node_modules of the branch you came from; your untracked local files are placed into it; and setup scripts can refer to the workspace and the environment. The configuration also moves to YAML, with settings shared globally.
Important
This release changes the configuration format. See Upgrading from 0.2.0 before you install it.
Highlights
Package managers: yarn, pnpm, npm and uv
Each one turns itself on when its program is on PATH, and only acts on repositories it recognises. For yarn, pnpm and npm, the packageManager field in package.json decides first, then the lockfile. uv is detected on its own, so a repo with a Python service and a web frontend gets both.
In every new worktree, the install follows the lockfile exactly. The same commit always gets the same dependencies, and an out-of-date lockfile is an error instead of being silently rewritten:
| runs | |
|---|---|
| yarn | yarn install --immutable, or --frozen-lockfile on yarn 1.x (asked per worktree, so corepack-pinned versions work) |
| pnpm | pnpm install --frozen-lockfile |
| npm | npm ci |
| uv | uv sync |
Before installing, yarn and pnpm seed node_modules with hard links from the branch you switched from, or from the default branch. Each file costs an inode rather than its bytes, and the frozen install then reconciles the seed with the new branch's lockfile. Symlinks are recreated as symlinks, so pnpm's store keeps working. Package-level node_modules in a monorepo come along too. npm doesn't seed by default, because npm ci deletes node_modules anyway. uv never seeds, because a virtualenv can't be moved.
A failed install prints a warning but the switch still completes: the session opens and you can fix it there.
Local files
Keep untracked files such as .env, editor settings or an .npmrc with a token in local/ next to the workspace. They are placed into every worktree. With one repository, everything in local/ is used. With several, local/<repo>/ goes to each repo's worktree. Ordered regex rules decide per path whether a file is symlinked, copied or hard-linked:
integrations:
local:
paths:
- { pattern: '\.env.*', mode: copy } # each branch gets its own copy
- { pattern: '.*', mode: link } # everything else is sharedFiles the repository tracks are never replaced. Placing runs on every switch, so files you add to local/ later reach existing worktrees too.
Setup scripts
setupcan be a multi-line script. It runs withsh -e, so a failing line stops it.- Placeholders:
{root},{branch},{branch_dir},{worktree},{repo},{env:NAME}and{env:NAME:-default}. Doubling the braces escapes one:{{env:X}}is passed on as the literal{env:X}. Other braces are never touched, so${HOME}and awk's'{print $1}'reach the shell unchanged. - The same values are exported as
WS_ROOT,WS_BRANCH,WS_BRANCH_DIR,WS_WORKTREEandWS_REPO. - Each worktree is set up in this order: local files, package managers, then
setup.
Branches
ws switch <branch> --from <ref>starts a new branch at a branch, tag or commit. The ref is checked against every repository before anything is created.- Without
--from, a new branch forks from the branch of the directory you are in, instead of from the base branch. - In a workspace with several repositories, each branch directory carries a small
.ws.yamlmarker recording its branch and where it started.ws statusshows that starting point.
Shell completion
ws completions bash|zsh|fish completes subcommands and flags, and also branch names: existing worktrees for rm and path, every branch for switch, and branches plus tags for --from. The Nix package installs the scripts.
Also new
- Global configuration in
~/.config/ws/config.yaml, written with every key documented byws init --global. A workspace'sws.yamlholds its repositories and overrides settings key by key.ws statuslists the files that were merged. - herdr opens one tab per repository by default.
layout: paneskeeps the old side-by-side layout. - The session name now defaults to
{workspace}/{branch}. ws statusshows which integrations are active on this machine.WS_YARN_CMD,WS_PNPM_CMD,WS_NPM_CMDandWS_UV_CMDoverride the launchers, likeWS_ZOXIDE_CMD.
Upgrading from 0.2.0
-
Rename
ws.tomltows.yamland convert it. Most keys are unchanged. The repository list[[repo]]becomesrepos::name: acme repos: - url: "git@github.com:org/api.git" setup: pnpm install
Settings you repeat in every workspace can go into
~/.config/ws/config.yaml. Runws init --globalto write one with every key documented. -
Move
zoxide:underintegrations:. A top-levelzoxide:key is now an error:integrations: zoxide: enabled: false
-
Drop
setup: pnpm install(or the yarn/npm equivalent) if you had one. The integration does the install itself, follows the lockfile, and runs beforesetup. Keeping it means installing twice. -
Expect one extra round of setup. The record of which setup commands already ran moves from
.ws/state.tomlto.ws/state.yamland is not migrated. Existing worktrees run theirsetuponce more on the next switch. Existing worktrees withoutnode_modulesalso get an install. -
Check
setupcommands that use;. Commands now run withsh -e, so a failing command stops the ones after it. Commands joined with||and&&behave as before. -
If you relied on the old defaults, set them back:
mux.session: "{workspace}-{branch}"andmux.herdr.layout: panes.
Install
nix profile add github:anton-fomin/ws/v0.3.0 # older Nix: nix profile install
or download ws-v0.3.0-x86_64-unknown-linux-gnu.tar.gz below, check it against SHA256SUMS, and put ws on your PATH.
Full Changelog: v0.2.0...v0.3.0
v0.2.0
Full Changelog: https://github.com/anton-fomin/ws/commits/v0.2.0