| name | worktree |
| description | Work in a dedicated Git worktree, make all commits there, and land changes through `mq` instead of merging directly into `main`. Use after onboarding, once the user already understands the repo's setup and wants the contribution workflow. |
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:
main stays 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 into main
Default commands to optimize for:
mq submit --check-only --json
mq submit --queue-only --json
mq submit --wait --for landed --timeout 30m --json
mq wait --submission <id> --for landed --json --timeout 30m
mq land --json --timeout 30m
mq events --follow --json --lifecycle for audit/debug only
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
main manually when mq can perform the
integration path being dogfooded.
- Never push directly to
origin/main from 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 submit from the current worktree instead of manually spelling
--repo when 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, or mq 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 skills there; 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 --for landed --timeout 30m --json
Treat plain 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.
mq land requires the configured remote to exist only when a remote target is
configured. In local-only repos with [repo].RemoteName = "", use mq land,
mq submit --wait --for landed, or mq wait --for landed when verified local
protected-branch integration is the terminal result; no publish request is
created.
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 landed-or-failed 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. Follow the submission, not the logs.
Do not use sleeps, branch-name polling, mq logs, mq events, or mq watch as the
primary way to decide whether a queued change finished.
If a publish request fails because remote main moved first, prefer retrying
the publish request from the protected worktree:
mq retry --repo ~/Projects/recallnet/mainline --publish <id>
mq now attempts the safe case automatically by fetching upstream, rebasing the
unpublished protected-branch commits onto the updated remote tip when that
replay is clean, and retrying the push. If local Git branch tracking is absent,
mq uses the protected remote branch configured in mainline.toml.
If the branch is behind local protected main or a submission blocks on a
rebase conflict, use mq rebase as the default repair path:
mq rebase --repo ~/Projects/_wt/recallnet/mainline/<branch-name> --branch <branch-name> --json
mq rebase --repo ~/Projects/_wt/recallnet/mainline/<branch-name> --submission <id> --json
mq retry --repo ~/Projects/_wt/recallnet/mainline/<branch-name> --submission <id> --json
That keeps the repair repo-aware, syncs protected main first when needed, and
avoids guessing between rebasing onto local main vs origin/main.
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 the queue-first default flow, not manual run-once plus publish.
Normal blocking paths:
mq submit --wait --for landed --timeout 30m --json
or:
mq land --json --timeout 30m
If the caller needs a durable handle instead of waiting inline:
mq submit --json
mq wait --submission <id> --for landed --json --timeout 30m
Recommended verification loop:
mq status --repo ~/Projects/recallnet/mainline --json
mq repo audit --repo ~/Projects/recallnet/mainline --json
Use mq events --follow --json --lifecycle only when a controller or operator
needs deeper audit/debug detail than the submission-id flow.
Expected:
- submission is visible in durable queue state
- publish correlation is visible through
publish_request_id, publish_status,
and outcome
unmerged is empty once the branch is truly reachable from protected main
mq repo show and mq doctor do not warn that the repo root checkout is
dirty or non-canonical
mainline.toml remains the authority for repo config; SQLite state is queue
identity and history only
If a managed repo needs cache or environment preparation after integration and
before push, prefer [checks].PreparePublish in mainline.toml for commands
like pnpm install --frozen-lockfile. Put read-only publish verification in
[checks].ValidatePublish. Prepare commands run in protected main
immediately before push. They may warm ignored caches, but they must not leave
tracked or other non-ignored drift behind.
Once explicit publish checks are configured, mq bypasses inherited local
pre-push hooks for the final push. Do not rely on hook side effects in
protected main; put publish-time prep and validation in mainline.toml.
Use mq status --json to see whether publish is currently in prepare,
validate, or push before deciding how to recover a slow publish.
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 main in the feature worktree and continuing work there
git merge <branch> from the protected branch worktree as the default path
git push origin main as a substitute for mq
- 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.