- every helper accepts an optional
cwdto target a specific repository - spawn failures are normalized instead of thrown, safe to call even without
jjinstalled - workspace helpers try a few command shapes to tolerate JJ version drift
- JJ command helpers return
Effectvalues; direct callers must supply an EffectChildProcessSpawnerservice
Import
The rootsmthrs facade exports the main JJ helpers:
createIsolatedClone, listGitRefs, and gitDirtyPaths are also exported by
the root smthrs facade.
Isolated clone and bundle handoff
createIsolatedClone({ repo, at, destination? }) creates a standalone,
detached clone at exactly at^{commit}. It removes remotes and refs, rejects
Git alternates, writes a nonce ownership marker, and will only clean a clone
whose marker still matches.
expectedHead^{commit} must be
readable while the clone is created. The source working tree, index, refs, JJ
bookmarks, object inventory, and later HEAD movement may change; they are not
quiescence gates. The clone is the isolation boundary. The emitted patch,
bundle, and JSON manifest are adoption evidence, and emitBundle() verifies
them in a fresh repository before returning. Land a handoff into a shared tree
only in a short serialized adoption step.
clone.run() always uses the clone root as cwd. It inherits only PATH,
HOME, temp-directory, user/shell, and locale variables, plus explicit env
overrides. Ambient GIT_*, SMITHERS_HOME, and other SMITHERS_* variables
are absent unless explicitly supplied.
Large Git inventories
listGitRefs(repo) and gitDirtyPaths(repo) use streamed child-process output,
so they do not have Node’s synchronous 1 MB maxBuffer ceiling. This matters
for JJ-colocated repositories, where tens of thousands of refs can produce
multi-megabyte output. Do not replace these helpers with execFileSync("git", ["for-each-ref"]) using its default buffer.
@effect/platform-bun for the Bun snippet, or provide the equivalent ChildProcessSpawner service for another runtime.
runJj(args, opts?)
Run an arbitrary jj command and capture its output.
- normalizes process failures instead of throwing, e.g.
{ code: 127, stdout: "", stderr: "..." }whenjjcannot be started - a raw escape hatch beneath the higher-level helpers below
getJjPointer(cwd?)
Returns the current workspace commit_id for @ (null if JJ is unavailable or the directory isn’t a JJ repo). The immutable commit ID pins the exact working-copy snapshot even as later writes amend the same JJ change.
revertToJjPointer(pointer, cwd?)
Restore the working copy from a recorded JJ pointer (a commit_id string, as returned by getJjPointer).
jj restore --from <pointer>.
isJjRepo(cwd?)
Detect whether a directory is a readable JJ repository.
workspaceAdd(name, path, opts?)
Create a JJ workspace with a friendly name at a target filesystem path.
- removes any existing workspace with the same name and its target directory if present before retrying, creating the parent directory if needed
- tries multiple
jj workspace addsyntaxes to work across JJ versions
workspaceList(cwd?)
List known workspaces for the current JJ repo.
jj workspace list output.
workspaceClose(name, opts?)
Forget a JJ workspace by name.
jj workspace forget <name>.
captureWorkspaceSnapshot(cwd?)
Capture the current JJ working-copy state as a restorable handle. This helper is exported by @smthrs/vcs, not by the root facade.
null on failures and timeouts, including non-JJ directories. Smithers uses commitId and operationId for workspace durability checkpoints.
findVcsRoot(startDir)
Walk upward from a directory and return the nearest .jj or .git root. JJ wins when both markers exist in the same directory.
resolveGitBinary() and resolveJjBinary()
Resolve the executable Smithers will spawn for VCS commands.
resolveGitBinary() checks SMITHERS_GIT_PATH, then git on PATH. resolveJjBinary() checks SMITHERS_JJ_PATH, then a bundled @smthrs/jj-<platform> package, then jj on PATH.
vcsToolingStatus()
Probe whether the resolved VCS binaries are usable on the current host.
When To Use These Helpers
Use these helpers when your application needs to:- show whether JJ-backed revert is available
- record or inspect a pointer outside the Smithers engine
- manage JJ workspaces directly from an app or integration layer
- check whether JJ or Git tooling is available before starting worktree logic