Skip to main content
Smithers exports a small VCS helper surface for applications that inspect or manage Jujutsu state directly:
  • every helper accepts an optional cwd to target a specific repository
  • spawn failures are normalized instead of thrown, safe to call even without jj installed
  • workspace helpers try a few command shapes to tolerate JJ version drift
  • JJ command helpers return Effect values; direct callers must supply an Effect ChildProcessSpawner service

Import

The root smthrs facade exports the main JJ helpers:
The lower-level VCS package also exports repository discovery, binary resolution, tooling preflight, and snapshot capture 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.
The hot-tree contract is deliberately narrow: 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.
Direct JJ helper calls need a platform layer:
Install @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.
Notes:
  • normalizes process failures instead of throwing, e.g. { code: 127, stdout: "", stderr: "..." } when jj cannot 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.
Smithers uses the same pointer model for revert support and cache invalidation.

revertToJjPointer(pointer, cwd?)

Restore the working copy from a recorded JJ pointer (a commit_id string, as returned by getJjPointer).
Wraps jj restore --from <pointer>.

isJjRepo(cwd?)

Detect whether a directory is a readable JJ repository.
Use this before showing JJ-specific UI or attempting a revert flow.

workspaceAdd(name, path, opts?)

Create a JJ workspace with a friendly name at a target filesystem path.
Behavior notes:
  • 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 add syntaxes to work across JJ versions

workspaceList(cwd?)

List known workspaces for the current JJ repo.
Prefers template output when supported, falls back to parsing the human-readable jj workspace list output.

workspaceClose(name, opts?)

Forget a JJ workspace by name.
Wraps 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.
Returns 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.
Synchronous and best-effort: runs version probes with a short timeout and powers the CLI’s VCS preflight checks.

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
For workflow-level revert behavior, prefer the runtime and CLI docs: