From klause-workflow
Use when the user wants to schedule a Linear project's tickets across worktree queues, distribute work based on dependencies, or says "schedule this project" / "assign tickets to worktrees" / "plan the work" / "save this schedule". Takes a Linear project, builds a dependency-aware assignment plan, then lets the user save the plan, enqueue it immediately, or cancel.
How this skill is triggered — by the user, by Claude, or both
Slash command
/klause-workflow:scheduleThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Schedule a Linear project's tickets across available Klausemeister worktree queues using dependency-aware load balancing.
Schedule a Linear project's tickets across available Klausemeister worktree queues using dependency-aware load balancing.
/schedule <project-name> [--name <schedule-name>]
Use the Linear MCP to get all issues in the project:
list_projects to find the project by name. If not found, stop with an error.list_issues with the project ID. Include relations to get blocks/blockedBy.Done or Canceled state.Call listWorktrees (Klausemeister MCP) to get all tracked worktrees with their current queue state. The response includes repoId and gitWorktreePath per entry.
Filter to the current repo. Klausemeister tracks worktrees across multiple repos and they often share names (alpha, beta, ...). Scheduling a Klause-team ticket onto another repo's epsilon would be silently wrong. To scope:
git rev-parse --show-toplevel. If the result contains /.worktrees/<name> strip back to the parent — that is the canonical repo root.gitWorktreePath is inside the canonical repo root (i.e. gitWorktreePath starts with <repo-root>/ or equals <repo-root>). This catches both the main checkout and any .worktrees/* siblings.<repo-root>). Create one before scheduling."If listWorktrees itself returns nothing, stop: "No worktrees found in Klausemeister."
From the listWorktrees response, collect all issueLinearId values across all inbox, processing, and outbox items. These issues are already scheduled and should be excluded.
Build the input JSON for the scheduling script:
{
"tickets": [
{
"id": "<linear UUID>",
"identifier": "<KLA-123>",
"title": "<issue title>",
"weight": <1|2|3>,
"blockedBy": ["<linear UUID>", ...]
}
],
"worktrees": [
{
"worktreeId": "<klausemeister worktree ID>",
"name": "<worktree name>",
"currentLoad": <sum of weights already in inbox>
}
]
}
Weight mapping from Linear estimate or complexity label:
simple label or estimate <= 1 -> weight 1medium label or estimate 2-3 -> weight 2complex label or estimate >= 4 -> weight 3currentLoad: Sum the weights of all inbox items for each worktree. Use the same weight mapping — look up each inbox item's issue in the Linear data to determine its weight.
blockedBy: Only include blocker IDs that are in the schedulable set (non-done issues in this project). External blockers are ignored by the algorithm.
Run the Python script with the prepared JSON piped to stdin:
echo '<input JSON>' | python3 klause-workflow/scripts/schedule.py
The script path is relative to the repo root. Parse the JSON output.
The algorithm distributes tickets across worktrees in topological waves
(see KLA-201)
— cross-worktree dependencies are allowed, and each item in the plan carries
its level: int (wave index, 0 = no in-set blockers). Runtime safety is
provided by KLA-200:
getNextItem skips inbox items whose blockers aren't done yet, so a meister
never claims an item whose dependency is still in flight on a different worktree.
If there are cycles, report them prominently:
Dependency cycles detected (these tickets cannot be scheduled):
- KLA-1 -> KLA-2 -> KLA-3 -> KLA-1
Then present the assignment plan as a table:
Assignment Plan
Worktree Queue Position Ticket Title Weight alpha 1 KLA-42 ... 2 alpha 2 KLA-43 ... 1 beta 1 KLA-44 ... 3 Load distribution: alpha: 3, beta: 3
If there are unscheduled tickets (beyond cycles), list them with reasons.
If there are external blockers (blockers outside this project), note them.
Present the three-way choice:
Choose an action:
save store this schedule in Klausemeister, do not enqueue
(find it later as a pill under the repo header in the sidebar)
run store and enqueue immediately (today's behavior)
cancel discard, do nothing
Do NOT proceed without explicit user choice.
Before making any MCP calls, determine the schedule name:
--name <string> to /schedule, use that string.<linear-project-name> · <YYYY-MM-DD HH:mm> in the user's local timezone.savesaveSchedule with the assignment plan. The payload shape is:
{
"name": "<schedule name>",
"assignments": [
{ "issueLinearId": "<UUID>", "targetWorktreeId": "<worktreeId>", "queuePosition": <int> }
]
}
Saved as schedule "<name>" (<id>). Open it from the sidebar pill under <repo-name> to view the gantt or run it later.runsaveSchedule with the same payload as above; capture the returned scheduleId.runSchedule({ scheduleId }).runSchedule's response.listWorktrees to confirm the updated queue state and include a summary.cancelStop immediately. Make no MCP calls and report: Cancelled — nothing changed.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub selfishfishi/klausemeister --plugin klause-workflow