Notable changes to cow, newest first.
Fixes cow create on Turbopack monorepos, where symlinks caused build failures. Adds a proper app icon to Herd.
cow create now detects turbo.json
and performs a full clone instead of symlinking node_modules, which Turbopack
cannot follow. A note is printed explaining the slightly slower clone.
Adds Herd, a SwiftUI menubar app that gives a live view of all pastures without opening a terminal.
Available via brew install joeinnes/tap/herd.
brew install joeinnes/tap/herd builds Herd from source,
no code signing required.
Patch release fixing two bugs — a silent mismatch in cow sync argument
parsing and missing Linux support in cow materialise — plus a major
expansion of the integration test suite.
cow sync <name> — the positional pasture name was silently
assigned to source_branch instead of name due to
swapped clap annotations in SyncArgs. The command fell back to
resolving the pasture from the current working directory, targeting the wrong
pasture. Fixed by making name the bare positional argument and
source_branch a --source-branch flag (consistent
with all other commands).
cow materialise on Linux — the materialise command lacked a
Linux implementation, causing a compile error on non-macOS targets. Now uses
cp --reflink=always with graceful fallback to a plain
cp -R (matching cow create behaviour).
gc, stats, materialise,
migrate, and fetch-from, covering the main happy
paths and key error branches in each command.
Patch release fixing a critical bug where cow run would hang
silently for any non-install subcommand, plus two quality-of-life improvements.
cow run — PM shims recursed infinitely when called with
non-install subcommands (e.g. pnpm run dev, npm test).
The shim used /usr/bin/env <pm> to find the real binary, but
since ~/.cow/shims/ is prepended to PATH the shim found itself
and looped. Fixed by stripping the shims directory from PATH at the top of
every shim before invoking the real binary. Existing stale shims are
automatically regenerated on the next cow run invocation.
cow list output is now sorted alphabetically by name, grouping
pastures by project naturally (e.g. all jazz2/ entries together).
cow install now sets up full tab completion for the cow
binary itself: subcommand completion at position 1, pasture name completion at
position 2 for all name-taking commands (run, status,
diff, remove, cd, materialise,
fetch-from, recreate). Users with the old snippet are
prompted to remove it and re-run cow install.
Five new commands, per-package dependency symlinks, git linked worktree support, and full MCP coverage for agent-driven workflows.
cow run <name> <cmd> — runs a command inside a pasture's
working directory. Auto-detects the package manager from lockfiles and
injects shims so install subcommands write to the pasture-local
node_modules rather than the shared source. Sets
COW_PASTURE, COW_SOURCE, and
COW_PASTURE_PATH env vars for the subprocess.
cow materialise <name> — replaces symlinked dependency
directories in a pasture with real APFS clonefiles, making the pasture
fully independent of the source.
cow fetch-from <from> — fetches all refs from another
pasture into this one, enabling cross-pasture rebase without touching
any remote.
cow recreate <name> — removes a pasture and re-creates it
from the same source, optionally on a different branch.
cow install — sets up the cowcd shell function and
tab completion in ~/.zshrc (zsh) or ~/.bashrc (bash)
automatically. Detects your shell from $SHELL. Idempotent.
--worktree flag — creates a git linked worktree instead of an
APFS clone. All worktree pastures share the same .git/objects/
pack store, so cross-pasture rebase works without any remote dance.
node_modules, vendor,
.venv, Pods, etc.) are now handled with per-package
symlinks: each top-level entry is symlinked individually so existing
packages are instantly available and new installs write locally to the
pasture. Previously the whole directory was symlinked.
--no-symlink flag — skips large-directory detection and always
performs a full clone.
cow status and cow list now show
changed instead of dirty for jj pastures, reflecting
jj semantics where the working copy is always materialised as a commit.
cow_migrate, cow_materialise,
cow_fetch_from, and cow_run tools added to the
MCP server, completing full command coverage for agent-driven workflows.
Pasture names are now scoped by source repository — feature-x
becomes brightblur/feature-x automatically. cow list
drops the SOURCE column (it's encoded in the name) and gets a cleaner layout.
Adds flags for scripting and non-TTY use: --print-path on create,
-y/--yes on remove, and -m/--message for jj.
cow create feature-x --source ~/repos/brightblur stores the
pasture as brightblur/feature-x. Supply an explicit
scope/name to override.
brightblur/agent-1, brightblur/agent-2, etc.
cow list redesigned — SOURCE column removed (source is now
encoded in the scoped name). Branch column only appears when the branch
differs from the pasture name suffix.
cow create --print-path — suppress all output except the final
pasture path, making it easy to capture in scripts:
WS=$(cow create my-feature --print-path).
cow create -m/--message <MSG> — set the initial jj change
description immediately after pasture creation. Removes the separate
jj describe step (jj repos only).
cow remove -y/--yes — skip confirmation prompts without implying
a safety override. Unlike --force (which bypasses dirty checks),
--yes still shows dirty warnings — it just doesn't wait for input.
Idiomatic for scripts and non-TTY contexts.
cow list now shows a file count next to dirty pastures
(e.g. dirty (3)), giving a quick sense of change scope without
running cow status.
cow create now rolls back atomically on failure and gains a
--from flag for branching from an arbitrary revision.
cow list contracts home to ~, and stale worktree
refs left behind by a failed clone are cleaned up automatically.
cow create --from <rev> — branch the new pasture from an
arbitrary revision rather than always using the source HEAD.
cow create now performs atomic rollback on failure: any partially
written pasture directory and git worktree entry are cleaned up before
returning an error.
cow create.
cow list now contracts the home directory to ~ in
path output, keeping lines short on typical setups.
Adds cow migrate, which discovers git linked worktrees, jj secondary
workspaces, and orphaned cow pasture directories and migrates them into proper
cow-managed APFS clone pastures — so you can adopt cow without starting your
in-progress branches from scratch.
cow migrate [--source] [--all] [--force] [--dry-run] — discover
and migrate git worktrees, jj workspaces, and orphaned directories into
cow-managed pastures. Git worktrees are replaced with an APFS clone and the
old worktree removed; jj workspaces are re-created with jj workspace add
and the old one forgotten; orphaned directories are registered in-place without
cloning. Dirty candidates are skipped unless --force is passed.
--dry-run prints the plan without making any changes.
cow migrate command reference and a Development section
documenting the three root causes of the test coverage gap in
migrate.rs (jj paths, subprocess integration tests, defensive error paths).
migrate tab.
Switches from a cp -Rc subprocess to a direct clonefile(2)
syscall for a measurable speed improvement on large repos, and fixes several
issues with Jujutsu pasture creation.
cp -Rc subprocess with a direct clonefile(2) syscall.
This is the same kernel call Time Machine uses: one atomic operation regardless of
directory depth, with no per-file process spawning. A 2 GB repository now clones in
around 130 ms wall time.
jj workspace add before copying untracked files from the source.
Previously the copy ran first, causing jj workspace add to reject the
non-empty destination directory.
signing.behavior="drop" to jj workspace add so SSH
passphrase prompts are suppressed during pasture creation. jj signs the initial
workspace commit immediately; this flag suppresses that without touching the
user's global jj config.
.jj/cow-context instead of .cow-context
at the pasture root. jj auto-tracks every new file in the working copy, so a
file at the root appeared as an addition in jj diff and jj status.
Content inside .jj/ is invisible to jj's working-copy tracking.
cow ships as a Homebrew formula and a Cargo crate (cow-cli),
covering the full pasture lifecycle with an MCP server for agent orchestration.
cow create — clone a repo into an isolated APFS pasturecow list — list all active pastures, with optional JSON outputcow status — detailed pasture status including diff summarycow diff — passthrough to git diff or jj diffcow extract — extract changes back to source as patch or branchcow remove — remove pastures, with dirty-state warningscow sync — fetch and rebase pasture onto source repo changescow cd — print pasture path for shell integrationcow mcp — run as an MCP stdio server for AI orchestrators