Skip to content

feat(cli): new --member picks multi-repo members; project list names them - #436

Merged
simion merged 4 commits into
simion:mainfrom
yb-yu:feat/cli-new-member
Oct 28, 2026
Merged

simion merged 4 commits into
simion:mainfrom
yb-yu:feat/cli-new-member

Conversation

@yb-yu

@yb-yu yb-yu commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a repeatable --member to termic new and a members array to MCP task_new, so a task in a multi-repo project worktrees only the named repos, as the New Task dialog does.
termic project list and MCP project_list now report each project's type and a multi-repo project's members.

Refs #424

What changed

  • termic new --member <name>: each named member gets a worktree on the task branch, cut from its own base, through the existing task_create_multi.
    A plain-folder member is linked; with --main, only the named members' live checkouts are linked.
    Without --member, nothing changes.
  • Names are resolved in handle_new against the on-disk project, before any RPC.
    An unknown name fails with the project's members, and --member on a project that is not multi-repo fails with the registered multi-repo projects. Nothing is created in either case.
  • project list / project_list: type (single / multi) and members, also in the text output.
  • new --help, TERMIC_CLI_HELP, the MCP instructions and the bundled termic skill (SKILL.md, control-surface.md) teach it.
  • Protocol v24: an older app would drop members and create a task without the member worktrees.
  • tools/list grows by 214 bytes (28122 to 28336), recorded in the size test.
  • Docs: cli-agent-instructions, ipc, e2e-coverage.

Tests

  • cargo test: src-tauri 1509, termic-cli 95, termic-proto 26 pass.
    New tests cover name resolution, both refusals, the plain-folder host and --main modes, the project list shape and the CLI flag rules.
  • npm test: 3528 pass. npm run build, npm run typecheck:e2e and make check-all pass.
  • cli.e2e.ts: 50 pass, with new cases through the real CLI: a two-member task, a single member named case-insensitively, --main, an unknown member, a single-repo project, and project list.
    mcp.e2e.ts: 28 pass. The full e2e suite was not run.

Manually tested

  • Exercised in the dev build with a 14-repo multi-repo project on a plain-folder host.
  • Asked its orchestrator agent in plain words, with no flag hints, for a task on two repos and a parallel one on a third: it found --member and the names through project list, and each task got worktrees of only its repos, on its own branch, grouped under the orchestrator.
  • An unknown repo name exited 1 with the member list and created nothing.

…them

On a multi-repo project, `termic new` had no way to say which members
a task needs: a worktree create went through the single-repo
task_create (no member worktrees at all), and on a plain-folder host
the server pinned the main checkout, which links every member's live
checkout. An orchestrator agent could not create the task the New
Task dialog creates, and `project list` did not say which projects
are multi-repo or name their members, so it had no names to pass.

`--member <name>` (repeatable; MCP task_new `members`) names them.
handle_new resolves the names against the disk-read project
(case-insensitive, project order) and sends the webview root_paths
plus a concrete mode: worktree unless --main, also on a plain-folder
host, matching the dialog's canWorktree. The webview then calls
task_create_multi (a plain-folder member is linked) or task_open_repo
with its member filter. Without --member nothing changes.

A wrong ask fails before anything is created, with the valid names:
an unknown member lists the project's members, and --member on a
single-repo project lists the registered multi-repo projects (or says
none is registered). --member is also refused alongside --from,
--checkout, --resume or a review.

`project list` reports each project's `type` ("single" or "multi",
the Project.type key) and a multi-repo project's members (name,
root_path, non_git, base_branch), and marks those rows in text.
`new --help`, TERMIC_CLI_HELP, MCP_INSTRUCTIONS and the bundled
termic skill now say how to find one and name its members; the
skill's control-surface reference no longer says task_new has no
member list.

Protocol v24: a v23 server would drop the field and create a task
with no member worktrees, or with every member linked.

Refs simion#424
@yb-yu
yb-yu force-pushed the feat/cli-new-member branch from 861fe2f to b29de40 Compare October 27, 2026 19:59

@simion simion left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

LGTM once CI is green.

The Windows cargo failure isn't this PR: write_atomic_never_exposes_a_partial_file_to_a_concurrent_reader (lib.rs:36533) got NotFound mid-rename, which is a flake on Windows. It passes on main and the PR doesn't touch it. I'll re-run it; the e2e jobs are still pending.

Three small follow-ups, none blocking:

  • The plain-folder decision in src/lib/cliRpc.ts:248 reads useApp projects, while the server resolved members from disk. If the store is behind, a plain-folder member goes out as "worktree" and git branch fails on it (rolled back, but a confusing error). The server already has each member's non_git and could send the mode with the path.
  • --base only applies to the host; new x --member api --base dev still cuts api from its own base. Matches the dialog, but one line in new --help would save the surprise.
  • Nit: agent_overview! (termic-cli/src/lib.rs:179) didn't get the multi-repo sentence that went into MCP_INSTRUCTIONS, which mcp_server.rs:782 asks to keep in step.

(Reviewed by Simion's agent, he'll take the final look.)

yb-yu added 3 commits October 27, 2026 22:33
handle_new now sends each member as { root_path, mode }, decided from
the disk-read project: a plain-folder member, or any member of a
main-checkout task, is repo_root. The webview used to read its store
for that, so a store lagging a member edit could send a plain folder
out as a worktree, which `git branch` then fails on.

Refs simion#424
Each --member keeps its own base, as in the New Task dialog; the help
did not say so.

Refs simion#424
agent_overview! (the long --help and help --json overview) and
MCP_INSTRUCTIONS each ask to be kept in step with the other; only the
MCP side had the multi-repo sentence.

Refs simion#424

@simion simion left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

LGTM, all three follow-ups are in and CI is green.

The server now sends each member's mode from the disk-read project (cli_server.rs:1440), so a lagging store can't worktree a plain folder.
--base is documented as the host's, and agent_overview! matches MCP_INSTRUCTIONS.

(Reviewed by Simion's agent, he'll take the final look.)

@simion
simion merged commit 75789c7 into simion:main Oct 28, 2026
7 checks passed
@simion

simion commented Oct 28, 2026

Copy link
Copy Markdown
Owner

This is live in v1.20.0, released today. Thanks for the contribution.

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.

2 participants