Use the `untaped workspace` command to manage local multi-repository git workspaces (register them, add or remove repos, clone and pull them together, check their status, switch branches, and run a command in every repo). Use when the user mentions a workspace, several repos at once, cloning or syncing many repos, dirty or behind repos, or running a command across repos.
Install
npx skillscat add alexisbeaulieu97/untaped/untaped-workspace Install via the SkillsCat registry.
SKILL.md
Untaped Workspace
Use this skill when the user wants an agent to operate untaped workspace for local multi-repo git workspaces.
Setup
- The command is
untaped workspace. It ships with the unifieduntapedCLI (no separate install). - A workspace has a local
untaped.ymlmanifest and registry state. - Profile settings are
cache_dir,workspaces_dirandparallel(defaultsync/foreachworkers; unset meansmin(8, 2 × CPUs)), addressed asworkspace.<field>(e.g.untaped config set workspace.cache_dir ...); theworkspacesname→path registry is tool-managed state written byadopt/init/forget, not a setting. - The workspace is the first positional argument,
WS: a registered name, or a path inside a workspace (.is the current directory). Omitted, it is the workspace containing the current directory. A path must exist (no silent walk-up from a typo).repos add WS URL...andrepos remove WS REPO...need it before positional repos (.works);foreach [WS] CMDandbranch set [WS] BRANCHread two positionals as workspace then value. There is no--workspace/--pathoption. - Use
untaped workspace repos list WSto inspect a workspace before mutating it.
Command Patterns
untaped workspace listshows registered workspaces.untaped workspace repos list|add|removereads or edits the repos declared in one workspace's manifest.untaped workspace statusreports repo branch/dirty/ahead/behind state.--dirty/--behindkeep only repos needing attention (either matches);--checkexits 3 when any repo is dirty or behind, or with the failure's own code when a repo could not be inspected (1, or 5 whengit statustimed out; filters never hide such rows). Under--all, stale or invalid workspace manifests emitaction="unavailable"rows and do not abort unaffected workspaces.untaped workspace syncupdates repos, and--allapplies across registered workspaces. It runs up toworkspace.parallel(defaultmin(8, 2 × CPUs)) repo sync jobs at once;-j N/--parallel Noverrides that (-j 1is serial). The cap is global across selected repos, not per workspace. Under--all, stale or invalid workspace manifests emitaction="unavailable"rows withrepo="".untaped workspace sync --pruneremoves safe orphan clones after sync jobs finish and skips unsafe, uninspectable, or symlinked orphans with row-levelskippedoutcomes. When safe orphans exist it previews them and prompts once; pass--yes/-yin non-interactive use.sync --prune --dry-runskips the sync and printsplanned/skippedorphan rows without changing anything.untaped workspace repos remove --pruneanduntaped workspace forget --prunepreview targets and prompt once before mutation unless--yes/-yis passed. Declining exits 1 (cancelled; no changes made) and preserves manifest, registry, and files.repos remove --dry-runandforget --prune --dry-runprintplannedrows without changing anything;forget --prune --dry-runalso lists every path the prune would delete and fails on unsafe clones like the real prune.init,repos add,repos remove,forgetandbranch unsetprint outcome rows on stdout (workspace.init_outcome,workspace.add_outcome,workspace.remove_outcome,workspace.forget_outcome,workspace.branch_unset_outcome) and honour--format/--columns.- Sync rows use
actionvaluesplanned,cloned,pulled,unchanged,skipped,failed,removed,unmatched,unavailable;branch applyrows usechecked_out,unchanged,skipped,failed. Sync, status, foreach, branch apply andrepos listrows carry an absolutetarget_path. Afailedrow keeps itsdetailand addserror(category,system,retryable,message,hint; not in tables). - Exit codes: 1 the thing failed (unknown workspace or repo, invalid
untaped.yml, a failed git step), 2 usage, 3 predicate hit, 4 fix the environment (settings,$EDITOR, git missing), 5 temporary (git timed out or lost the network; retry later); a run exits with its most severe failure. With--format jsonstderr is JSON Lines with each error'scategory,systemandhint. untaped workspace foreachruns a shell command across selected repos; use care with side effects. Select repos with--repoor--stdin(repo names, orworkspace.repo/workspace.status/workspace.sync_outcomerecords ofWS; records from another workspace exit 2);--allruns in every registered workspace, with--repoas a per-workspace filter. Quote multi-word commands:foreach 'make build'. It runsworkspace.parallelrepos at once by default; pass-j 1for strict fail-fast ordering. Child stdin is closed, and each repo command has a 600s default timeout unless--timeout Nis passed.- Branch commands operate on workspace manifests and git refs; inspect
--helpfor exact selector behavior.branch applyskips a target branch that exists neither locally nor on origin unless--createis passed.
Agent Guidance
- Prefer
--format jsonfor structured state and--format raw --columns ...for shell pipelines. - Use
--format pipeto chain commands: it emits one self-describing record per line tagged with akind(e.g.workspace.workspace,workspace.repo);path --stdinreadsworkspace.workspacestreams back (untaped workspace list --format pipe | untaped workspace path --stdin),repos add --stdinreadsgithub.repo/github.repo_hit/github.sweep_repo(clone_url, elseurl) orworkspace.repo(url) records, andrepos remove --stdinreadsworkspace.repo/workspace.sync_outcomerecords (repo); any other kind exits 2.repos list --format piperepo rows keeppathas the workspace root and includetarget_pathfor the concrete repo checkout; an empty workspace emits aworkspace.repo.summaryrow with notarget_path. - Every command accepts
--quiet/-qto mute the spinner and success/info lines (errors and data still print).untaped doctordiagnoses the active config anduntaped config editedits it. - Do not assume the current directory is the intended workspace: pass
WSexplicitly. Without it, commands use the nearest parentuntaped.yml. - Treat destructive repo operations as explicit user intent. Inspect
untaped workspace statusbefore broad sync or branch changes. - Sync uses a central bare cache plus
git clone --reference --dissociatefor missing clones, so clones are self-contained and pruning or deleting the cache never breaks them (clones from older releases may still borrow cache objects via alternates). Existing clones fetch/pull their own working remotes and do not touch the bare cache. - Sync branch metadata is clone-time only. Use
untaped workspace branch applyto switch existing clones; sync skips dirty, diverged, or wrong-branch repos instead of checking them out. - Prune safety is local-only.
sync --pruneskips, andremove --prune/forget --prunerefuse, when a clone has dirty/untracked/staged work, stash entries, or commits/local tags not reachable from local remote-tracking refs. The prune check does not fetch; stale remote-tracking refs are trusted as the offline safety boundary.remove --prune,forget --prune, andsync --prunepreview their targets and confirm once; a declined prompt exits 1 without mutation.forget --prunedeletes only safe declared/orphan clones, symlinks standing in for them, anduntaped.yml; loose files and non-git directories are kept, and the workspace directory is removed only if it ends up empty (a warning lists what was left). sync -j Nis not host-aware;-jbelow 1 is a usage error (exit 2) for bothsyncandforeach, and aworkspace.parallelbelow 1 is an invalid config value (exit 4). Ctrl-C cancels queued sync/foreach work; foreach also terminates every running command's process group (including under--parallel).- Treat
action="unavailable"withrepo=""as a workspace-level manifest failure forsync --all/status --all(foreach --allskips such a workspace with a warning); it is not a repo-level skip and the registry entry is not removed automatically.