worktree
Worktree
Use this skill when working on mainline from a feature worktree and landing
that work back through mq.
Do not use this as a substitute for first-time setup or repo orientation. If
the user is new here, on a fresh clone, or asking what this checkout is and how
to get started, use the onboarding skill first.
If you hit DX friction, missing features, confusing docs, or real bugs while
using mq, file them proactively in recallnet/mainline and then continue the
task with the best safe workaround. Do not silently work around product gaps
without capturing them.
The goal is simple:
mainstays clean- the repo root checkout stays boring and trustworthy
- each task gets its own worktree
- all commits happen in the feature worktree
- landing happens through
mq, not manual merge intomain
Default commands to optimize for:
mq submit --check-only --jsonmq submit --queue-only --jsonmq submit --wait --timeout 15m --jsonmq submit --wait --for landed --timeout 30m --jsonmq wait --submission <id> --for landed --json --timeout 30mmq land --json --timeout 30mmq events --follow --json --lifecycle
Do not use this skill to bypass mq. It exists to dogfood the workflow that
mainline is building for other repos.
Treat PLAN.md as the forward product plan and SPEC.md as the current product contract. If a change alters the supported operator model or product boundary, those docs need to move with the code.
Supported agent clients may also enforce this with hooks. If a hook blocks a
native git mutation on the protected main worktree, that is not a false
positive to work around. Move to a feature worktree and continue there.
Operating rules
- Never do feature work on the protected branch worktree.
- Never commit unfinished feature work onto
main. - Never merge a feature branch into
mainmanually whenmqcan perform the integration path being dogfooded. - Never push directly to
origin/mainfrom a feature worktree as part of the normal flow. - Make all code changes, tests, and commits from the feature worktree tied to the branch being submitted.
- Prefer
mq submitfrom the current worktree instead of manually spelling--repowhen the current shell is already in the topic worktree. - Use explicit protected-worktree paths when invoking operator commands like
mq publish,mq land,mq watch, ormq events.
Standard flow
1. Start from a clean protected branch worktree
Use the repo root checkout as the canonical protected branch worktree.
Example:
cd ~/Projects/recallnet/mainline
git status --short
git branch --show-current
Expected:
- worktree is clean
- branch is
main - this root checkout is the one humans inspect and wrappers build from
- do not run helpers like
npm skillsthere; run them in the topic worktree so generated lockfile drift does not block publish
Before trusting that assumption on a machine you did not set up yourself:
mq repo root --repo ~/Projects/recallnet/mainline --json
If the root checkout is already clean and on main but config drift points the
canonical main worktree somewhere else, repair the configuration instead of
trying to outsmart the wrapper:
mq repo root --repo ~/Projects/recallnet/mainline --adopt-root
2. Create a dedicated feature worktree
Prefer the machine worktree layout convention:
mkdir -p ~/Projects/_wt/recallnet/mainline
git worktree add ~/Projects/_wt/recallnet/mainline/<branch-name> -b <branch-name> main
Example:
git worktree add ~/Projects/_wt/recallnet/mainline/m4-run-once -b m4-run-once main
3. Do all work inside the feature worktree
cd ~/Projects/_wt/recallnet/mainline/m4-run-once
git status --short
git branch --show-current
All of these should now happen in the feature worktree:
- editing files
- running tests
- making commits
- amending or stacking follow-up commits
Do not hop back to the protected branch worktree to finish the task.
4. Commit only from the feature worktree
Example:
git add <files>
git commit -m "Implement run-once integration worker"
If review finds a defect, make the fix as another commit on the same feature branch unless there is an explicit reason to rewrite history.
5. Submit through mq
Most agents should finish from the feature worktree with:
mq submit --check-only --json
mq submit --wait --timeout 15m --json
Treat mq submit --wait as an integration answer, not a remote-publish answer.
If the repo keeps [publish].Mode = 'manual', use mq land or
mq wait --for landed when the job is not done until remote main moves.
If the repo uses [publish].Mode = 'auto' and the wrapper wants one blocking
submit call through publish, use mq submit --wait --for landed --timeout 30m --json.
Use mq submit --queue-only --json only when the point is to prove some other
process handled the queued submission instead of opportunistic submit-side
drain.
That gives the agent:
- a deterministic dry-run before expensive follow-up work
- a blocking integrated-or-blocked answer without inventing a poll loop
- stable JSON for wrappers and orchestration
If the wrapper needs a durable handle instead of waiting inline:
mq submit --json
mq wait --submission <id> --for landed --json --timeout 30m
Use that pattern when the caller wants to track a specific queued submission by id instead of polling by branch name.
If the branch is ready to hand off asynchronously instead:
mq submit
That now queues first and then opportunistically tries to drain. If another worker already holds the integration lock, the submit still succeeds and the active drainer owns the rest.
If a controller owns the full integrate-plus-publish path:
mq land --json --timeout 30m
If needed, be explicit:
mq submit \
--repo ~/Projects/recallnet/mainline \
--branch <branch-name> \
--worktree ~/Projects/_wt/recallnet/mainline/<branch-name>
Submission expectations:
- the worktree must be clean
- the branch must not be
main - the worktree must belong to the same repo
- the submitted branch head is recorded in durable queue state
6. Let mq land the change
Use mq instead of manual merge:
mq run-once --repo ~/Projects/recallnet/mainline
When publish behavior is part of the dogfood target:
mq publish --repo ~/Projects/recallnet/mainline
Recommended verification loop:
mq status --repo ~/Projects/recallnet/mainline --json
mq repo audit --repo ~/Projects/recallnet/mainline --json
mq events --repo ~/Projects/recallnet/mainline --follow --json --lifecycle
Expected:
- submission is visible in durable queue state
- integration result is visible after
mq run-once - publish result is visible after
mq publish status --jsoncan correlate a succeeded submission topublish_request_id,publish_status, andoutcomeunmergedis empty once the branch is truly reachable from protectedmainmq repo showandmq doctordo not warn that the repo root checkout is dirty or non-canonical
Review and fix loop
If code review finds an issue after submission-ready work:
- Return to the same feature worktree.
- Make the fix there.
- Commit the fix on the same branch.
- Re-submit if the queued SHA must be refreshed.
Do not patch main directly to fix a feature-branch defect.
Cleanup
After the branch is integrated and no longer needed:
git worktree remove ~/Projects/_wt/recallnet/mainline/<branch-name>
git branch -d <branch-name>
Only delete the branch after the integration result is confirmed.
What to avoid
git checkout mainin the feature worktree and continuing work theregit merge <branch>from the protected branch worktree as the default pathgit push origin mainas a substitute formq- reusing one worktree for multiple unrelated branches
- committing from the wrong worktree because the shell is pointed at the wrong directory
Current project note
This skill is the committed self-hosting path for mainline.
If the shipped command surface changes, update this skill alongside the README, flow docs, and plan so agents are never instructed to follow stale workflow steps.