skills/start/SKILL.md
Start or resume a Nazgul autonomous development loop. Use when user says "start nazgul", "run nazgul", "begin development", "resume the loop", or passes an objective for new work. Auto-detects project state — no arguments needed.
npx skillsauth add OrodruinLabs/nazgul nazgul:startInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
/nazgul:start — Auto-detect project state and resume or begin work/nazgul:start "add user authentication" — Start a new objective/nazgul:start --afk --max 20 — Run autonomously for up to 20 iterations/nazgul:start --yolo — Full autonomous mode with no permission prompts/nazgul:start --yolo --task-pr — YOLO mode with stacked per-task PRs$ARGUMENTS
cat nazgul/config.json 2>/dev/null || echo "NOT_INITIALIZED"jq -r '.objective // "none"' nazgul/config.json 2>/dev/null || echo "none"cat nazgul/context/discovery-summary.md 2>/dev/null || echo "NOT_RUN"cat nazgul/context/project-spec.md 2>/dev/null | head -3 || echo "NONE"cat nazgul/context/project-classification.md 2>/dev/null | head -5 || echo "NOT_CLASSIFIED"ls nazgul/docs/*.md 2>/dev/null | wc -l | tr -d ' 'grep -rl 'Status.*\(READY\|IN_PROGRESS\|IN_REVIEW\|IMPLEMENTED\|CHANGES_REQUESTED\)' nazgul/tasks/TASK-*.md 2>/dev/null | wc -l | tr -d ' 'grep -rl 'Status.*DONE' nazgul/tasks/TASK-*.md 2>/dev/null | wc -l | tr -d ' 'ls nazgul/tasks/TASK-*.md 2>/dev/null | wc -l | tr -d ' 'ls .claude/agents/generated/ 2>/dev/null || echo "No reviewers generated"head -20 nazgul/plan.md 2>/dev/null || echo "No plan yet"sed -n '/^## Recovery Pointer/,/^## /p' nazgul/plan.md 2>/dev/null | head -7 || echo "none"grep -rn 'TODO\|FIXME\|HACK\|XXX' --include='*.ts' --include='*.js' --include='*.py' --include='*.rb' --include='*.go' --include='*.rs' --include='*.java' --include='*.md' . 2>/dev/null | head -10 || echo "none"cat nazgul/context/test-strategy.md 2>/dev/null | head -5 || echo "none"Format all output per references/ui-brand.md — use stage banners, status symbols, spawning indicators, and display patterns defined there.
$ARGUMENTS may contain:
--afk, --hitl, --max N, --yolo, --task-pr, --continueIf --yolo flag is present:
afk.enabled: true and afk.yolo: true in config.json--task-pr flag is also present: set afk.task_pr: true in config.json--dangerously-skip-permissions:
YOLO mode requires --dangerously-skip-permissions. Restart with:
claude --dangerously-skip-permissions
Then re-run: /nazgul:start --yolo --max N
Read nazgul/config.json → models to determine which model to assign each pipeline agent. When delegating via the Agent tool, pass the model parameter:
| Pipeline Agent | Config Key | Default |
|-------------------|-----------------------|---------|
| Discovery | models.discovery | sonnet |
| Doc Generator | models.docs | sonnet |
| Planner | models.planning | opus |
| Implementer | models.implementation | sonnet |
| Review Gate | models.review | sonnet |
If the models section is missing from config.json, use "sonnet" as the fallback for all agents.
Fast Mode: If models.fast_mode_implementation is true, implementation and specialist agents use fast mode for ~2.5x speed improvement. This trades higher token cost for faster iteration cycles — useful for large objectives with many tasks.
When launching Nazgul, use session naming for identification:
claude -n "nazgul-<feat_display_id>" (e.g., claude -n "nazgul-FEAT-003")nazgul-impl-TASK-NNN, nazgul-review-TASK-NNNLoop counters are per-run state, not objective state. A stale counter left over from a previous run will silently brick the loop: the stop hook hits its max-iteration or consecutive-failure gate on the very first iteration and exits 0 (allows the stop) instead of re-dispatching — so the loop "never continues" even though READY tasks exist.
Before delegating to any agent, reset the counters. The [ -f ... ] guard makes this a safe no-op in the NOT_INITIALIZED case (no nazgul/config.json yet), so the command is always safe to run regardless of ordering:
[ -f nazgul/config.json ] && \
jq '.current_iteration = 0 | .safety.consecutive_failures = 0 | .safety._prev_done_count = 0' \
nazgul/config.json > nazgul/config.json.tmp && mv nazgul/config.json.tmp nazgul/config.json
This applies to every loop-starting path (ACTIVE_LOOP, DOCS_READY, DISCOVERY_DONE, FRESH, New Objective Override). Do not skip it for those states.
Evaluate the preprocessor data above. Work through this state machine top-to-bottom — take the FIRST state that matches:
Detection: Config shows "NOT_INITIALIZED"
Action: Tell the user: "Nazgul not initialized. Run /nazgul:init first."
Stop here.
Detection: Active tasks > 0 (any task with status READY, IN_PROGRESS, IN_REVIEW, IMPLEMENTED, or CHANGES_REQUESTED) Action: Auto-resume the loop.
nazgul/plan.md → Recovery Pointernazgul/checkpoints/nazgul/config.json → branch.feature.
git checkout <feature> if not on itbranch.base
b. Store pwd as branch.main_worktree_path
c. Slugify objective → feat/<display_id>-<slug>
d. Compute feature ID: FEAT-NNN from objectives_history.length + 1. If board connected, prefer issue number as display_id.
e. Store feat_id and feat_display_id in config.json. Set afk.commit_prefix to feat(<display_id>):.
f. git checkout -b feat/<display_id>-<slug>
g. Create worktree dir, store paths in configDetection: Total tasks > 0 AND active tasks == 0 AND done tasks == total tasks Action: All tasks are done.
grep -H -E '(^\- \*\*Status\*\*:|^## Status:)' nazgul/tasks/TASK-*.md). If any task is not
DONE, this state was mis-detected — report the actual statuses and route to
the appropriate state instead. Never emit NAZGUL_COMPLETE, and never write
DONE entries to plan.md, based on remembered transitions: status writes can
be blocked by guards, so claims must come from reads that happened after the
last write.nazgul/config.json → branch.feature and branch.base
b. If feature branch exists:
git push -u origin <feature-branch>gh pr create --base <base-branch> --head <feature-branch> --title "<objective> (<feat_display_id>)" --body "<task summary>"Detection: Docs generated > 0 AND total tasks == 0 Action: Documents exist but no plan yet — regenerate documents from current context, then run the planner.
branch.feature is null):
a. Capture current branch as branch.base
b. Store pwd as branch.main_worktree_path
c. Slugify objective → feat/<display_id>-<slug>
d. Compute feature ID: FEAT-NNN from objectives_history.length + 1. If board connected, prefer issue number as display_id.
e. Store feat_id and feat_display_id in config.json. Set afk.commit_prefix to feat(<display_id>):.
f. git checkout -b feat/<display_id>-<slug>
g. Create worktree dir, store paths in configDetection: Discovery summary is NOT "NOT_RUN" AND docs generated == 0 AND total tasks == 0 Action: Discovery ran but no docs or plan yet.
branch.base
b. Store pwd as branch.main_worktree_path
c. Slugify objective → feat/<display_id>-<slug>
d. Compute feature ID: FEAT-NNN from objectives_history.length + 1. If board connected, prefer issue number as display_id.
e. Store feat_id and feat_display_id in config.json. Set afk.commit_prefix to feat(<display_id>):.
f. git checkout -b feat/<display_id>-<slug>
g. Create worktree dir, store paths in configDetection: None of the above matched (config exists but discovery hasn't run) Action: Fresh project — need discovery + everything.
branch.base
b. Store pwd as branch.main_worktree_path
c. Slugify objective → feat/<display_id>-<slug> (lowercase, non-alnum to hyphens, max 50 chars)
d. Compute feature ID: FEAT-NNN from objectives_history.length + 1. If board connected, prefer issue number as display_id.
e. Store feat_id and feat_display_id in config.json. Set afk.commit_prefix to feat(<display_id>):.
f. git checkout -b feat/<display_id>-<slug>
g. Create worktree dir at ../<project>-nazgul-worktrees/, store path in confignazgul/context/project-profile.md for "## GitHub Integration" sectionjq -r '.board.enabled' nazgul/config.json is false):
/nazgul:board github later)gh project create --owner [owner] --title "Nazgul: [repo]", then bash scripts/board-sync-github.sh setup [number]bash scripts/board-sync-github.sh setup [number]/nazgul:board explicitly)When no objective exists in config.json and none was provided as an argument, Nazgul derives one from project signals. The approach depends on whether this is a greenfield project.
If classification is GREENFIELD (from nazgul/context/project-classification.md) OR the codebase has fewer than 10 source files:
→ Go to Greenfield Stack Scaffolding (below)
Otherwise → continue with signal scanning:
Gather signals in priority order:
nazgul/context/project-profile.md for stated goals, purposeproject.test_command) and capture failuresgit log --oneline -10 for patterns like "WIP:", "started:", incomplete workgh issue list --limit 5 --state open (if gh is available)HITL mode — Present discovered signals as an interactive menu:
Nazgul scanned your project and found potential work:
1. [signal description] (source: TODOs in src/payments/)
2. [signal description] (source: 2 failing tests in auth.test.ts)
3. [signal description] (source: GitHub issue #12)
4. Something else — tell me what you want to build
Which objective should I pursue?
Wait for user selection. If user picks "something else", use their input.
AFK mode — Auto-select the highest-priority signal:
/nazgul:start 'your objective' to specify one."Write the derived/selected objective to config.json:
{
"objective": "[the derived objective]",
"objective_set_at": "[ISO 8601 timestamp]"
}
Append to objectives_history array.
For greenfield projects, Nazgul first checks for a project spec (see Step 0 in references/greenfield-scaffolding.md), then runs an interactive stack selection, tool pre-flight check, and configuration workflow. Consult references/greenfield-scaffolding.md for the full process including project spec detection, stack selection menus, AFK defaults, tool configuration steps, infrastructure scaffolding, and config storage.
For the tool detection commands table (check commands and install commands per platform), see references/tool-preflight.md.
When the user explicitly passes an objective string in $ARGUMENTS:
You have an active objective: "[stored objective]" with [N] tasks remaining.
Options:
a. Archive it and start the new objective
b. Cancel and resume current work (/nazgul:start)
nazgul/archive/[YYYY-MM-DD-HHMMSS]/ directoryobjectives_history in config.json with completed_at and plan_archived_toobjective, objective_set_at, append to objectives_history--continue Flag (backward compatibility)If --continue is present, behave exactly as ACTIVE_LOOP state (loop counters are reset by the mandatory Reset Loop Counters step).
If no active tasks found: "Nothing to continue. Run /nazgul:start to auto-detect what to do."
Before dispatching the implementer, check for wave-based parallel execution:
nazgul/plan.md for a ## Wave Groups sectionnazgul/config.json for parallelism.wave_execution and parallelism.enabledIf wave groups exist AND wave_execution is true AND parallelism is enabled:
a. Identify the current wave — the lowest wave number with READY tasks b. Collect all READY tasks in that wave c. If only 1 task: dispatch implementer normally (no parallelism overhead) d. If 2+ tasks: dispatch parallel Agent Teams:
git worktree add <worktree_dir>/TASK-NNN -b feat/<display_id>/TASK-NNN <feature-branch>nazgul-impl-wave-[N]parallelism.max_parallel_teammates from configgit merge --no-ff feat/<display_id>/TASK-NNNgit merge --abort, mark conflicting task BLOCKED with conflict detailsIf wave groups don't exist OR wave_execution is false:
Safety rules:
max_parallel_teammatesafk.enabled: true in configfeat(FEAT-003): or feat(#42):)--task-pr — enables stacked per-task PRs targeting feature branch (legacy behavior)<worktree_dir>/TASK-NNN with branch feat/<display_id>/TASK-NNN--dangerously-skip-permissionstesting
Human acceptance testing — structured verification that work actually works. Run standalone or integrated in HITL review cycle.
devops
Task lifecycle management — skip, unblock, add, prioritize, info, and list tasks. Use when you need to manage individual tasks in the Nazgul pipeline.
development
Check the current state of a Nazgul autonomous loop. Use when asked about loop progress, task status, iteration count, review board status, or how the Nazgul loop is going.
development
Run a cleanup and simplification pass on all files modified during a Nazgul loop. Use after a Nazgul loop completes to improve code clarity without changing functionality.