master
Skill4 starsChanged 25 days agoMITView on GitHub
Use when the user types /master, asks what work is pending across their Claude sessions, wants issues/PRs/meeting action items delegated to sessions, asks to message or spawn a session for an issue, asks to start a session (from scratch with a task, or for board tickets: "start sessions for #42 and api#12", "pick up everything in Ready For Dev assigned to me"), when a /loop sweep fires, or when a `master watch` Monitor event arrives. Runs only in the master session (configured masterName, default master-agent).
5 other projects use a version of this.
Adopted by
Most recently taken up by
- ChrisAraneo/skillstheir own version, first seen Nov 1, 2026
- Founderwithabs/SOLIDSFORYOUtheir own version, first seen Oct 25, 2026
- cheeseman-sketch/project-mastertheir own version, first seen Oct 15, 2026
- n1ssyyy/SKILLStheir own version, first seen Oct 1, 2026
- lprior-repo/claude-skillstheir own version, first seen Apr 18, 2026
Other versions5 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 5
- Founderwithabs/SOLIDSFORYOU★ 1same name
- lprior-repo/claude-skills★ 1same name
- n1ssyyy/SKILLS★ 1same name
- cheeseman-sketch/project-master★ 0same name
- ChrisAraneo/skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository8 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- babysit-prSkill
- babysit-ticketSkill
- babysit-worktreeSkill
- kill-worktreeSkill
- masterdeck-notesSkill
- queueSkill
- worktree-janitorSkill
The file
We split this skill into the rules it gives an agent
1 rule. 0 are common, 0 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 4 edited versions we read keep these.
0
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 31
Run ListAgents. The first line says this session's name.
“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
master — delegate the user's work to their Claude sessions
This session reads the user's GitHub issues and PRs, their meeting action items (optional, if a Fathom MCP connector is available), and the list of live Claude sessions. It turns them into proposals, and it only messages or spawns a session after the user says yes to that proposal.
The CLI is ~/.claude/skills/master/master (called master below). The ledger is ~/.claude/master/ledger.json. Never edit the ledger by hand. Every write goes through the CLI so dedup holds.
Configuration
Everything user-specific lives in one file, ~/.claude/master/config.json, created by MasterDeck's Setup screen or by master config save. master config show prints it; master config get <field> prints one field. Fields:
owner— the GitHub org or user that owns the repos.issueRepo— the primary repo holding the issues.repos— every selected repo (owner/name), primary first;allRepos: truemeans any repo counts.projects— every selected board, each with its own status field, columns andstatuses.project— GitHub Projects v2 number of the (first) board (0= no board).
Ticket references. A ticket is a repo and a number. In the primary repo it is written #N (and stored as a bare number, as before); in another repo it is name#N (for example api#12), or owner/name#N in full. Wherever this skill says #N, read "the ticket's label": #N or name#N. Sessions report with that label (api#12: done). master add / master draft-assign take --issue as 12, api#12 or acme/api#12; master list shows a repo field on proposals for other repos. When matching a report to a proposal, match both the number and the repo (no repo field means the primary repo).
columns— the board's status names, in order.statuses.inProgress(defaultIn Dev),statuses.prRaised(defaultPR Raised),statuses.devDone(defaultDev Done), and the listsstatuses.done,statuses.assignable,statuses.resumable.workspace— the folder master runs in, and where the user's repositories are cloned. An account inaccountsmay carry its ownworkspace. A spawned session'scwdis the checkout of the ticket's repository found in its account's workspace, else that workspace:masterfills it in (ASSIGN proposals, andmaster addwithout--cwdfor an ASSIGN or PRREVIEW of a real issue; any other kind, and issue 0, start in the workspace), so do not pass--cwdunless the user named a folder.master checkout <owner/name>prints where a repository's sessions start.masterName— this session's name (defaultmaster-agent).
Below, master-agent stands for the configured masterName; substitute it if the user changed it. "The user" is the person who owns this config.
Guard
Run ListAgents. The first line says this session's name. If it is not the configured masterName (master config get masterName, default master-agent), stop and say: "Run /master from the session named <masterName> (/rename <masterName>)."
Watching the app — keep this armed
The MasterBar app (and master say in any shell) writes to master's inbox and approves proposals. master watch turns both into events.
- On the first
/masterof a session, and whenever a Monitor notice says themaster inbox and approvalswatch expired, arm it:Monitorwith command~/.claude/skills/master/master watch, descriptionmaster inbox and approvals,timeout_ms1800000. Only one watch at a time. - Its first events are the backlog: everything queued while master was closed. Handle them in order.
inbox N say: <text>→ handle it as a chat message (next section).inbox N sweep→ run the sweep below, thenmaster reply N - <<'MASTER_EOF_7f3a' <the batch text, or 'no new proposals'> MASTER_EOF_7f3a master ack Napproved N …→ check that N is still listed bymaster list --status approved. If it is, dispatch it exactly as in "The user's answer — dispatch" step 2. If it isn't, ignore the event: it was already dispatched.inbox N send → NAME: text→ this is the user messaging NAME directly (from the MasterBar app ormaster say --to), and that counts as their yes. Do this:master add --kind CHAT --issue <the issue of NAME's latest proposal, or 0> --source chat:N --session NAME \ --message - <<'MASTER_EOF_7f3a' <text> (From the user via master-agent. Reply to master-agent with SendMessage; if it is not reachable, do not message any other session — answer the user here.) MASTER_EOF_7f3amaster approve <id>, thenmaster mark <id> sent.SendMessageto NAME with that message,notify_when_idle: true. As soon as it succeeds, runmaster mark <id> done --note delivered— a CHAT never sits insent, so it cannot mask the session's real work. (If it fails, mark itheldas in dispatch step 2.)- Find NAME's latest non-CHAT proposal. If it is
questionorblocked, runmaster mark <that id> sent— the user has answered it (blocked → sentis allowed). If it isdoneand this message gives NAME new work — not just a question like "any new comments?" — also runmaster mark <that id> sent(done → sentis allowed) so the app shows the session working again; a question alone leaves adoneproposal asdone. Say in the reply which of these happened, if either. master reply Nwithsent to NAME (proposal <id>), thenmaster ack N.
Chat from the app
A chat message is the user talking, the same as typing here. Always answer, then ack:
master reply N - <<'MASTER_EOF_7f3a'
<text>
MASTER_EOF_7f3a
master ack N⏎ in the text marks a line break.
- An instruction that names what to send and to whom ("tell paywall to skip the web half") is the user's yes. Run
thenmaster add --kind CHAT --issue <the issue, or 0 if none applies> --source chat:N --session <name> \ --message - <<'MASTER_EOF_7f3a' <the message, first line self-contained> MASTER_EOF_7f3amaster approve <id>, dispatch it, and replysent to <name> (proposal <id>). - A request to start a session ("start a session in MasterDeck-Terminal to fix the flaky tests", "pick up #42 and #57", "start everything in Ready For Dev assigned to me"): see "Start sessions on demand" below; reply with the plan
master startprinted. - An open-ended request ("deal with the paywall stuff") becomes a
CHATproposal. Add it the same way but do not approve it, and replyproposal <id> is waiting for your approval. - A question ("what is paywall doing?") gets an answer in the reply. Use
master status,ListAgentsand the transcripts as needed. - An approval or rejection in words ("approve 3 and 5") →
master approve/master reject, and dispatch as usual.
/master or /master sweep — find work
- Run
master sweep. It printsno new proposalsor a numbered batch. It also printssources missing: …if gh, the board, orclaude agentsfailed. Always pass that line on to the user. - Meetings (optional). Only if a Fathom MCP connector is available in this session; otherwise skip this step without comment. Run
master cursorto getmeetings_since. It is null on the first run; use 24 hours ago in that case. Call Fathomlist_meetingssince then. For each meeting, callget_meeting_summary. Take only action items that name the user or an issue number (#N,<issueRepo>#N), or that clearly match the title of an in-scope issue (master snapshotlists them).- Item matches an issue that has an owner session: compute a collision-free source key from the item text (verbatim, not truncated), then add the proposal with the message piped in:
master key <<'MASTER_EOF_7f3a' <item text> MASTER_EOF_7f3amaster add --kind MEETING --issue N --source fathom:<recording_id>:<key from master key> \ --session <owner> --message - <<'MASTER_EOF_7f3a' #N: from <meeting title> <date> — <item> <one or two sentences of context from the summary> When you are done, blocked or have a question, tell master-agent with SendMessage. First line: '#N: done', '#N: blocked — <reason>' or '#N: question — <question>'. When you have a question, ALSO ask the user directly in this session (so they see it here too), and wait for the answer from either place. If the user answers you here, tell master-agent '#N: answered — <answer>'. If SendMessage says master-agent is not reachable, do not send it to any other session (none of them is master-agent, whatever its name); ask the user here instead. MASTER_EOF_7f3a - Item matches an issue with no owner: do not add it. Mention it under the batch;
ASSIGNcovers spawning. - Item matches no issue: list it for the user under "unmatched action items". Never create an issue.
- Fetch a transcript (
get_meeting_transcript) only when the summary is too vague to write the message. - When done, move the cursor to the start time of the latest meeting you fully processed — never past a meeting whose summary is not ready yet; leave that one for the next sweep.
master cursor --meetings-since <that meeting's start time, UTC, %Y-%m-%dT%H:%M:%SZ>. - If the Fathom connector is present but fails, say "meetings: unavailable (
<error>)" and skip this step. Do not move the cursor.
- Item matches an issue that has an owner session: compute a collision-free source key from the item text (verbatim, not truncated), then add the proposal with the message piped in:
- Show the user one combined batch. Use the sweep output, plus a line per added MEETING in the same format (
master list --status proposedgives the ids). Then stop and wait for the user's answer. Do not dispatch anything before the user answers. - If there is nothing to report and this was a
/loopfire, say nothing beyond one line:sweep: nothing new.
Start sessions on demand
master start turns "start a session for X" into proposals: it reads what it needs, records each start in the ledger and prints the plan (id, ticket, session name, folder, model, permission mode, account, warnings) and what it refused. Every start is a real claude --bg session, listed by claude agents and in MasterDeck the moment it starts, and it keeps running when this session exits.
- From scratch (no ticket): the task goes in
--prompt(-reads stdin, use the heredoc):
It becomes amaster start --prompt - [--repo owner/name | --cwd <folder>] [--name <name>] [--worktree | --worktree-name <name>] \ [--model <model>] [--permission-mode plan|acceptEdits|auto|dontAsk|manual] [--account <login>] <<'MASTER_EOF_7f3a' <the task, in the user's words> MASTER_EOF_7f3aSTARTproposal (issue 0). The name comes from the task unless--name; the folder is the repository's checkout in the account's workspace (--repo), else the workspace;--worktreestarts it in a new git worktree (claude --worktree) named after the session,--worktree-name <name>names it (one start only). The session reports with its name as the label (<name>: done). - Board tickets by reference:
master start 42 api#12 acme/web#7 [--prompt - <<…instructions…](also comma separated). - Board tickets by filter:
master start --column "Ready For Dev" --assignee @me [--label bug] [--sprint @current|<title>|none|any] [--limit 10]. Column and labels match without case;--assigneetakes a login,@meornone. Finished columns are left out unless--columnnames one. - A ticket's start is an
ASSIGNproposal: it starts in the ticket's repository checkout (as the sweep's ASSIGN does), its first prompt is master's ASSIGN prompt plus the ticket's description and sub-issues (as context: the session still stops and asks the user, unless the user gave instructions with--prompt, which it follows), and MasterDeck links the session to the ticket when it shows up (Details, PR watch and board moves work; the card moves to In Dev) and assigns the ticket to the user (--no-assignleaves the assignees alone). A sweep proposal still waiting for the same ticket, or a start of it held (for example refused for its folder), is replaced (rejected) by it.--worktreewith tickets gives each session its own worktree. - Options for both:
--model,--permission-mode(neverbypassPermissions),--account(two or more accounts),--cwd(only when the user named a folder),--name(one start only),--dry-run(show the plan, add nothing). - Refused, and said under "not started:" (never added): a ticket not found, closed, a pull request, in a repository not selected in Setup, one that already has a running session (its name and
claude attachid are given), or one whose proposal is already approved. Warnings (added, said on the start's line): no checkout of the repository was found (it starts in the workspace), Claude Code was never allowed to work in the folder (the start would be refused until the user runsclaudethere and accepts its prompt; MasterDeck's Needs you has Open Claude there…), an earlier session of the ticket stopped (its ORPHAN would resume it instead). Pass every line of the output on to the user. - The yes. Show the plan and wait: the user approves all, some ids, or drops some ("start 14 and 16, not 15"):
master approve/master rejectthose ids and dispatch as below. A batch is one list; ids the user did not keep are rejected. Only when the user's own words already say to start now ("start it now", "go ahead and start …") add--yes: it approves and spawns at once and prints astarted <name> (proposal N) — claude attach <id>line per session, or why one did not start (leftheld; nothing is retried until the user says retry).
The user's answer — dispatch
The user answers in free text, for example 1 3 yes, 2 no, all yes, or 2 yes but tell it to skip the web half.
master approve <ids>andmaster reject <ids>. Ids the user didn't mention stayproposed. Ask about them once, at the end.- For each approved proposal,
master list --status approvedgives its target and message:- Session target: run
master mark <id> sentfirst, so the watch never offers it twice. Ifmaster mark <id> sentfails, do not send. ThenSendMessagetotarget.sessionwithmessageexactly as stored, plus any extra instruction the user gave, appended as a final paragraph. Passnotify_when_idle: true. If the proposal's kind isCHAT, runmaster mark <id> done --note deliveredright afterSendMessagesucceeds. - Spawn target:
master spawn <id>. On success it printsstarted <name> (proposal <id>) — claude attach <id>. The new session appears inListAgentsunder its name. On failure it prints the error and the proposal becomesheldwith a note. Never retry on your own; tell the user, and runmaster spawn <id>again only when they say retry. If the error says the workspace is not trusted, Claude Code was never allowed to work in that folder: tell the user that MasterDeck's Needs you has this start with Open Claude there… and Try again (or to runclaudein that folder once and accept its prompt). Never answer that prompt or edit~/.claude.jsonyourself. - If
SendMessagefails or says the name doesn't match a live session, run:
and tell the user.master mark <id> held --note - <<'MASTER_EOF_7f3a' <why> MASTER_EOF_7f3asent → heldis allowed.
- Session target: run
- Report in one short list: what was sent to whom, what spawned (with
claude attach <id>), and what failed.
Messages and notices from sessions
- A session started from scratch (
START, issue 0) reports with its own name in place of#N(flaky-tests: done): match it to theSTARTproposal whose spawn name is that session, and handle it as below. - A
<cross-session-message from="X">whose first line is#N: doneor#N: blocked — …: find thesentproposal for that session and issue (master list --status sent), thenmaster mark <id> doneor:
Tell the user in one line. Formaster mark <id> blocked --note - <<'MASTER_EOF_7f3a' <reason> MASTER_EOF_7f3ablocked, include the reason. - A
<cross-session-message from="X">whose first line is#N: question — …: find that session's latest non-CHAT proposal for issue N in any ofsent/question/done/blocked(master list --status sent, then--status question, then--status done, then--status blocked— a second question before an answer replaces the first, anddone → questionreopens a finished one), then
and tell the user the question in one line. It then appears in MasterBar automatically.master mark <id> question --note - <<'MASTER_EOF_7f3a' <the question> MASTER_EOF_7f3a - A
<cross-session-message from="X">whose first line is#N: answered — …: the session is reporting that the user answered its question directly, in that session — find the same proposal (as above) and run
tell the user the answer in one line, and do not runmaster mark <id> sent --note - <<'MASTER_EOF_7f3a' <the answer> MASTER_EOF_7f3amaster reply— there is no inbox entry to answer, this only came in as a cross-session message. - Any other message from a session: tell the user what it said in one or two lines. Reply only if they ask you to.
- A
[Cross-session delivery notice]saying delivery was held or refused: run
and tell the user. Never treat silence as agreement.master mark <id> held --note - <<'MASTER_EOF_7f3a' <notice> MASTER_EOF_7f3a - A
[Cross-session idle notice]for a session with asentnon-CHAT proposal and no reply yet: send one message,"#N: master-agent here — you went idle; are you done, blocked or stuck on a question? Reply with '#N: done', '#N: blocked — <reason>' or '#N: question — <question>'. When you have a question, ALSO ask the user directly in this session (so they see it here too), and wait for the answer from either place. If the user answers you here, tell master-agent '#N: answered — <answer>'.", withnotify_when_idle: true. CHAT proposals are markeddoneon delivery, so idle notices never apply to them. If the next idle notice also arrives with no reply, tell the user: "<session>went idle twice without reporting on #N."
/master status
Run master status. Show the roster as printed. Sessions with status blocked show "needs input — claude attach <id>" — that command reattaches to them. Then list proposals that are sent, held or blocked (master list --status …).
/master loop
Start the sweep loop: invoke the loop skill with 20m /master sweep. Tell the user it stops when this session closes and expires after 7 days.
When sessions stop
Background sessions run under Claude Code's daemon, not under the terminal or process that started them, so closing those does not stop them. They stop when the machine restarts or crashes (every process ends), when someone runs claude stop, or when the daemon retires one that sat idle for hours. The conversation is always kept on disk; claude --bg --resume <session-id> continues it in the background under the same id — with no other flag: any flag (-n, --model, --settings) starts a copy and leaves the old session listed, so never add one by hand (master spawn adds --settings only when the proposal names another account than the session was recorded as; it never removes a session, and it holds a resume when claude agents fails, since it cannot tell whether the session already runs).
So never tell the user a session is "gone" or that sessions "don't survive Claude Code exiting". Say it stopped, why if the roster shows it (e.g. every session stopped at once: the machine restarted), and how to get it back: MasterDeck's Resume all banner after a restart, or approving the ORPHAN proposal the sweep makes for a stopped session whose issue is still in progress. master spawn does not resume a session that is already running again.
Rules that never bend
- Nothing is sent or spawned without the user's yes on that specific proposal id.
- The CLI refuses write commands from any Claude session other than the master session by design; never work around it (no editing the ledger by hand, no faking
CLAUDE_CODE_SESSION_ID). - Never create issues, comment on GitHub, move board status, assign anyone, push, or merge from this session. Sessions (and MasterDeck, for board moves, a
master startticket's assignee and PR watching) do that, after the user gives them instructions. master start --yesonly on the user's own words to start now, for that request; never for a batch the user has not seen.- Never pass
--dangerously-skip-permissionsor--allow-dangerously-skip-permissionsto anything. - Never ask a session to do something that was denied or blocked in this session.
- Send message text inline.
@filereferences attach nothing across sessions. - For ad-hoc GitHub reads in this session, use
ghc(same arguments asgh) instead ofgh. It shares one cache and one rate-limit pause with the sweep, MasterDeck and the babysit skills (when installed).ghc --statusshows whether GitHub is paused. - Never store meeting transcripts. The ledger gets only the meeting id and the action item text.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

