Workflows

Generated automatically at build time from the madtea repository - do not edit here. Source: docs/reference/cli-workflows.md.

Destruction model for prune (content-verified, never force-delete) and branch delete: ADR 0029.

CLI Commands

madtea adr check

Verify ADR numbering, index bijection, and links (exit 1 on drift)

madtea adr new

Create the next ADR record and index row (number from origin)

FlagTypeDefaultDescription
--offlineboolfalseNumber from the local tree instead of the origin default branch
--titlestringRecord title (defaults to a title derived from the slug)
--trackingstringTracking reference recorded in the header (e.g. an issue or epic)

madtea finish

Commit, push, create PR, merge, and return to default branch

FlagTypeDefaultDescription
--branchstringFinish a named branch instead of the current checkout (skips the commit step; the branch must exist locally and be ahead of the default)
--closeboolfalseClose linked issue (this is the default behavior — accepted for compatibility)
--close-linkedboolfalseForce-close all branch-detected issues (skip dependency safety check)
--closesstringSlice[]Issue numbers to explicitly close (repeatable, comma-separated)
--filesstringSlice[]Stage these paths before committing, in this same finish call (comma-separated or repeatable; mirrors madtea add). Mutually exclusive with –no-commit and –branch
--no-closeboolfalseReference branch-detected issues only, never close them
--no-commitboolfalseSkip commit step (use when changes are already committed)
--owner-repostringComplete a branch that lives only on the forge (owner/repo), with no local checkout: opens the PR, merges, and deletes the remote branch. Requires –branch; mutually exclusive with –files/–no-commit
--summarystringPR summary (use @file to read from file, @- for stdin)
--summary-filestringRead PR summary from file (use - for stdin, avoids shell quoting issues)

madtea init

Create a new repository and push initial commit

FlagTypeDefaultDescription
--descriptionstringRepository description
--dirstringDirectory to initialize (default: ./)
--orgstringCreate repository under an organization
--privateboolfalseMake repository private

madtea orchestrate

Merge PRs in batch with verification and bisect failure isolation

FlagTypeDefaultDescription
--max-failuresint2Stop after N culprits found and reverted (0 = unlimited, capped at 50 as a safety limit)
--no-revertboolfalseSkip bisection and revert on failure; just report pass/fail
--strict-overlapboolfalseError and refuse to start if any PRs touch the same files
--stylestringMerge strategy (merge, rebase, rebase-merge, squash, fast-forward-only); default honors the repo’s configured merge style
--verifystringShell command to run after each merge (executed via sh -c with full local shell access)
--verify-timeoutduration5m0sTimeout for each verify command execution

madtea orchestrate reconcile

Merge a moved base branch into an open PR’s head (no force-push)

FlagTypeDefaultDescription
--abortboolfalseDiscard an in-progress reconcile merge (git merge –abort)
--continueboolfalseComplete an in-progress reconcile merge (after resolving + staging conflicts) and push
--owner-repostringForge repository (owner/repo) whose PR number is meant; default derives it from the checkout’s origin

madtea prune

Clean up stale remote refs and merged branches

FlagTypeDefaultDescription
--countboolfalsePrint the number of prunable branches (dry run; exits 0 regardless of count)
--delete-branchesboolfalseActually delete merged branches (default is dry run)
--dry-runboolfalseShow what would be deleted without deleting (this is the default)
--remoteboolfalseAlso delete remote branches via Gitea API

madtea secret-exec

Execute a command with the Forgejo/Gitea token injected as an environment variable

MCP Tools

madt_adr

Create and consistency-check architecture decision records (ADRs) in any repo that carries a docs/adr/ tree.

Output schema: declared

One tool, action-dispatched. Set action to one of:

action="check"

Verify the ADR tree — unique numbers, file/index bijection, and resolvable links — and report every inconsistency; a clean tree returns OK. Returns an error when drift is found so it wires straight into a gate.

action="new"

Create the next ADR record and index row; the number is resolved from the origin default branch, NOT the local tree, so a diverged branch cannot reissue a landed number. Fails if origin is unreachable — pass offline=true to number from the local tree instead.

Required: slug

Optional: title, tracking, offline

Example:

madt_adr(action="new", slug="origin-first-forge-resolution")

madt_clone

Clone a Forgejo/Gitea repository - public repos succeed without credentials; private repos require madtea auth login first. When credentials are configured, per-repo credentials are set up automatically. Use this instead of raw git clone with a credentialed URL (which would leak the token into git config/history). The result names the resolved forge host and warns when the repo is a read-only mirror.

Output schema: declared

ParameterTypeRequiredDescription
branchstringnoClone specific branch
depthintegernoShallow clone depth
directorystringnoTarget directory (default: repo name)
repositorystringyesRepository in owner/repo format or full URL

madt_finish

