Brainstorm a new idea/objective into a Nazgul spec and tasks, then optionally run it. Interactive design front-end — produces a per-idea spec and a ready-to-execute task plan.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add OrodruinLabs/nazgul --skill plan --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Plan?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/orodruinlabs-plan)More formats (shields.io, HTML) on the badges page.
---
name: nazgul:plan
description: Brainstorm a new idea/objective into a Nazgul spec and tasks, then optionally run it. Interactive design front-end — produces a per-idea spec and a ready-to-execute task plan.
argument-hint: "[\"idea or objective\"]"
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Task, ToolSearch
metadata:
author: Jose Mejia
---
# Nazgul Plan
## Examples
- `/nazgul:plan` — brainstorm a new idea interactively, then generate spec + tasks
- `/nazgul:plan "add OAuth login"` — seed the brainstorm with an idea
- After it finishes: `/nazgul:start` runs the generated tasks (asks which mode)
## Arguments
$ARGUMENTS
## Current State
- Config: !`cat nazgul/config.json 2>/dev/null | head -3 || echo "NOT_INITIALIZED"`
- Discovery: !`test -f nazgul/context/discovery-summary.md && echo "done" || echo "NOT_RUN"`
- Existing objectives: !`ls nazgul/context/objectives/*-spec.md 2>/dev/null | wc -l | tr -d ' '`
- Open tasks: !`ls nazgul/tasks/TASK-*.md 2>/dev/null | wc -l | tr -d ' '`
## Instructions
Format all output per `${CLAUDE_PLUGIN_ROOT}/references/ui-brand.md`.
**Pre-load:** run `ToolSearch` with query `select:AskUserQuestion` (deferred tool) before any step that prompts.
### Pre-flight
1. If `nazgul/config.json` is missing: "Nazgul not initialized. Run `/nazgul:init` first." and STOP.
2. If `$ARGUMENTS` (the `## Arguments` value) is the bare literal `$ARGUMENTS`, STOP: "Skill argument substitution failed — plugin bug, do not proceed."
3. If an objective is already active — `nazgul/config.json → objective` is non-null AND any task in `nazgul/tasks/TASK-*.md` has status READY / IN_PROGRESS / IN_REVIEW / IMPLEMENTED / CHANGES_REQUESTED — STOP and tell the user: "An objective is already active with open tasks. Finish it (`/nazgul:start`), or archive with `/nazgul:reset`, before planning a new idea." Do NOT overwrite objective identity or append to `objectives_history` while a loop is active.
### Display Banner
```text
─── ◈ NAZGUL ▸ PLAN ────────────────────────────────────
```
### Step 1: Brainstorm the idea
Run an interactive design dialogue (one focused question at a time, or batched with `AskUserQuestion`). Seed from the `$ARGUMENTS` idea if provided. Cover:
- **Purpose** — what problem does this idea solve, and for whom?
- **Scope & constraints** — what's in, what's explicitly out, hard constraints.
- **Success criteria** — how do we know it's done/working?
- **Objective type** — feature / bugfix / refactor / greenfield / migration (Nazgul's types).
Don't over-ask; once you can state the idea crisply, confirm your understanding back to the user and get a yes before writing anything.
### Step 2: Write the per-idea spec
1. Own the objective identity (mirror what `/nazgul:start`'s Objective Derivation stores). Order matters:
- **First** compute the feature id from the CURRENT history: `FEAT-NNN` where `NNN = ((.objectives_history // []) | length) + 1`, formatted `FEAT-%03d` (so the first idea is `FEAT-001`). Use `(.objectives_history // [])` to tolerate a missing or non-array field. Set `feat_display_id` to the same value (or the board issue id if a board is connected). Do this BEFORE appending to `objectives_history`, so the array length still reflects prior objectives.
- **Then** write ALL of these to `nazgul/config.json` in ONE jq update (tmp + mv), so config is never left partially written:
- `.objective` = the one-line objective statement
- `.feat_id` = the computed `FEAT-NNN`
- `.feat_display_id` = same (or board issue id)
- `.afk.commit_prefix` = `"feat(<feat_display_id>):"`
- append to `.objectives_history`: `{ feat_id, objective, started_at }` where `started_at` = `date -u +%Y-%m-%dT%H:%M:%SZ` — type-guard the field before `+` so a missing or non-array value never errors:
```bash
jq --arg id "$FEAT_ID" --arg obj "$OBJECTIVE" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'.objective=$obj | .feat_id=$id | .feat_display_id=$id
| .afk.commit_prefix=("feat(" + $id + "):")
| .objectives_history = ((if (.objectives_history | type) == "array" then .objectives_history else [] end) + [{feat_id:$id, objective:$obj, started_at:$ts}])' \
nazgul/config.json > nazgul/config.json.tmp && mv nazgul/config.json.tmp nazgul/config.json
```
(If a board is connected and you use an issue id as `feat_display_id`, set `.feat_display_id` and the `commit_prefix` from that instead.)
2. Create `nazgul/context/objectives/` if missing. Write `nazgul/context/objectives/<feat_id>-spec.md` with: title, the objective statement, purpose, scope (in/out), constraints, success criteria, and an objective-type line. This is the per-idea spec the doc-generator reads as PRIMARY for this objective.
3. Show the spec and get the user's approval before generating tasks (HITL checkpoint). On changes, revise and re-confirm.
### Step 3: Generate tasks (reuse the pipeline)
1. Scrub the superseded objective's transient artifacts (the pre-flight check above already guarantees no open tasks): run `"$CLAUDE_PLUGIN_ROOT/scripts/scrub-stale-review-artifacts.sh" --for-new-objective "$FEAT_ID"`. This archives stale `nazgul/reviews/` and `nazgul/learning/proposed-rules.md`/`.distilled` from the completed prior objective into `nazgul/archive/`, so `nazgul:doc-generator`/`nazgul:planner` never read stale verdicts or rules as current. It no-ops cleanly if nothing is stale.
2. Every dispatch below opens with the runtime-state root. Each of these agents' input contract (RULES.md §21) STOPs when the brief omits it and `branch.main_worktree_path` is unreadable — and that key is still `null` on a project that has never run `/nazgul:start`. Resolve `ROOT` once from this checkout (`git rev-parse --show-toplevel`, the directory holding `nazgul/config.json`) and prepend these two lines to each prompt, `$ROOT` expanded to the absolute path:
```text
Dispatch brief: <main_worktree_path> = /abs/path/to/project. Nazgul config: /abs/path/to/project/nazgul/config.json.
Address every runtime-state path under that root, absolute and verbatim — your cwd is not it.
```
3. If `$ROOT/nazgul/context/discovery-summary.md` is absent, dispatch `nazgul:discovery` (Task tool) to profile the project.
4. Dispatch `nazgul:doc-generator` (Task tool) — it reads the per-idea spec as PRIMARY and produces feature-scoped docs.
5. Dispatch `nazgul:planner` (Task tool) — it decomposes the objective into task manifests under `$ROOT/nazgul/tasks/`.
6. If any of these fail, report the failure and STOP (do not offer to run a broken plan).
7. Show the generated task list (ids + titles) for the user to review.
### Step 4: Offer to run
Ask with `AskUserQuestion`: "Spec + N tasks ready. Start now?"
- **Yes** → invoke `/nazgul:start` (it will resolve the run mode — flag / your `default_mode` / a prompt).
- **No** → end with a Next Up block: "Tasks ready. Run `/nazgul:start` when you want to execute."
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!