Skip to content

Releases

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 05 Nov 15:37
v0.8.0
6b17550

What's Changed

Full Changelog: v0.7.0...v0.8.0

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 04 Nov 07:49
v0.7.0
79cb5c9

What's Changed

Full Changelog: v0.6.0...v0.7.0

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 30 Oct 10:39
v0.6.0
ea981ea

Full Changelog: v0.5.0...v0.6.0

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 30 Oct 10:30
v0.5.0
0aa867c

Full Changelog: v0.4.1...v0.5.0

v0.4.1

Choose a tag to compare

@github-actions github-actions released this 21 Oct 19:43
v0.4.1
9f6bd1f

Full Changelog: v0.4.0...v0.4.1

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 21 Oct 19:08
v0.4.0
d82a1a8

Full Changelog: v0.3.0...v0.4.0

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 20 Oct 18:00
v0.3.0
749118d

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 shared

Files the repository tracks are never replaced. Placing runs on every switch, so files you add to local/ later reach existing worktrees too.

Setup scripts

  • setup can be a multi-line script. It runs with sh -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_WORKTREE and WS_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.yaml marker recording its branch and where it started. ws status shows 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 by ws init --global. A workspace's ws.yaml holds its repositories and overrides settings key by key. ws status lists the files that were merged.
  • herdr opens one tab per repository by default. layout: panes keeps the old side-by-side layout.
  • The session name now defaults to {workspace}/{branch}.
  • ws status shows which integrations are active on this machine.
  • WS_YARN_CMD, WS_PNPM_CMD, WS_NPM_CMD and WS_UV_CMD override the launchers, like WS_ZOXIDE_CMD.

Upgrading from 0.2.0

  1. Rename ws.toml to ws.yaml and convert it. Most keys are unchanged. The repository list [[repo]] becomes repos::

    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. Run ws init --global to write one with every key documented.

  2. Move zoxide: under integrations:. A top-level zoxide: key is now an error:

    integrations:
      zoxide:
        enabled: false
  3. Drop setup: pnpm install (or the yarn/npm equivalent) if you had one. The integration does the install itself, follows the lockfile, and runs before setup. Keeping it means installing twice.

  4. Expect one extra round of setup. The record of which setup commands already ran moves from .ws/state.toml to .ws/state.yaml and is not migrated. Existing worktrees run their setup once more on the next switch. Existing worktrees without node_modules also get an install.

  5. Check setup commands that use ;. Commands now run with sh -e, so a failing command stops the ones after it. Commands joined with || and && behave as before.

  6. If you relied on the old defaults, set them back: mux.session: "{workspace}-{branch}" and mux.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

Choose a tag to compare

@github-actions github-actions released this 18 Oct 16:34
v0.2.0
e1807f2