Complete a feature branch: commit, push, create PR, merge, return to mainline. Must be run from a FEATURE branch (errors on the default branch). The commit step commits the staged changes — or stages files=[…] itself in THIS call (mirrors madt_add/madt_commit; mutually exclusive with no_commit/branch=), collapsing the separate madt_commit step. There is no blanket “stage everything” mode (the removed all=true/git add -A): declare the paths in files=[…], or stage via madt_add first (check with madt_status), or set no_commit=true if already committed; mixed staged/unstaged trees silently drop unstaged edits from the PR. Merges to the DEFAULT branch — ONLY for branch completion, NOT for intermediate work (use madt_commit for mid-branch checkpoints; push with madt_push). It ALWAYS merges: for a review-only PR without merging, use madt_push then madt_prs action=create draft=true instead — and do not call finish on a branch that already has an open PR. Branch-detected issues (e.g. ‘feat/issue-321-thing’) auto-close iff they have no open dependencies in Forgejo/Gitea — issues that look like parent epics (have open deps) are referenced instead. Override with closes/close_linked/no_close. Set branch= to finish a branch by name without checking it out: the branch must exist and be ahead of the default; use this for a branch in a linked worktree (same repo, no dir=) without disturbing its checkout. Pass dir= to target another local git repo by path (validated, any path); a same-repo dir changes nothing. A FOREIGN dir requires branch= (no checkout-mode finish cross-repo) and defaults no_close=true (override via closes=/close_linked=). When the server’s working directory is itself NOT a git repo (a session launched in a plain parent dir that merely contains clones), a repo whose toplevel is strictly UNDER that dir is in-scope, not foreign: it is finished via branch= (there is no checkout to stage in a non-git cwd) but keeps normal branch-detected auto-close (no forced no_close=true). Without dir, targets the server’s working directory; in a detected multi-repo workspace with no dir it fails closed regardless (set MADTEA_CALLER_REPO). Set owner_repo=owner/repo (no dir, no checkout) to complete a forge-only branch (e.g. one committed by madt_files new_branch=) via a pure API path: open the PR, merge (honoring default_merge_style), delete the remote branch. Requires branch=; mutually exclusive with dir=/files=/no_commit; defaults no_close=true (override via closes=/close_linked=). For the parallel-agent worktree flow (commit in a linked worktree with madt_commit dir=, then finish it by name with branch= from the mainline checkout), see madt_help(topic=“worktrees”).

Output schema: declared

ParameterTypeRequiredDescription
branchstringnoName of a local branch to finish instead of the current checkout (e.g. ‘feat/issue-42-auth’). When set, the commit step is skipped and that branch is pushed, PR-opened, and merged by name — intended for branches checked out in a linked worktree so you can finish them without switching the worktree’s checkout. The branch must exist (in dir=, if set) and have commits ahead of the default, and must not itself be the default branch. Required — and the ONLY allowed form — when dir= names a FOREIGN repo: a foreign target never checks out or stages a stranger’s working tree.
close_linkedbooleannoForce-close every branch-detected issue, skipping the dependency safety check. Default behavior already auto-closes issues with no open dependencies — only set this to true to override that check. Also overrides the foreign-target no_close=true default when dir= names a repo outside the server’s working directory.
closesstringnoComma-separated issue numbers to explicitly close on merge (e.g. ‘218,221’). These are closed without consulting the dependency API — use only when you are sure the work fully resolves them. Also overrides the foreign-target no_close=true default when dir= names a repo outside the server’s working directory.
dirstringnoAbsolute path to a LOCAL git repo to finish, for a repo other than the server’s working directory (validated: resolved, must be an existing git repository; no workspace-roots confinement). A repo that turns out to be the SAME one (or one of its linked worktrees) changes nothing — finish behaves exactly as it would without dir=. A genuinely FOREIGN repo is allowed only in the no-checkout branch= form, and defaults no_close to true unless closes= or close_linked=true is also set.
files[]string | stringnoPaths to stage before committing, in this SAME finish call (files or directories, e.g. [‘docs/’, ‘main.go’]) — mirrors madt_add/madt_commit’s files, so a caller need not round-trip through madt_add first. There is no blanket “stage everything” mode (the removed all/git add -A) — name the paths you mean. Mutually exclusive with no_commit and branch=.
no_closebooleannoReference branch-detected issues (Refs) but never close them. Use when the branch implements one slice of a parent epic and you don’t want any auto-close behavior. This is the DEFAULT automatically when dir= names a FOREIGN repo — a generic branch name must never auto-close a stranger’s tracker entry on a coincidental issue-number match; pass closes= or close_linked=true to still close in that repo.
no_commitbooleannoSkip commit step if changes are already committed
owner_repostringnoowner/repo naming a repository on the forge to complete a branch in with NO local checkout of any kind (e.g. ‘acme/widgets’) — the remote-only form for a branch that lives only on the forge, such as one committed by madt_files new_branch=. It resolves the default branch, opens the PR from the remote branch, merges honoring the repo’s default_merge_style, and deletes the remote branch, all via the API with no clone. Requires branch=; mutually exclusive with dir=/files=/no_commit; defaults no_close=true (override via closes=/close_linked=), like a foreign dir.
raw_jsonbooleannoReturn raw JSON (the {“kind”:“ledger”,…} step envelope) instead of the compact agent line.
summarystringyesPR body summary describing the changes (use @file to read from file, @- for stdin)
titlestringyesCommit message subject and PR title — the one-line conventional-commit summary applied to both the commit and the PR (e.g. ‘feat: add auth’).

madt_init

Bootstrap a new repository: create remote, init local, stage everything (git add -A), commit, push. Set org to create under an organization; omit org for a personal repo. Only for brand-new work: fails if the target directory already has commits — to publish an EXISTING local repo, create the remote with madt_repos action=create, then madt_remote_add, then push. Creates a README.md if the directory is empty.

Output schema: declared

ParameterTypeRequiredDescription
descriptionstringnoRepository description
dirstringnoDirectory to initialize (default: ./)
namestringyesRepository name to create
orgstringnoOrganization to create the repo under (omit for personal repo)
privatebooleannoMake repository private
raw_jsonbooleannoReturn raw JSON (the {“kind”:“ledger”,…} step envelope) instead of the compact agent line.

madt_orchestrate

Merge PRs in batch with verification and bisect failure isolation, OR reconcile a conflicted PR whose base moved. BATCH-MERGE mode (prs + verify): merges all PRs first, runs verify once, then bisects to find and revert culprits on failure. Already-merged PRs are skipped (safe to re-run). Requires a local checkout that is ON the default branch with a CLEAN working tree — the run pulls the current branch after merging, checks out commits during bisection (fails on a dirty tree), and creates revert branches from HEAD. All listed PRs must be open and non-draft: a closed or draft PR aborts the entire run before any merge (only already-merged PRs are skipped). SECURITY: verify runs via sh -c with full local shell access (env vars, files, network) and may execute multiple times during bisection — only pass trusted commands, never untrusted or user-supplied strings. RECONCILE mode (reconcile=): the push-compatible, force-push-free recovery when madt_finish/merge fails because the base branch moved under an open PR — checks out the PR’s head and merges the latest base INTO it, so the follow-up push needs no force. A clean merge is pushed and steers you back to finish/merge; a conflict returns the conflicted-file work-list plus continue/abort rails: resolve, madt_add the files, then reconcile_continue=true or reconcile_abort=true. Reconcile also takes dir=/owner_repo= (see param docs) for foreign-repo PRs: reconciled in a linked worktree holding the head; a foreign PRIMARY checkout is refused.

Output schema: declared

ParameterTypeRequiredDescription
dirstringnoReconcile mode only: absolute path to the LOCAL git repo/worktree to reconcile in (validated: an existing git repository). For a FOREIGN repo’s PR pass a LINKED WORKTREE holding the PR’s head branch; a foreign PRIMARY checkout is refused and never touched. Defaults to the working directory.
max_failuresintegernoStop after N culprits found and reverted. Default: 2. Note: over MCP, 0 is indistinguishable from unset and is treated as the default (2) — it is NOT unlimited; pass 50 explicitly for the maximum allowed.
merge_stylestringnoMerge strategy: merge, squash, rebase, rebase-merge, fast-forward-only
no_revertbooleannoSkip bisection and revert on failure; just report pass/fail (leaves broken merges on main)
owner_repostringnoReconcile mode: owner/repo naming which repo’s PR number is meant — the fix for a same-numbered PR resolving in the wrong repo. Defaults to dir’s origin when omitted.
prsstringnoComma-separated PR numbers to merge in order (e.g. ‘101,102,103’)
reconcilestringnoPR number whose base branch moved (e.g. ‘1956’): switches to reconcile mode and merges the latest base branch INTO that open PR’s head branch — the push-compatible, force-push-free recovery. Mutually exclusive with prs/verify.
reconcile_abortbooleannoDiscard an in-progress reconcile merge (git merge –abort), restoring the head branch to its pre-merge state (e.g. true).
reconcile_continuebooleannoComplete an in-progress reconcile merge after you resolved and staged the conflicts with madt_add (git merge –continue + push) (e.g. true).
strict_overlapbooleannoError and refuse to start if any PRs touch the same files (default: warn but proceed)
verifystringnoShell command to run for verification (executed via sh -c with full local shell access)
verify_timeoutstringnoTimeout for each verify command (e.g. ‘5m’, ’30s’). Default: 5m

madt_prune

Clean up stale remote refs and delete branches merged into the default branch. Default is dry run; set delete_branches=true to delete. Set remote=true to also delete merged remote twins and merged remote-only branches (orphans), then remove the now-stale remote-tracking refs. Local branches whose content already landed in the default branch via a squash/cherry-pick merge (squash_merged) are content-verified, so they too ARE deleted under delete_branches=true - including their remote twins under remote=true - and listed as would-delete on a dry run. Branches held by a linked worktree are skipped and reported, never attempted-and-errored. To delete one specific (possibly unmerged) remote branch, use madt_branches_remote action=delete instead.

Output schema: declared

ParameterTypeRequiredDescription
delete_branchesbooleannoActually delete merged branches (default: dry run showing what would be deleted without deleting)
raw_jsonbooleannoReturn raw JSON (the prune result: merged_branches, remote_orphans, deleted counts, dry_run), also incl. squash_merged, instead of the formatted text line.
remotebooleannoAlso delete remote branches via Gitea API

Canonical source: docs/reference/cli-workflows.md in the madtea repo.