alexisbeaulieu97

untaped-workspace

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.

alexisbeaulieu97 0 Updated 3w ago
GitHub

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 unified untaped CLI (no separate install).
  • A workspace has a local untaped.yml manifest and registry state.
  • Profile settings are cache_dir, workspaces_dir and parallel (default sync/foreach workers; unset means min(8, 2 × CPUs)), addressed as workspace.<field> (e.g. untaped config set workspace.cache_dir ...); the workspaces name→path registry is tool-managed state written by adopt/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... and repos remove WS REPO... need it before positional repos (. works); foreach [WS] CMD and branch set [WS] BRANCH read two positionals as workspace then value. There is no --workspace / --path option.
  • Use untaped workspace repos list WS to inspect a workspace before mutating it.

Command Patterns

  • untaped workspace list shows registered workspaces.
  • untaped workspace repos list|add|remove reads or edits the repos declared in one workspace's manifest.
  • untaped workspace status reports repo branch/dirty/ahead/behind state. --dirty / --behind keep only repos needing attention (either matches); --check exits 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 when git status timed out; filters never hide such rows). Under --all, stale or invalid workspace manifests emit action="unavailable" rows and do not abort unaffected workspaces.
  • untaped workspace sync updates repos, and --all applies across registered workspaces. It runs up to workspace.parallel (default min(8, 2 × CPUs)) repo sync jobs at once; -j N / --parallel N overrides that (-j 1 is serial). The cap is global across selected repos, not per workspace. Under --all, stale or invalid workspace manifests emit action="unavailable" rows with repo="".
  • untaped workspace sync --prune removes safe orphan clones after sync jobs finish and skips unsafe, uninspectable, or symlinked orphans with row-level skipped outcomes. When safe orphans exist it previews them and prompts once; pass --yes / -y in non-interactive use. sync --prune --dry-run skips the sync and prints planned / skipped orphan rows without changing anything.
  • untaped workspace repos remove --prune and untaped workspace forget --prune preview targets and prompt once before mutation unless --yes / -y is passed. Declining exits 1 (cancelled; no changes made) and preserves manifest, registry, and files. repos remove --dry-run and forget --prune --dry-run print planned rows without changing anything; forget --prune --dry-run also lists every path the prune would delete and fails on unsafe clones like the real prune.
  • init, repos add, repos remove, forget and branch unset print 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 action values planned, cloned, pulled, unchanged, skipped, failed, removed, unmatched, unavailable; branch apply rows use checked_out, unchanged, skipped, failed. Sync, status, foreach, branch apply and repos list rows carry an absolute target_path. A failed row keeps its detail and adds error (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 json stderr is JSON Lines with each error's category, system and hint.
  • untaped workspace foreach runs a shell command across selected repos; use care with side effects. Select repos with --repo or --stdin (repo names, or workspace.repo / workspace.status / workspace.sync_outcome records of WS; records from another workspace exit 2); --all runs in every registered workspace, with --repo as a per-workspace filter. Quote multi-word commands: foreach 'make build'. It runs workspace.parallel repos at once by default; pass -j 1 for strict fail-fast ordering. Child stdin is closed, and each repo command has a 600s default timeout unless --timeout N is passed.
  • Branch commands operate on workspace manifests and git refs; inspect --help for exact selector behavior. branch apply skips a target branch that exists neither locally nor on origin unless --create is passed.

Agent Guidance

  • Prefer --format json for structured state and --format raw --columns ... for shell pipelines.
  • Use --format pipe to chain commands: it emits one self-describing record per line tagged with a kind (e.g. workspace.workspace, workspace.repo); path --stdin reads workspace.workspace streams back (untaped workspace list --format pipe | untaped workspace path --stdin), repos add --stdin reads github.repo/github.repo_hit/github.sweep_repo (clone_url, else url) or workspace.repo (url) records, and repos remove --stdin reads workspace.repo/workspace.sync_outcome records (repo); any other kind exits 2. repos list --format pipe repo rows keep path as the workspace root and include target_path for the concrete repo checkout; an empty workspace emits a workspace.repo.summary row with no target_path.
  • Every command accepts --quiet/-q to mute the spinner and success/info lines (errors and data still print). untaped doctor diagnoses the active config and untaped config edit edits it.
  • Do not assume the current directory is the intended workspace: pass WS explicitly. Without it, commands use the nearest parent untaped.yml.
  • Treat destructive repo operations as explicit user intent. Inspect untaped workspace status before broad sync or branch changes.
  • Sync uses a central bare cache plus git clone --reference --dissociate for 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 apply to switch existing clones; sync skips dirty, diverged, or wrong-branch repos instead of checking them out.
  • Prune safety is local-only. sync --prune skips, and remove --prune / forget --prune refuse, 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, and sync --prune preview their targets and confirm once; a declined prompt exits 1 without mutation. forget --prune deletes only safe declared/orphan clones, symlinks standing in for them, and untaped.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 N is not host-aware; -j below 1 is a usage error (exit 2) for both sync and foreach, and a workspace.parallel below 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" with repo="" as a workspace-level manifest failure for sync --all / status --all (foreach --all skips such a workspace with a warning); it is not a repo-level skip and the registry entry is not removed automatically.