Skip to content

feat: add pm - project manager for multi-repo workspaces#581

Open
baxen wants to merge 3 commits intomainfrom
baxen/pm-cli
Open

feat: add pm - project manager for multi-repo workspaces#581
baxen wants to merge 3 commits intomainfrom
baxen/pm-cli

Conversation

@baxen
Copy link
Copy Markdown
Collaborator

@baxen baxen commented Apr 6, 2026

Simple CLI for managing multi-repo projects with git worktree pooling.

Commands

  • pm new <project> - create a new project
  • pm add <repo> - add a repo (infers project from cwd, GitHub shorthand)
  • pm rm <project> - remove a project (handles manual rm gracefully)
  • pm status - show all projects and pool state
  • pm cleanup - find stale/merged projects

Key features

  • GitHub shorthand: block/goose just works
  • HTTPS-first clone with SSH fallback
  • Branch convention: $USER/$PROJECT
  • Auto-init, auto-clone, cwd-aware
  • Resilient to manual rm of project dirs

baxen added 2 commits April 4, 2026 11:27
Simple CLI for managing multi-repo projects with git worktree pooling.

Commands:
  pm new <project>     - create a new project
  pm add <repo>        - add a repo (infers project from cwd, GitHub shorthand)
  pm rm <project>      - remove a project (handles manual rm gracefully)
  pm status            - show all projects and pool state
  pm cleanup           - find stale/merged projects

Key features:
  - GitHub shorthand: 'block/goose' just works
  - HTTPS-first clone with SSH fallback
  - Branch convention: $USER/$PROJECT
  - Auto-init, auto-clone, cwd-aware
  - Resilient to manual rm of project dirs
@baxen baxen requested review from matt2e and wesbillman as code owners April 6, 2026 16:54
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c79877e778

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +251 to +253
if project_dir.exists() {
std::fs::remove_dir_all(&project_dir)
.with_context(|| format!("Failed to remove {}", project_dir.display()))?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Refuse deleting directories not tracked as projects

rm recursively deletes base/<name> whenever that path exists, even if <name> was never registered in state.projects. In practice, a typo like pm rm docs can wipe an unrelated workspace folder and its contents. This should be gated on the project being managed (or return an error) before calling remove_dir_all.

Useful? React with 👍 / 👎.

Comment on lines +85 to +87
let state: State =
serde_json::from_str(&data).with_context(|| "Failed to parse state file")?;
Ok(Some(state))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Rebind loaded state root to the active workspace path

State::load returns the deserialized struct without normalizing root to the base being opened. Since later operations (including save() and pool path resolution) use self.root, moving/renaming a workspace or opening it via a different canonical path can make pm read/write state and worktrees in the old location instead of the current one.

Useful? React with 👍 / 👎.

Comment on lines +65 to +69
if needs_checkout {
let repo = state.repos.get(repo_name).unwrap();
if slot.path.exists() {
git::checkout(&slot.path, branch)?;
} else {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recreate missing worktree when reusing an owned slot

For slots already owned by the same project, repair logic only runs when the branch changes. If the slot directory was manually removed and the branch is unchanged, this path returns success without restoring the worktree, so subsequent pm add can leave a symlink pointing at a non-existent target while reporting success.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator

@wesbillman wesbillman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! This is great! In a follow on PR maybe, we should add some README and a bunch of tests for this thing.

Pool conflict resolution:
- Interactive terminal: dialoguer Select menu to choose which
  project to evict, grow the pool, or abort
- Non-interactive (agent/CI): aborts with clear error and
  actionable --evict <project> / --grow-pool flags
- Detection uses std::io::stdin().is_terminal()

New CLI flags on 'pm add':
  --evict <project>  evict a specific project (non-interactive)
  --grow-pool        add a slot instead of evicting
  --existing --worktree  register existing checkout for worktree use

Refactored pool::acquire_slot to return AcquireResult enum.
New pool::execute_eviction and pool::grow_and_acquire.
Improved git checkout with 3-step fallback strategy.
Improved is_branch_merged to handle squash merges.
@github-advanced-security
Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants