⏱️ Reading time: 15 min
Claude Code stops to ask for approval every few minutes, the usual cost of autonomous AI agents when the workflow prioritizes oversight over speed. The post “Superlite: hand an agent a spec, come back to tested work”, published on contextfirst.blog, sums it up well: its author asked for a spec, made a sandwich, and came back to find the agent stopped at section 1, waiting for a “yes” that had been sitting there for twenty minutes.
📑 En este artículo
- TL;DR
- What are autonomous AI agents?
- Why autonomous AI agents stop at every step
- How the permission model works in Claude Code
- Hooks: the other layer of control
- Superlite: a concrete case of an autonomous coding agent
- Getting started: configuring permissions and hooks in Claude Code
- Real-world use cases
- Comparison with alternatives
- Common mistakes and best practices
- Deep dive: the task graph and the decision log
- Frequently Asked Questions
- Does Superlite replace Superpowers?
- Can hooks block any action of an autonomous coding agent?
- What happens if the agent tries to push to main with the configuration from this article?
- How many human approvals does a build need with Superlite?
- Can Claude Code permissions be combined with hooks?
- Does autonomous agentic AI work with models other than Claude?
- References
This article explains why that happens, what mechanisms (permissions, hooks, and automatic task review) let you delegate a full spec without constant supervision, and how Superlite, the Claude Code plugin born from that frustration, combines them in practice.
TL;DR
- Agents stall because every sensitive tool asks for confirmation unless a permission rule already exists.
- PreToolUse and PostToolUse hooks intercept every action and approve or block it with code, without asking you.
- Superlite swaps 8 to 12 approvals per feature for a single one, and moves the rest of the rules into code.
- A plan split into tasks with no shared files lets several agents run at once instead of one at a time.
- Automatic code review replaces human approval, except for destructive or security-sensitive changes.
What are autonomous AI agents?
Autonomous AI agents are programs that carry out development tasks (planning, writing code, running tests, fixing bugs) by chaining calls to a language model and system tools, without a human confirming every intermediate step: only destructive, irreversible, or security-related decisions require intervention.
Tools like Claude Code, Cursor, or GitHub Copilot’s agent mode work this way by default. They receive an instruction, break it down into steps, and run each tool (reading a file, running a command, editing code) through a loop of planning, acting, and observing the result.
By design, most of these agents are conservative. Before running something irreversible (deleting a file, pushing, installing a dependency), they stop and ask for human confirmation. That caution prevents disasters, but it also multiplies the pauses when the user already knows exactly what they want to build.
Why autonomous AI agents stop at every step
The contextfirst.blog post profiled its own workflow (based on the “superpowers” plugin for Claude Code) and found five bottlenecks. The first: between 8 and 12 human approval gates per feature, one for each section of the design, plus separate reviews of the spec, the plan, and the execution method.
The second is strictly sequential execution: one implementer, then one reviewer, then the next task. In the author’s first benchmark that translated into a queue of 21 dispatches in a single file, like a bank with one teller window and a very long lunch break.
The third is review after every task, with retries whenever the review finds something: in a 34-minute build, 12 minutes went to those reviews alone. The fourth is running the full test suite multiple times, once for every skill that wants to make sure nothing changed. The fifth is using the most capable model (Opus) on the critical path: according to the post, it writes code at half the speed of Sonnet.
None of these brakes are a design flaw. Each one is a reasonable safety net when the goal is to have a human review every decision. The problem shows up when the user already knows exactly what they want to build: there, that same safety net turns into a four-hour meeting that scheduled itself.
How the permission model works in Claude Code
Claude Code handles the first layer of control with a permission system declared in settings.json. Every action (running a shell command, editing a file, calling an MCP tool) is evaluated against three lists: allow (runs without asking), ask (requests interactive confirmation), and deny (never runs, it’s not even asked about).
The rules use patterns by tool and argument, not just by command name. Bash(git commit:*) authorizes any commit, but not a push; Bash(rm -rf:*) can be placed directly in deny so that no agent, no matter how politely it asks, can delete an entire directory.
The other axis is the session’s permission mode: the default mode asks about any action not covered by a rule; acceptEdits approves file edits automatically but still asks about shell commands; plan doesn’t execute anything until the user approves the full plan; and bypassPermissions runs everything except what’s explicitly in deny. Superlite and similar projects rely on this last mode combined with carefully thought-out deny rules, not on trusting the agent to behave.
flowchart TD
T["Agent calls a tool"] --> C{"Rule in permissions"}
C -->|"allow"| E["Runs without asking"]
C -->|"ask"| H["Hook or interactive prompt"]
C -->|"deny"| D["Blocked, never runs"]
H --> F{"Hook decides"}
F -->|"approve"| E
F -->|"block"| D
Hooks: the other layer of control
Permissions decide whether an action runs; hooks decide what happens before and after it runs, with real code instead of a declarative rule. Claude Code fires events like PreToolUse (before running a tool), PostToolUse (after), and SessionStart (when the session opens), and each one can be tied to a script that receives JSON context over stdin and returns a decision.
A PreToolUse hook tied to the Bash matcher sees the exact command the agent is about to run before it runs. If the command attempts a git push to main, the hook can return a block with a reason, without the model needing to understand or honor a plain-text instruction.
#!/usr/bin/env bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // empty')
if [[ "$cmd" == *"push"* && "$cmd" == *"main"* ]]; then
echo '{"decision":"block","reason":"push to main requires human review"}'
exit 0
fi
echo '{"decision":"approve"}'
If the agent attempts git push origin main, the hook prints {"decision":"block","reason":"push to main requires human review"} and Claude Code cancels the command without running it; for any other command, it prints {"decision":"approve"} and execution continues normally.
sequenceDiagram
participant Agent
participant Hook as PreToolUse Hook
participant Repo as Repository
Agent->>Hook: attempts "git push origin main"
Hook-->>Agent: decision block, reason
Agent->>Repo: push cancelled
💭 Key takeaway: The original post puts it bluntly: an agent reads a rule written in text and then does whatever it wants. That’s why the rules that matter live in code (permissions and hooks), not in a paragraph-long instruction inside the spec.
Superlite: a concrete case of an autonomous coding agent
Superlite is the Claude Code plugin contextfirst.blog built to solve exactly those five bottlenecks. Instead of asking for approval section by section, it groups the questions into a single batch of up to four, depending on the size of the request: a typo gets fixed directly, with no design document; a change to an existing flow gets a short design in the chat; a new project gets a single design-and-plan document that the user approves once.
After that single approval, Superlite only asks again before something destructive, externally visible, or security-sensitive: it won’t push to main while the user is out at lunch, but it will do everything else without interruption.
The central piece is the plan: instead of a list of steps, Superlite generates a task graph. Each task declares which files it owns, which interfaces it consumes and produces, and which tests it has to pass. Tasks that don’t share files or depend on each other run at the same time; the width of the graph decides how many agents work in parallel at any given moment.
Every decision that would normally trigger a question gets logged as a ruling: what was decided, why, and what happens if it turned out to be wrong. That’s what lets autonomous AI agents move forward without constant supervision without losing traceability: the user comes back at the end knowing exactly which decision to review first, instead of reconstructing the reasoning from scratch.
flowchart TD
subgraph Sequential["One agent, one step at a time"]
A1["Task 1"] --> P1["Human approval"]
P1 --> A2["Task 2"]
A2 --> P2["Human approval"]
P2 --> A3["Task 3"]
end
subgraph Parallel["Several agents at once"]
B1["Task 1"] --> R["Automatic review"]
B2["Task 2"] --> R
B3["Task 3"] --> R
end
Getting started: configuring permissions and hooks in Claude Code
Dependencies before starting: Claude Code installed, a project with a .claude/ folder at the root, and jq available to parse the JSON inside the hook (on Linux and macOS it’s almost always already there or installs with the system package manager; on Windows, without WSL, the same hook is written in PowerShell with ConvertFrom-Json in one line).
First, create or edit .claude/settings.json at the project root with permission rules:
{
"permissions": {
"allow": ["Bash(npm test:*)", "Bash(git commit:*)"],
"ask": ["Bash(git push:*)"],
"deny": ["Bash(rm -rf:*)"]
}
}
With this, Claude Code runs tests and commits without asking, requests confirmation before any push, and will never run an rm -rf, no matter how it’s asked.
Second, create the hook at .claude/hooks/guard-push.sh with the script shown in the previous section, and give it execute permission with chmod +x .claude/hooks/guard-push.sh.
Third, register the hook in the same settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{"type": "command", "command": ".claude/hooks/guard-push.sh"}]
}
]
}
}
To confirm the permission rule is active, run /permissions inside a Claude Code session: it lists every pattern (allow, ask, or deny) along with the tool it applies to. For the hook, the real check is asking the agent to attempt git push origin main: if the configuration is right, the command gets cancelled and the reason push to main requires human review shows up in the output instead of running.
Real-world use cases
A new, well-scoped feature (an endpoint, a form, a data migration) is the most straightforward use case: the user approves a plan once and comes back hours later to tested code, instead of having approved twenty small decisions one at a time.
A large refactor that touches many files benefits from the task graph: if the refactor can be split into modules that don’t step on each other (for example, migrating each API route from one framework to another), several agents work in parallel instead of one after the other.
A one-off bug fix follows the short path: Superlite detects that it’s a small change and fixes it directly, without generating a design document for a typo. The size of the response matches the size of the request, not the other way around.
The case where this approach doesn’t work is the opposite: when the user still doesn’t know exactly what they want to build and needs to iterate on the design live, section by section. There, the collaborative flow (Superpowers, with a human close to every step) remains the right tool.
Comparison with alternatives
None of the following three approaches is universally better: the decision depends on whether the user already has the design worked out in their head or is still building it together with the agent.
| Option | When to use it | Advantage | Limitation |
|---|---|---|---|
| Manual approval at every step | Design still uncertain, decided on the fly | Total control, zero surprises | 8 to 12 pauses per feature, doesn’t scale to large tasks |
| Superpowers (collaborative flow) | User wants to review the spec, plan, and execution separately | Maximum traceability and safety | Sequential execution, slow for specs that are already closed |
| Superlite (spec to autonomous execution) | The spec is already defined and just needs to be built | One approval, parallel tasks, decision log | Requires well-written permission rules and hooks ahead of time |
Common mistakes and best practices
The most common mistake is turning on bypassPermissions without writing any deny rules. The mode assumes that everything not forbidden is allowed, so an agent in that mode with an empty deny list can run any command, including a destructive one.
The second is confusing an instruction in the spec (“never delete production files”) with a real rule. That sentence lives in the context the model reads. A context shift, a contradictory instruction further down, or simply a misreading can make the agent skip right past it. The rule needs to live in code: in settings.json or a hook, where it’s always evaluated, without depending on the model remembering it.
The third, documented in the Superlite post itself, is running Superpowers and Superlite in the same session: both inject context at session start and share skill names, so they end up contradicting each other. Pick one per session, not both.
⚠️ Watch out: a hook that always responds{"decision":"approve"}without reading the command protects nothing. It’s an illusion of control. The hook has to inspect the realtool_inputbefore deciding.
The practice that works best is splitting the rules into two layers: permissions for what’s predictable (which commands are always safe or always dangerous) and hooks for what depends on the exact content of the command (which branch gets pushed to, which file gets deleted). The two layers get tested separately, before trusting them with a large spec.
Deep dive: the task graph and the decision log
Under the hood, Superlite’s planner doesn’t hand out tasks at random: it builds a directed graph where each node is a task with three explicit properties: the files it owns, the interfaces it consumes from other tasks, and the tests it has to pass to be considered done. Two tasks with no file overlap and no interface dependencies land in the same layer of the graph and fire together.
This is different from simply telling several agents to work in parallel with no further structure: without the file constraint, two agents touching the same module generate merge conflicts that nobody reviewed. The graph prevents the conflict before it happens, it doesn’t fix it afterward.
Automatic review works the same way for every finished task: a second agent (not necessarily the same model) runs the declared tests and checks the result against the promised interface. If it fails, a correction task is generated that goes through the same check again, without waking up the user, unless the check keeps failing.
And when the process does need the user, it doesn’t do it with a loose question: it hands over the full list of rulings made during execution, each one with its justification and its cost if it turned out to be the wrong decision. That’s how autonomous AI agents manage to move forward for hours without intervention while still leaving an auditable trail.
Your next step: clone a test repo, add the guard-push.sh hook from this article to .claude/hooks/, and ask Claude Code to attempt a git push origin main to see the block in action.
Frequently Asked Questions
Does Superlite replace Superpowers?
No. Superpowers prioritizes keeping a human close to every step, and Superlite prioritizes speed once the spec is already settled. They share a codebase, but contextfirst.blog recommends not enabling both in the same session because their skills collide.
Can hooks block any action of an autonomous coding agent?
Yes, any action that passes through an event with a registered hook, such as PreToolUse for tools or SessionStart when the session opens. Whatever the hook doesn’t intercept (an event with no matcher configured) follows the normal permission rules.
What happens if the agent tries to push to main with the configuration from this article?
The guard-push.sh hook detects “push” and “main” in the command, returns {"decision":"block"} with the reason, and Claude Code cancels the command without running it in the repository.
How many human approvals does a build need with Superlite?
One, when approving the design and the plan. After that, according to the original post, it only asks again before destructive, externally visible, or security-sensitive actions.
Can Claude Code permissions be combined with hooks?
Yes, and it’s the recommended combination: permissions cover predictable rules by command pattern, and hooks cover decisions that depend on the exact content of that command, like which branch a push targets.
Does autonomous agentic AI work with models other than Claude?
The mechanism (declarative permissions plus hooks in code) is specific to Claude Code. Other agentic environments solve the same problem with their own policy systems, but the principle of rules in code, not in prompt text, applies just the same.
References
- Contextfirst.blog: the original post introducing Superlite, its benchmarks, and the plugin’s design.
- GitHub: anthropics/claude-code: the official Claude Code repository, with documentation on hooks and permissions.
- Claude Docs: Anthropic’s official documentation on Claude Code and its configuration.
- Wikipedia: Software agent: a general definition of the software agent concept.
📱 Like this content? Follow @programacion on Telegram for daily tech content in Spanish: quick summaries, fresh content every day.
Featured image: Foto de National Cancer Institute en Unsplash
Did it work for you? Got a different error? Say so below: questions get answered and help the next reader.
Leave a comment
0 Comments