Agent skill
workflow-manifest
Install this agent skill to your Project
npx add-skill https://github.com/leeovery/agentic-workflows/tree/main/skills/workflow-manifest
SKILL.md
Workflow Manifest
CLI tool for reading and writing work unit manifest files. Single source of truth for all workflow state.
{work_unit} is the top-level directory name under .workflows/ (e.g., dark-mode, payments-overhaul). {topic} is the item within a phase (e.g., discussion name, spec name, plan name). For feature/bugfix they share the same value; for epic they're distinct.
Invocation
node .claude/skills/workflow-manifest/scripts/manifest.cjs <command> [args]
Dot-Path Syntax
Every command follows: command path [field] [value]
The path joins work unit, phase, and topic with dots. The field is always a separate argument. Segment count in the path determines the access level:
| Segments | Level | Path | Field | Resolves to |
|---|---|---|---|---|
| 1 | Work unit | my-epic |
work_type |
work_type |
| 2 | Phase | my-epic.planning |
format |
phases.planning.format |
| 3 | Topic | my-epic.discussion.auth-flow |
status |
phases.discussion.items.auth-flow.status |
Project-Level Access
The reserved path prefix project routes to the project manifest (.workflows/manifest.json). For project paths, the field is embedded in the dot-path — no separate field argument:
MANIFEST="node .claude/skills/workflow-manifest/scripts/manifest.cjs"
# Read:
$MANIFEST get project # Full project manifest
$MANIFEST get project.work_units # All work units
$MANIFEST get project.defaults.plan_format # Specific default
# Write (field path + value):
$MANIFEST set project.defaults.plan_format local-markdown
$MANIFEST push project.defaults.project_skills ".claude/skills/golang-pro"
# Check existence:
$MANIFEST exists project.defaults.plan_format
# Delete:
$MANIFEST delete project.defaults.plan_format
Work-Unit, Phase, and Topic Access
MANIFEST="node .claude/skills/workflow-manifest/scripts/manifest.cjs"
# Work-unit level (1 segment):
$MANIFEST get {work_unit} [field]
$MANIFEST set {work_unit} field value
$MANIFEST delete {work_unit} field.path
$MANIFEST exists {work_unit} [field.path]
# Phase level (2 segments):
$MANIFEST get {work_unit}.{phase} [field]
$MANIFEST set {work_unit}.{phase} field value
$MANIFEST delete {work_unit}.{phase} field.path
# Topic level (3 segments):
$MANIFEST get {work_unit}.{phase}.{topic} [field.path]
$MANIFEST set {work_unit}.{phase}.{topic} field.path value
$MANIFEST delete {work_unit}.{phase}.{topic} field.path
$MANIFEST init-phase {work_unit}.{phase}.{topic}
# Wildcard (3 segments, * as topic):
$MANIFEST get {work_unit}.{phase}.* [field.path]
$MANIFEST exists {work_unit}.{phase}.* [field.path]
# Existence checks (always exit 0, outputs true/false):
$MANIFEST exists {work_unit}
$MANIFEST exists {work_unit} [field.path]
$MANIFEST exists {work_unit}.{phase} [field.path]
$MANIFEST exists {work_unit}.{phase}.{topic} [field.path]
# Management (unchanged):
$MANIFEST init name --work-type type --description "..."
$MANIFEST list [--status s] [--work-type t]
Phase-level access (2-segment path) — accesses fields directly on the phase object (phases.{phase}.{field}). Useful for phase-wide metadata like format, analysis_cache, etc.
Topic-level access (3-segment path) — routes through items: phases.{phase}.items.{topic}.{field}. Used for per-topic state like status, gate modes, etc.
Wildcard topic (* as third segment) — collects values from all topics in a phase. Supported by get and exists only. For epic: iterates all items. For feature/bugfix: returns the single item.
Internal routing (CLI handles, skills don't know):
my-epic.discussion.auth-flow status→phases.discussion.items.auth-flow.status
Naming Constraints
- Work unit names must not contain dots — dots are the path separator
- Work unit names must not match phase names (
research,discussion,investigation,specification,planning,implementation,review) - Work unit names must not be reserved —
projectis reserved for project-level manifest access
Commands
init
Create a new work unit manifest.
node .claude/skills/workflow-manifest/scripts/manifest.cjs init <name> --work-type <epic|feature|bugfix|quick-fix|cross-cutting> --description "..."
Creates .workflows/<name>/manifest.json with identity fields and empty phases. Errors if manifest already exists. Rejects names containing dots or matching phase names.
get
Read a value or subtree. Three levels:
Work-unit level (1 segment):
# Full manifest
node .claude/skills/workflow-manifest/scripts/manifest.cjs get <name>
# Scalar value — output raw (no quotes)
node .claude/skills/workflow-manifest/scripts/manifest.cjs get <name> status
# Subtree — output as formatted JSON
node .claude/skills/workflow-manifest/scripts/manifest.cjs get <name> phases
Phase level (2 segments):
# Whole phase object
node .claude/skills/workflow-manifest/scripts/manifest.cjs get <name>.discussion
# Specific field within phase
node .claude/skills/workflow-manifest/scripts/manifest.cjs get <name>.planning format
Topic level (3 segments):
# Specific field within topic
node .claude/skills/workflow-manifest/scripts/manifest.cjs get <name>.discussion.auth-flow status
# Nested field path
node .claude/skills/workflow-manifest/scripts/manifest.cjs get <name>.specification.auth-flow sources.auth-api.status
Wildcard topic (3 segments, * as topic):
# Collect status from all topics in a phase
node .claude/skills/workflow-manifest/scripts/manifest.cjs get '<name>.discussion.*' status
Output is a JSON array of {topic, value} objects:
[
{ "topic": "auth-flow", "value": "completed" },
{ "topic": "data-model", "value": "in-progress" }
]
For feature/bugfix, returns a single-element array (topic matches work unit name). Errors if the phase has no items.
Errors to stderr with non-zero exit if the path does not exist.
set
Write a value. Three levels:
Work-unit level (1 segment):
node .claude/skills/workflow-manifest/scripts/manifest.cjs set <name> description "Updated description"
node .claude/skills/workflow-manifest/scripts/manifest.cjs set <name> status completed
Phase level (2 segments):
node .claude/skills/workflow-manifest/scripts/manifest.cjs set <name>.planning format local-markdown
node .claude/skills/workflow-manifest/scripts/manifest.cjs set <name>.research analysis_cache '{"checksum":"..."}'
Topic level (3 segments):
node .claude/skills/workflow-manifest/scripts/manifest.cjs set <name>.discussion.auth-flow status completed
node .claude/skills/workflow-manifest/scripts/manifest.cjs set <name>.planning.auth-flow task_list_gate_mode auto
Values are parsed as JSON first (for arrays, objects, numbers, booleans), falling back to string. Validates structural fields:
- work_type:
epic,feature,bugfix,quick-fix,cross-cutting - phase names:
research,discussion,investigation,scoping,specification,planning,implementation,review - phase statuses: per-phase valid values (see Validation section)
- gate modes:
gated,auto - work unit status:
in-progress,completed,cancelled
delete
Remove a key from the manifest. Three levels:
Work-unit level (1 segment):
node .claude/skills/workflow-manifest/scripts/manifest.cjs delete <name> <field.path>
Phase level (2 segments):
node .claude/skills/workflow-manifest/scripts/manifest.cjs delete <name>.research analysis_cache
Topic level (3 segments):
node .claude/skills/workflow-manifest/scripts/manifest.cjs delete <name>.implementation.auth completed_tasks
Errors if the path does not exist. Deletes the key entirely (not just setting to null). Parent keys are preserved.
list
Enumerate work units by scanning .workflows/ for manifest.json files. Skips dot-prefixed directories (.archive, .state, .cache).
# All work units
node .claude/skills/workflow-manifest/scripts/manifest.cjs list
# Filter by status
node .claude/skills/workflow-manifest/scripts/manifest.cjs list --status in-progress
# Filter by work type
node .claude/skills/workflow-manifest/scripts/manifest.cjs list --work-type epic
# Combined filters
node .claude/skills/workflow-manifest/scripts/manifest.cjs list --status in-progress --work-type feature
Output: JSON array of manifest objects.
init-phase
Register a topic within a phase. Creates phases.<phase>.items.<topic> with { "status": "in-progress" }. Requires a 3-segment path.
node .claude/skills/workflow-manifest/scripts/manifest.cjs init-phase <name>.discussion.<topic>
Errors if item/phase already exists.
push
Append a value to an array field. Creates the array if it doesn't exist. Errors if the field exists but is not an array. Three levels:
Work-unit level (1 segment):
node .claude/skills/workflow-manifest/scripts/manifest.cjs push <name> tags "v1"
Phase level (2 segments):
node .claude/skills/workflow-manifest/scripts/manifest.cjs push <name>.research analysis_cache.files "a.md"
Topic level (3 segments):
node .claude/skills/workflow-manifest/scripts/manifest.cjs push <name>.implementation.{topic} completed_tasks "{topic}-1-1"
node .claude/skills/workflow-manifest/scripts/manifest.cjs push <name>.implementation.{topic} completed_phases 1
node .claude/skills/workflow-manifest/scripts/manifest.cjs push <name>.review.{topic} reviewed_tasks "{topic}-1-1"
key-of
Find the key in an object whose value matches. Useful for reverse lookups — e.g., finding an internal ID from an external ID in task_map.
# Find internal ID from external ID
node .claude/skills/workflow-manifest/scripts/manifest.cjs key-of <name>.planning.<topic> task_map {external_id}
Output: the matching key to stdout (e.g., portal-1-1). Errors if the value is not found or the path is not an object.
exists
Check whether a work unit, field, or phase entry exists. Always exits 0 — both true and false are valid results. Outputs true or false to stdout, nothing to stderr.
# Does the work unit exist?
node .claude/skills/workflow-manifest/scripts/manifest.cjs exists <name>
# Does a field path exist? (work-unit level)
node .claude/skills/workflow-manifest/scripts/manifest.cjs exists <name> work_type
# Does a phase-level field exist?
node .claude/skills/workflow-manifest/scripts/manifest.cjs exists <name>.discussion
# Does a topic entry exist?
node .claude/skills/workflow-manifest/scripts/manifest.cjs exists <name>.discussion.auth-flow
node .claude/skills/workflow-manifest/scripts/manifest.cjs exists <name>.discussion.auth-flow status
# Wildcard: does any topic in the phase have this field?
node .claude/skills/workflow-manifest/scripts/manifest.cjs exists '<name>.discussion.*'
node .claude/skills/workflow-manifest/scripts/manifest.cjs exists '<name>.discussion.*' status
If the work unit doesn't exist and a deeper path is requested, outputs false (no error). Actual usage errors (missing args, invalid phase name) still use die().
Wildcard topic (* as third segment) — outputs true if any topic in the phase matches (has the field, or exists at all if no field specified), false otherwise. Always exits 0.
project (legacy convenience)
List or get work units from the project manifest. Prefer the project.* dot-path syntax via get/set/exists/delete/push for new usage. The project list --type filter is retained as a convenience.
List work units:
# All registered work units
node .claude/skills/workflow-manifest/scripts/manifest.cjs project list
# Filter by work type
node .claude/skills/workflow-manifest/scripts/manifest.cjs project list --type cross-cutting
Output: one name per line. No output if none found.
Get work unit entry:
node .claude/skills/workflow-manifest/scripts/manifest.cjs project get <name>
Output: work_type: <type>. Errors if not found.
The project manifest is automatically updated when init creates a new work unit.
Project Defaults
Project-wide settings are stored in the defaults section of the project manifest. These serve as suggestions when starting new topics — the user always confirms or overrides. The chosen value is saved back as "most recently used".
| Default | Description | Used by |
|---|---|---|
plan_format |
Output format for plans (e.g., tick, linear, local-markdown) |
Planning |
project_skills |
Array of skill paths used during implementation | Implementation |
linters |
Array of linter configs used during TDD cycle | Implementation |
The cascade is: project defaults (suggestion) → topic level (actual value used). There is no phase-level storage.
Validation
The CLI validates structural values to prevent invalid state:
| Field | Valid Values |
|---|---|
work_type |
epic, feature, bugfix, quick-fix, cross-cutting |
status (work unit) |
in-progress, completed, cancelled |
Item status (research) |
in-progress, completed |
Item status (discussion) |
in-progress, completed |
Item status (investigation) |
in-progress, completed |
Item status (scoping) |
in-progress, completed |
Item status (specification) |
in-progress, completed, superseded, promoted |
Item status (planning) |
in-progress, completed |
Item status (implementation) |
in-progress, completed |
Item status (review) |
in-progress, completed |
Gate modes (*_gate_mode) |
gated, auto |
Status is always tracked at the item level (phases.{phase}.items.{topic}.status), never at the phase level.
Output Conventions
- Scalar values: raw to stdout, no quotes (e.g.,
in-progress,completed) - Subtrees and lists: formatted JSON to stdout
- Errors: message to stderr, non-zero exit code
Notes
- File locking:
.lockfile next to manifest, exclusive create (wxflag), 30s stale detection. Prevents concurrent session conflicts. - Atomic writes: write to
.tmpthenfs.renameSync. No partial writes. - Auto-creation:
initcreates the work unit directory. Phase directories are created by skills when they enter that phase, not by the CLI. - Domain routing: The dot-path syntax lets skills use logical coordinates. The CLI resolves to the correct internal JSON path — all work types use
itemsstructure.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
update-workflow-explorer
Audit and update workflow-explorer.html flowcharts to match the current codebase logic. Reads all command, skill, and agent source files, compares against the 4 data structures in the HTML file, reports drift, and applies updates. Use when workflow logic has changed and the explorer needs syncing.
create-output-format
Scaffold a new planning output format adapter. Creates a format directory with all required files implementing the output format contract.
continue-feature
workflow-review-entry
workflow-planning-process
workflow-start
Didn't find tool you were looking for?