Why does Claude Code skip steps in my process?
Because a process written in a prompt or in CLAUDE.md is context, not a rule. Claude reads it, weighs it against everything else in the conversation, and decides what applies right now.
Anthropic says this plainly in the memory docs: Claude treats CLAUDE.md files "as context, not enforced configuration", and to block an action regardless of what Claude decides you use a PreToolUse hook instead. The same docs warn that longer files reduce adherence, and that when two instructions contradict each other Claude may pick one arbitrarily.
So a ten-step checklist pasted into CLAUDE.md is a suggestion that competes for attention with the code, the task and the chat. Step 7 gets skipped not because the model is careless, but because nothing in the system makes step 7 a condition for step 8.
- A process in the prompt is guidance. It works most of the time.
- A process in a hook, a permission rule or a workflow engine is structure. It works every time it is checked.
- Pick the strength per step: most steps need guidance, a few need a hard stop.
sourcesClaude Code docs: memoryClaude Code docs: hooks
in the prompt read by the AI
Shipped. Nobody said yes.
as a gate checked by the engine
Waiting for you.
What are the ways to enforce a process in Claude Code?
Claude Code has five native layers, from soft to hard: CLAUDE.md, skills, subagents, permission rules and hooks. Dynamic workflows script several agents in code. An external workflow engine over MCP adds state and gates that outlive the session.
| Option | What it does | Enforced? | Best for |
|---|---|---|---|
| CLAUDE.md | Loads facts and conventions into every session | No, context only | Build commands, layout, naming |
| Skill (SKILL.md) | A named procedure loaded when invoked with /name | No, but it arrives at the right moment | One repeatable multi-step task |
| Subagent | A separate context with its own prompt and tools | Tool list is enforced, steps are not | Review, research, focused roles |
| Permission rules | allow, ask or deny per tool and command pattern | Yes, deny beats ask beats allow | Commands that must never or always need a yes |
| Hooks | Your script runs on events like PreToolUse and Stop | Yes, exit 2 or a deny decision blocks | Preconditions: tests passed, branch is right |
| Dynamic workflows | A script that orchestrates subagents | The script order is enforced | Parallel fan-out inside one session |
| Workflow engine over MCP | Holds the process outside the model, one step at a time | Yes, gates are evaluated on every advance | Long processes, sign-offs, many agents and people |
sourcesClaude Code docs: memoryClaude Code docs: skillsClaude Code docs: subagentsClaude Code docs: permissionsClaude Code docs: hooksClaude Code docs: Dynamic workflows
How do I turn my process into a Claude Code skill?
Write the steps once in a SKILL.md file and invoke it by name. Only the skill name and description load at session start; the full steps load when the skill runs, so a long procedure stops costing context on every unrelated task.
- 1
Create the skill folder
Project skills live in .claude/skills/<name>/SKILL.md and are shared through git. Personal skills go in ~/.claude/skills.
mkdir -p .claude/skills/ship-fix - 2
Write the steps as an ordered list
Number the steps, name the commands, and end with the place where Claude must stop and ask. Setting disable-model-invocation to true means only you can start it, with /ship-fix.
--- name: ship-fix description: Ship a bug fix. Use when the user asks to fix and ship a bug. disable-model-invocation: true --- Follow these steps in order. Do not skip one. 1. Reproduce the bug with a failing test. Show the failure. 2. Fix the code. Keep the change minimal. 3. Run the full test suite: npm test 4. Write a summary of the root cause and the fix. 5. Stop and ask me before you push. - 3
Run it
Type /ship-fix in Claude Code, with the bug as the argument. Claude loads the steps and works through them in this session.
/ship-fix the refund total rounds down on EUR orders - 4
Check what loaded
Use /context to see what is in the context window. After compaction, Claude Code re-attaches the first 5,000 tokens of each skill you invoked, so keep the important steps near the top.
sourcesClaude Code docs: skills
How do I stop Claude Code at a step it must not skip?
Use a hook or a permission rule for the steps that must never be skipped. A skill tells Claude what to do; a PreToolUse hook runs your own script before the tool call and can refuse it, whatever Claude decided.
The example below refuses git push until a test marker file exists. Exit code 2 blocks the call and sends your stderr message back to Claude. Permission rules sit alongside: deny is checked first, then ask, then allow. One caveat from Anthropic's docs: command patterns match the text, so a deny on "git push" does not catch "git -C . push". Use hooks for checks that need logic.
- 1
Write the hook script
It reads the tool call as JSON on stdin and decides. Make it executable with chmod +x.
#!/usr/bin/env bash # .claude/hooks/require-tests.sh # PreToolUse hook: refuse "git push" until the test marker exists. cmd=$(jq -r '.tool_input.command // ""') if [[ "$cmd" == git\ push* ]] && [[ ! -f .claude/state/tests-passed ]]; then echo "Run the test suite and record a pass before pushing." >&2 exit 2 fi exit 0 - 2
Register it in .claude/settings.json
The matcher picks the tool. Add permission rules in the same file for the simple cases.
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/require-tests.sh" } ] } ] }, "permissions": { "allow": ["Bash(npm test *)", "Bash(git commit *)"], "deny": ["Bash(git push --force *)"] } } - 3
Gate the finish too
A Stop hook can return {"decision": "block", "reason": "Build failed, fix errors before continuing"} to keep Claude working. Check the stop_hook_active field in the input so it cannot loop forever.
sourcesClaude Code docs: hooksClaude Code docs: permissions
What if my process has many steps, branches and sign-offs?
Then a single session is the wrong place to hold it. Skills and hooks live inside one Claude Code session on one machine; a process that spans days, people and several agents needs state that outlives the chat.
Claude Code's Dynamic workflows (a JavaScript script in .claude/workflows that orchestrates subagents) help with fan-out inside one session. Anthropic lists their limit: no mid-run user input, and "for sign-off between stages, run each stage as its own workflow." Sign-off, hand-off to a person and resume tomorrow are exactly what a process engine is for.
| Need | Inside Claude Code | Workflow engine over MCP |
|---|---|---|
| Steps in order | Skill text, followed by the model | Cursor held by the engine, one step at a time |
| Human sign-off mid-process | A permission ask in the live session | A gate that waits, hours or days, for a person |
| Branches and loops | Written as prose or script logic | Decisions, sub-workflows and loops back to a step |
| Same process in Codex, Cursor or a teammate | Copy the files per tool | One definition, any MCP client |
| Record of who moved it | Session transcript | Field-level audit on tasks and workflow instances |
sourcesClaude Code docs: Dynamic workflows
How does ConvOps make Claude Code follow a process?
ConvOps holds the process as a graph of workflows and gives Claude Code one step at a time over MCP. Claude asks for the current step, does it, and asks to advance. The engine checks the gate on that step against real state, and an unmet gate leaves the cursor where it is.
The agent never sees the other steps, so there is nothing to skim past. Policies attach rules to the active step. Advancing can carry context, stored as a memory linked to the task, so the next session or the next agent starts where this one stopped.
- 1
Connect Claude Code
One command. OAuth opens in your browser on first use.
claude mcp add --transport http convops https://mcp.convops.app/ - 2
Put the process in a workflow
Write the steps once in ConvOps, or start from a template. Mark the step that needs a person as requiring approval.
{ "id": "approve", "gate": { "requires_approval": true, "wait_for_children": true, "prompt": "Ship it?" } } - 3
Ask Claude to do the task
Claude creates or picks the task, reads the current step, and works it. When it tries to move past the gate before you said yes, the engine refuses and lists what is missing.
workflow_advance(task_id="…") { "current_step": { "id": "review" }, "unmet_conditions": [ "Requires explicit user approval", "1 of 1 child tasks are not completed" ] } - 4
Approve on the advance
You review and say go. Approval has to be passed explicitly on the advance call, never inferred from chat text. The audit row keeps the agent label and the signed-in person.
Which approach should I pick?
Use the lightest layer that holds. A common setup uses all three: CLAUDE.md for facts, skills and hooks for one person's repo, and a workflow engine for processes the team shares.
| Your situation | Start with |
|---|---|
| One person, one repo, a checklist that is mostly followed | A skill |
| A command that must never run, or must always ask | Permission rules |
| A precondition with logic (tests passed, right branch) | A PreToolUse hook |
| Parallel research or review inside one session | Subagents or Dynamic workflows |
| Sign-off by a person, many agents, or work that spans days | A workflow engine over MCP, such as ConvOps |
Frequently asked questions
Why does Claude Code ignore my CLAUDE.md instructions?
CLAUDE.md is loaded as context, not enforced configuration. Long files, vague wording and contradictions all lower adherence. Keep it short and specific, and move anything that must always happen into a hook or a permission rule.
Is a skill enough to make Claude Code follow a process?
For a short procedure one person runs, usually yes. A skill is still text the model follows. If skipping a step would be costly, back it with a hook that checks the precondition before the risky tool call.
Can a hook stop Claude Code from pushing?
Yes. A PreToolUse hook on the Bash tool can exit with code 2, or return a deny decision, and the call is blocked with your reason shown to Claude. A deny permission rule also works for simple command patterns.
Do Claude Code Dynamic workflows support human approval between steps?
Not mid-run. Anthropic documents that a run pauses on its own only for permission prompts and usage-limit waits, and recommends running each stage as its own workflow when you need sign-off between stages.
Does ConvOps replace Claude Code?
No. ConvOps does not run models. Claude Code stays your agent and connects over MCP. ConvOps holds the process, the gates, the memory and the audit, and the same workflow also runs from Codex, Cursor and other MCP clients.