feat(cli): workspace project repo lifecycle (list, add, rm, sync, doctor)
Summary
Umbrella for making workspace projects operable from the ao CLI after initial ao project add --as-workspace.
Today a workspace is scanned once at add time. ao project get --json returns a thin workspaceRepos list (name, relativePath, repo). There is no CLI (and little daemon surface) to list children with health, add or remove a child later, rescan the folder, set a per-child default branch, or explain which child blew up ao spawn.
This is long-running. Ship in slices. Related: #5643 (add-repo only). Keep that issue; this one is the full lifecycle.
Why
Workspace projects grow. Orchestrators and agents only have the CLI. Example: AgentLab added alab-cli after the workspace existed. Clone + root .gitignore was possible by hand. The project record did not update, so new session worktrees still omit the child. Spawn failures name a nested .git/config lock and kill the whole workspace spawn with no child-level diagnosis.
Desktop project settings mostly display workspaceRepos. They are not a substitute for CLI.
Current surface (checked 2026-09-19)
ao project add --as-workspace: initial register; adopts children present at that momentao project set-config: branch, env, agents, rules, etc. No workspace-repo fieldsao project get --json:workspaceReposwithoutdefault_branch, even thoughworkspace_repos.default_branchexists in the store- No
ao project repos,repo add,repo rm,repos sync, or workspace-specific doctor checks
Desired CLI (names are proposals)
1. List
ao project repos [<project-id>]
ao project repos --jsonPer child: name, relative path, origin URL, default branch, on-disk present, last-known git status / HEAD resolve. This is the inspect primitive everything else hangs off.
2. Add and remove (overlaps #5643)
ao project repo add --project <id> --path <dir>
ao project repo rm --project <id> <name>Add: existing git checkout under the workspace root (or clone-then-attach if we later add an explicit --clone <url>). Infer name, relative path, origin, default branch. Update the project record so the next ao spawn worktrees that child. Update root .gitignore for the child path when that is already the workspace convention.
Remove: drop the registry row. Do not delete the folder unless --delete-files is explicit.
3. Sync / rescan
ao project repos sync [<project-id>]Rescan the workspace directory. Adopt new git children already on disk that are not in workspaceRepos. Report missing registered children. Do not surprise-delete registry rows; rm stays explicit.
This is the 80% path: human or agent clones a repo into the workspace, then sync.
4. Per-child default branch
ao project repo set <name> --default-branch <branch>Workspace-wide defaultBranch is the wrong knob when children disagree. Unresolved origin/HEAD already fails spawn with DEFAULT_BRANCH_UNRESOLVED. Expose and set the per-child column the DB already has.
5. Spawn diagnostics per child
When ao spawn fails inside a workspace worktree add, the error must name:
- child repo name and path
- git command
- lock or config file if that is the cause
Today one nested git config lock aborts the entire workspace spawn as a generic worktree error.
6. Doctor checks
ao doctor (or ao project doctor) for workspace kind:
- child missing on disk
- child not a git repo
- child on disk but not in
workspaceRepos - child not gitignored at workspace root (when other children are)
- origin HEAD unresolved
Orchestrators should run this before a wave of spawns.
Non-goals
- Nested workspaces
- Silent auto-clone from GitHub into the workspace
- Spawn that checks out only one child (workspace remains all children in one worktree)
- Changing single-repo or scratch project kinds
--clone <url> on add can be a later slice. Not required for v1 of this umbrella.
Suggested slices (independent PRs)
ao project reposlist (+ json), including default branchrepo add/repo rm(can close #5643 when add ships)repos syncrepo set --default-branch- Spawn error includes child identity
- Doctor checks
Acceptance (umbrella)
- A workspace can gain a child without re-running
ao project add --as-workspace ao project repos --jsonis enough for an orchestrator to see drift vs disk- Next
ao spawnafter add or sync worktrees the new child - A spawn failure on child B does not look like a generic workspace failure with no name
ao doctorflags unsynced children
Environment
- Project kind:
workspace - Trigger: AgentLab workspace, 2026-09-19, adding
alab-cliafter initial register
Source: Untrivial-ai/agent-orchestrator