Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Post-completion self-review for coding agents that runs simplify, harden, re-verification, and micro-documentation passes on non-trivial code or high-impact configuration changes.
SkillScore86/100
Test results 86
3/3 safety checks passed
36%86%of test cases passed +50 pts
Passed 19 of 22 test cases with the skill, and 8 of 22 without it.
12 fixed7 passed either way2 still failing1 broke
One test taskYou made two behavior-preserving cleanup edits in `src/parser/csv.ts` during Pass 1. You then ran `npm test src/parser/csv.test.ts` for Pass 4 re-verification, and one test failed due to an unexpected null-handling edge case. What is the mandatory next step?
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add pskoett-simplify-and-harden
claude --plugin-dir "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents"The same install from Python, for a notebook or a setup script.
pip install "decimalai>=0.15"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
print("Added. Start Claude Code with the command below.")claude --plugin-dir "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents"Type these in a Claude Code session. No account or API key. It writes the skill and any files it bundles, and asks first when its safety rating isn't Passed.
/plugin marketplace add decimal-labs/decimalai-claude-plugins
/plugin install decimalai@decimalai/decimalai:install pskoett-simplify-and-hardenThe plugin needs python3 and curl on your machine.
No Python or account. Claude Code picks it up in its next session.
curl -fsSL --create-dirs -o .claude/skills/pskoett-simplify-and-harden/SKILL.md https://app.decimal.ai/s/pskoett-simplify-and-harden/SKILL.md.claude/skills/pskoett-simplify-and-harden/SKILL.mdThis gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[claude-agent-sdk]"
decimalai skills add pskoett-simplify-and-hardenimport asyncio
from claude_agent_sdk import ClaudeAgentOptions
from decimalai.claude_agent_sdk import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
async def main():
question = "Hello!"
async with support.run(question) as run: # one user message, one run
async for message in run.query(options=ClaudeAgentOptions(max_turns=6)):
print(message)
# In a notebook or async code: await main()
asyncio.run(main())Prefer its own loader? ClaudeAgentOptions(plugins=[skills_plugin()], skills="all") reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[claude-agent-sdk]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
import asyncio
from claude_agent_sdk import ClaudeAgentOptions
from decimalai.claude_agent_sdk import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
async def main():
question = "Hello!"
async with support.run(question) as run: # one user message, one run
async for message in run.query(options=ClaudeAgentOptions(max_turns=6)):
print(message)
# In a notebook or async code: await main()
asyncio.run(main())Prefer its own loader? ClaudeAgentOptions(plugins=[skills_plugin()], skills="all") reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
options = ClaudeAgentOptions(system_prompt=f"You are a helpful agent.\n\n{skill}", max_turns=6)
async def main():
async for message in query(prompt="Hello!", options=options):
print(message)
# In a notebook or async code: await main()
asyncio.run(main())This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai-agents]"
decimalai skills add pskoett-simplify-and-hardenfrom agents import Agent, Runner
from decimalai.openai_agents import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
name=support.name,
instructions=support.instructions, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# In a notebook or async code: result = await Runner.run(agent, "Hello!")
result = Runner.run_sync(agent, "Hello!")Using SandboxAgent? capabilities=[Shell(), decimalai.openai_agents.sandbox_skills()] points its own loader at the same folder.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai-agents]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
from agents import Agent, Runner
from decimalai.openai_agents import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
name=support.name,
instructions=support.instructions, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# In a notebook or async code: result = await Runner.run(agent, "Hello!")
result = Runner.run_sync(agent, "Hello!")Using SandboxAgent? capabilities=[Shell(), decimalai.openai_agents.sandbox_skills()] points its own loader at the same folder.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
agent = Agent(name="support", instructions=f"You are a helpful agent.\n\n{skill}")
# In a notebook or async code: result = await Runner.run(agent, "Hello!")
result = Runner.run_sync(agent, "Hello!")This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai]"
decimalai skills add pskoett-simplify-and-hardenimport json
from openai import OpenAI
from decimalai.openai import agent_config
client = OpenAI()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your tools, as Chat Completions takes them, and what answers each.
TOOLS = [{"type": "function", "function": {
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
# run.system is your prompt, then the skill list.
messages = [{"role": "system", "content": run.system}, run.message]
while True:
reply = client.chat.completions.create(
model="gpt-5.4-mini",
messages=messages,
tools=[*TOOLS, *run.tools], # your tools, then load_skill
).choices[0].message
messages.append(reply)
if not reply.tool_calls:
break
for call in reply.tool_calls:
# load_skill is answered by the run; your own tools by FUNCTIONS.
function = FUNCTIONS.get(call.function.name)
messages.append(run.tool_result(call) or {
"role": "tool", "tool_call_id": call.id,
"content": function(**json.loads(call.function.arguments)) if function
else f"There is no tool named {call.function.name!r}.",
})
print(reply.content)
# The Responses API takes run.response_tools instead of run.tools.The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
import json
from openai import OpenAI
from decimalai.openai import agent_config
client = OpenAI()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your tools, as Chat Completions takes them, and what answers each.
TOOLS = [{"type": "function", "function": {
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
# run.system is your prompt, then the skill list.
messages = [{"role": "system", "content": run.system}, run.message]
while True:
reply = client.chat.completions.create(
model="gpt-5.4-mini",
messages=messages,
tools=[*TOOLS, *run.tools], # your tools, then load_skill
).choices[0].message
messages.append(reply)
if not reply.tool_calls:
break
for call in reply.tool_calls:
# load_skill is answered by the run; your own tools by FUNCTIONS.
function = FUNCTIONS.get(call.function.name)
messages.append(run.tool_result(call) or {
"role": "tool", "tool_call_id": call.id,
"content": function(**json.loads(call.function.arguments)) if function
else f"There is no tool named {call.function.name!r}.",
})
print(reply.content)
# The Responses API takes run.response_tools instead of run.tools.No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
reply = client.chat.completions.create(
model="gpt-5.4-mini",
messages=[
{"role": "system", "content": f"You are a helpful agent.\n\n{skill}"},
{"role": "user", "content": "Hello!"},
],
).choices[0].messageThis gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[anthropic]"
decimalai skills add pskoett-simplify-and-hardenimport anthropic
from decimalai.anthropic import agent_config
client = anthropic.Anthropic()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
question = "Hello!"
with support.run(question) as run: # one user message, one run
answer = client.beta.messages.tool_runner(
model="claude-haiku-5-5",
max_tokens=4096,
system=run.system, # your prompt, then the skill list
tools=[*run.tools], # your tools, then load_skill
messages=[{"role": "user", "content": question}],
).until_done()The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[anthropic]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
import anthropic
from decimalai.anthropic import agent_config
client = anthropic.Anthropic()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
question = "Hello!"
with support.run(question) as run: # one user message, one run
answer = client.beta.messages.tool_runner(
model="claude-haiku-5-5",
max_tokens=4096,
system=run.system, # your prompt, then the skill list
tools=[*run.tools], # your tools, then load_skill
messages=[{"role": "user", "content": question}],
).until_done()No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
reply = client.messages.create(
model="claude-haiku-5-5",
max_tokens=4096,
system=f"You are a helpful agent.\n\n{skill}",
messages=[{"role": "user", "content": "Hello!"}],
)This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[google-genai]"
decimalai skills add pskoett-simplify-and-hardenfrom google import genai
from google.genai import types
from decimalai.google_genai import agent_config
client = genai.Client()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your functions, as declarations for the model, and what answers each.
TOOLS = [{"function_declarations": [{
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters_json_schema": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}]}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
config = types.GenerateContentConfig(
system_instruction=run.system, # your prompt, then the skill list
tools=[*TOOLS, *run.tool_params], # your functions, then load_skill
)
contents = [{"role": "user", "parts": [{"text": run.message}]}]
while True:
response = client.models.generate_content(
model="gemini-3.5-flash", contents=contents, config=config,
)
if not response.function_calls:
break
contents.append(response.candidates[0].content)
parts = []
for call in response.function_calls:
# load_skill is answered by the run; your own functions by FUNCTIONS.
# A loop of your own rather than automatic function calling, which
# raises KeyError when the model asks for a function you did not pass.
function = FUNCTIONS.get(call.name)
parts.append(run.tool_result(call) or {"function_response": {
"name": call.name, "id": call.id,
"response": {"result": function(**(call.args or {})) if function
else f"There is no function named {call.name!r}."},
}})
contents.append({"role": "user", "parts": parts})
print(response.text)The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[google-genai]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
from google import genai
from google.genai import types
from decimalai.google_genai import agent_config
client = genai.Client()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your functions, as declarations for the model, and what answers each.
TOOLS = [{"function_declarations": [{
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters_json_schema": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}]}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
config = types.GenerateContentConfig(
system_instruction=run.system, # your prompt, then the skill list
tools=[*TOOLS, *run.tool_params], # your functions, then load_skill
)
contents = [{"role": "user", "parts": [{"text": run.message}]}]
while True:
response = client.models.generate_content(
model="gemini-3.5-flash", contents=contents, config=config,
)
if not response.function_calls:
break
contents.append(response.candidates[0].content)
parts = []
for call in response.function_calls:
# load_skill is answered by the run; your own functions by FUNCTIONS.
# A loop of your own rather than automatic function calling, which
# raises KeyError when the model asks for a function you did not pass.
function = FUNCTIONS.get(call.name)
parts.append(run.tool_result(call) or {"function_response": {
"name": call.name, "id": call.id,
"response": {"result": function(**(call.args or {})) if function
else f"There is no function named {call.name!r}."},
}})
contents.append({"role": "user", "parts": parts})
print(response.text)No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
response = client.models.generate_content(
model="gemini-3.5-flash",
contents="Hello!",
config=types.GenerateContentConfig(system_instruction=f"You are a helpful agent.\n\n{skill}"),
)This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[langchain]" langchain-openai
decimalai skills add pskoett-simplify-and-hardenfrom langchain.agents import create_agent
from decimalai.langchain import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = create_agent(
"openai:gpt-5.4-mini",
tools=[], # your tools; the middleware adds load_skill
middleware=[support.middleware], # your prompt, the skill list and load_skill
)
result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[langchain]" langchain-openaifrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
from langchain.agents import create_agent
from decimalai.langchain import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = create_agent(
"openai:gpt-5.4-mini",
tools=[], # your tools; the middleware adds load_skill
middleware=[support.middleware], # your prompt, the skill list and load_skill
)
result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
agent = create_agent("openai:gpt-5.4-mini", tools=[], system_prompt=f"You are a helpful agent.\n\n{skill}")
result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})This gets SKILL.md only. The skill's 1 other file is not included.
CrewAI's own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" "crewai>=1.15.27"
decimalai skills add pskoett-simplify-and-hardenimport decimalai.crewai
from crewai import Agent, Crew, Task
agent = Agent(
role="Support", goal="Help the customer", backstory="A support agent.",
llm=llm, # your own CrewAI LLM
skills=decimalai.crewai.skills(), # the installed folder
tools=decimalai.crewai.skill_tools(), # reads a skill's files, runs its scripts
)
task = Task(description="Hello!", expected_output="an answer", agent=agent)
Crew(agents=[agent], tasks=[task]).kickoff()The same install from Python, for a notebook or a setup script. CrewAI's own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" "crewai>=1.15.27"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
import decimalai.crewai
from crewai import Agent, Crew, Task
agent = Agent(
role="Support", goal="Help the customer", backstory="A support agent.",
llm=llm, # your own CrewAI LLM
skills=decimalai.crewai.skills(), # the installed folder
tools=decimalai.crewai.skill_tools(), # reads a skill's files, runs its scripts
)
task = Task(description="Hello!", expected_output="an answer", agent=agent)
Crew(agents=[agent], tasks=[task]).kickoff()No DecimalAI package. CrewAI's own loader reads the folder, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
from crewai import Agent, Crew, Task
agent = Agent(
role="Support", goal="Help the customer", backstory="A support agent.",
llm=llm, # your own CrewAI LLM
skills=[Path(".agents/skills")],
)
task = Task(description="Hello!", expected_output="an answer", agent=agent)
Crew(agents=[agent], tasks=[task]).kickoff()This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[adk]"
decimalai skills add pskoett-simplify-and-hardenfrom decimalai.adk import DecimalAIPlugin, agent_config
from google.adk.agents import LlmAgent
from google.adk.apps import App
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = LlmAgent(
name="support", # ADK needs a Python identifier
model="gemini-3.5-flash",
instruction=support.instruction, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# DecimalAIPlugin makes each invocation of runners built from this App one trace.
app = App(name="support", root_agent=agent, plugins=[DecimalAIPlugin()])Prefer ADK's own loader? SkillToolset(skills=decimalai.adk.skills(), ...) reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[adk]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
from decimalai.adk import DecimalAIPlugin, agent_config
from google.adk.agents import LlmAgent
from google.adk.apps import App
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = LlmAgent(
name="support", # ADK needs a Python identifier
model="gemini-3.5-flash",
instruction=support.instruction, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# DecimalAIPlugin makes each invocation of runners built from this App one trace.
app = App(name="support", root_agent=agent, plugins=[DecimalAIPlugin()])Prefer ADK's own loader? SkillToolset(skills=decimalai.adk.skills(), ...) reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
agent = LlmAgent(
name="support",
model="gemini-3.5-flash",
instruction=lambda context: f"You are a helpful agent.\n\n{skill}",
)This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[pydantic-ai]"
decimalai skills add pskoett-simplify-and-hardenfrom pydantic_ai import Agent
from decimalai.pydantic_ai import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
"openai:gpt-4o-mini",
name=support.name,
tools=[], # your tools; the capability adds load_skill
capabilities=[support], # your prompt, the skill list and load_skill
)
# In a notebook or async code: result = await agent.run("Hello!")
result = agent.run_sync("Hello!")On the Pydantic AI harness, decimalai.pydantic_ai_harness.skills(project) uses its own loader instead.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[pydantic-ai]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
from pydantic_ai import Agent
from decimalai.pydantic_ai import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
"openai:gpt-4o-mini",
name=support.name,
tools=[], # your tools; the capability adds load_skill
capabilities=[support], # your prompt, the skill list and load_skill
)
# In a notebook or async code: result = await agent.run("Hello!")
result = agent.run_sync("Hello!")On the Pydantic AI harness, decimalai.pydantic_ai_harness.skills(project) uses its own loader instead.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
agent = Agent("openai:gpt-4o-mini", instructions=f"You are a helpful agent.\n\n{skill}")
# In a notebook or async code: result = await agent.run("Hello!")
result = agent.run_sync("Hello!")This gets SKILL.md only. The skill's 1 other file is not included.
Deep Agents' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" deepagents
decimalai skills add pskoett-simplify-and-hardenimport decimalai.deepagents
from deepagents import create_deep_agent
agent = create_deep_agent(model=model, **decimalai.deepagents.skills())
agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})The default backend reads files but has no shell. To run a skill's scripts, pass skills(backend=LocalShellBackend(...)).
The same install from Python, for a notebook or a setup script. Deep Agents' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" deepagentsfrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
import decimalai.deepagents
from deepagents import create_deep_agent
agent = create_deep_agent(model=model, **decimalai.deepagents.skills())
agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})The default backend reads files but has no shell. To run a skill's scripts, pass skills(backend=LocalShellBackend(...)).
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
agent = create_deep_agent(model=model, system_prompt=f"You are a helpful agent.\n\n{skill}")
agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})This gets SKILL.md only. The skill's 1 other file is not included.
Its own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" agent-framework
decimalai skills add pskoett-simplify-and-hardenimport asyncio
from agent_framework import Agent
from decimalai.agent_framework import skills
agent = Agent(client=client, instructions="You are a helpful agent.", context_providers=[skills()])
asyncio.run(agent.run("Hello!"))It caches skills by default, so restart the process after decimalai skills update.
The same install from Python, for a notebook or a setup script. Its own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" agent-frameworkfrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
import asyncio
from agent_framework import Agent
from decimalai.agent_framework import skills
agent = Agent(client=client, instructions="You are a helpful agent.", context_providers=[skills()])
asyncio.run(agent.run("Hello!"))It caches skills by default, so restart the process after decimalai skills update.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
agent = Agent(client=client, instructions=f"You are a helpful agent.\n\n{skill}")
asyncio.run(agent.run("Hello!"))This gets SKILL.md only. The skill's 1 other file is not included.
Strands' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" strands-agents
decimalai skills add pskoett-simplify-and-hardenfrom decimalai.strands import skills
from strands import Agent
from strands.vended_tools import file_editor, shell
agent = Agent(
model=model, # always pass one: the default is Amazon Bedrock
system_prompt="You are a helpful agent.",
tools=[file_editor, shell],
plugins=[skills()],
)
agent("Hello!")Strands loads an agent's skills once, so build the agent again after decimalai skills update.
The same install from Python, for a notebook or a setup script. Strands' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" strands-agentsfrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("pskoett-simplify-and-harden")
if result.exit_code:
raise SystemExit(result.problems)
from decimalai.strands import skills
from strands import Agent
from strands.vended_tools import file_editor, shell
agent = Agent(
model=model, # always pass one: the default is Amazon Bedrock
system_prompt="You are a helpful agent.",
tools=[file_editor, shell],
plugins=[skills()],
)
agent("Hello!")Strands loads an agent's skills once, so build the agent again after decimalai skills update.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/pskoett-simplify-and-harden/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/pskoett-simplify-and-harden/SKILL.md").read_text()
agent = Agent(model=model, system_prompt=f"You are a helpful agent.\n\n{skill}")
agent("Hello!")This gets SKILL.md only. The skill's 1 other file is not included.
Adds every file the skill has, pinned so you can update it. Cursor, Copilot, Cline and Warp read this folder by themselves.
pip install "decimalai>=0.15"
decimalai skills add pskoett-simplify-and-hardenNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/pskoett-simplify-and-harden/SKILL.md https://app.decimal.ai/s/pskoett-simplify-and-harden/SKILL.md.agents/skills/pskoett-simplify-and-harden/SKILL.mdThis gets SKILL.md only. The skill's 1 other file is not included.
Give its text to your model as instructions. No account or package needed.
This gets SKILL.md only. The skill's 1 other file is not included.
Raw files: /s/pskoett-simplify-and-harden/SKILL.md · /s/pskoett-simplify-and-harden.json
Fetch the file and give its text to your model as instructions. No account or package needed.
curl -fsSL https://app.decimal.ai/s/pskoett-simplify-and-harden/SKILL.mdcurl -fsSL https://app.decimal.ai/s/pskoett-simplify-and-harden.jsonThis gets SKILL.md only. The skill's 1 other file is not included.
You don't need a DecimalAI account.
Saved prompts and skills, pinned versions, and traces of this skill in your runs. DecimalAI does not run your agent.
Claude Code reads files from your project, so DecimalAI config does not apply there.
On Claude Agent SDK: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On OpenAI Agents: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On OpenAI SDK: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Anthropic: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Gemini API: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On LangChain: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On CrewAI: set DECIMAL_API_KEY and add decimalai.init(crewai=True) to record runs and skill use. The skill version stays in your repo.
On Google ADK: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Pydantic AI: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Deep Agents: set DECIMAL_API_KEY and add decimalai.init(langchain=True) to record runs and skill use. The skill version stays in your repo.
On Microsoft Agent Framework: set DECIMAL_API_KEY and add decimalai.init(otel=True, agent_name="support") to record runs and skill use. The skill version stays in your repo.
On Strands: set DECIMAL_API_KEY and add decimalai.init(otel=True, agent_name="support") to record runs and skill use. The skill version stays in your repo.
Editors read files from your project, so DecimalAI config does not apply there.
Anywhere else: record a use with decimalai.log_skill_activation() inside a trace.
gh skill install pskoett/pskoett-skills simplify-and-harden
For CI-only execution, use:
gh skill install pskoett/pskoett-skills simplify-and-harden-ci
Fallback using the Agent Skills CLI:
npx skills add pskoett/pskoett-skills/skills/simplify-and-harden
npx skills add pskoett/pskoett-skills/skills/simplify-and-harden-ci
| Field | Value |
|---|---|
| Skill ID | simplify-and-harden |
| Version | 0.1.0 |
| Trigger | Post-completion hook |
| Author | Peter Skøtt Pedersen |
| Category | Code Quality / Security |
| Priority | Recommended |
When a coding agent completes a task, it holds peak contextual understanding of the problem, the solution, and the tradeoffs it made along the way. This context degrades immediately -- the next task wipes the slate. Simplify & Harden exploits that peak context window to perform two focused review passes before the agent moves on.
Most agents solve the ticket and stop. This skill turns "done" into "done well."
The operating philosophy is a deliberate "fresh eyes" self-review before moving on: carefully re-read all newly written code and all existing code modified in the task, and look hard for obvious bugs, errors, confusing logic, brittle assumptions, naming issues, and missed hardening opportunities. The goal is not to expand scope or rewrite the solution -- it is to use peak context to perform a disciplined first review pass while the agent still remembers the intent behind every change.
This skill is a post-completion self-pass and does not replace an independent review pass.
Recommended flow:
If the two disagree, treat the independent review findings as the external gate and either fix or explicitly waive findings.
For larger or risky changes, use a general-purpose subagent with fresh context. No named agent preset is required. Give it the changed-file list, diff, approved plan or acceptance criteria, and relevant verification evidence. Ask it to read the scoped code directly and report findings without editing files. Restrict tools to read-only where the host supports it; otherwise state that constraint in the brief. In Copilot, request the same scoped independent review in chat.
Use the Simplify and Harden checklists below for complexity and security. Also compare every supplied requirement against the implementation: missing features, incorrect behavior, incomplete edge/error paths, API and response contracts, test coverage, and unverified acceptance criteria. Classify spec gaps as missing, incorrect, incomplete, or untested.
Require severity-ordered findings with file and line (or "not implemented"), category, concrete evidence, relevant spec reference or attack vector, and a specific fix. Keep out-of-scope observations separate and explicitly report when there are no in-scope findings. The reviewer reports; the implementing agent handles fixes under the existing approval and re-verification rules.
One reviewer can cover all relevant dimensions. Split reviews only when scope or risk justifies it, not automatically into three agents. If independent review is unavailable, report that limitation; a self-pass is not a substitute for an independent merge gate.
The skill activates automatically when ALL of the following are true:
Non-trivial code change definition
Treat a diff as non-trivial when either condition is true:
*.ts,
*.tsx, *.js, *.jsx, *.py, *.go, *.rs, *.java, *.cs,
*.rb, *.php, *.swift, *.kt, *.scala, *.sh) and includes
either:
Treat the diff as non-trivial = false when it is docs-only, low-impact config-only, comments-only, formatting-only, generated artifacts only, or tests-only.
The skill does NOT activate when:
--no-review or equivalent flagHard rule: Only touch files modified in this task.
The agent MUST NOT:
The agent SHOULD flag out-of-scope concerns in the summary output rather than acting on them.
Budget limits:
budget_exceeded flagObjective: Reduce unnecessary complexity introduced during implementation.
Default posture: simplify, don't restructure. The primary goal of this pass is lightweight cleanup that is demonstrably behavior-preserving. Refactoring is the exception, not the rule.
Fresh-eyes start (mandatory): Before making any edits in this pass, re-read all code added or modified in this task with "fresh eyes" and actively look for obvious bugs, errors, confusing logic, brittle assumptions, naming issues, and missed hardening opportunities.
The agent reviews its own work and asks:
"Now that I understand the full solution, is there a simpler way to express this?"
Dead code and scaffolding -- Did I leave behind debug logs, commented-out attempts, unused imports, or temporary variables from my iteration loop? Remove them.
Naming clarity -- Do function names, variables, and parameters make sense when read fresh? Names that made sense mid-implementation often read poorly after the fact. Rename them.
Control flow -- Can any nested conditionals be flattened? Can early returns replace deep nesting? Are there boolean expressions that could be simplified? Tighten them.
API surface -- Did I expose more than necessary? Could any public methods/functions be private? Reduce visibility.
Over-abstraction -- Did I create classes, interfaces, or wrapper functions that aren't justified by the current scope? Agents tend to over-engineer. Flag it, but don't restructure unless the win is significant.
Consolidation opportunities -- Did I spread logic across multiple functions or files when it could live in one place? Flag it, but only propose a refactor if the duplication is egregious and the consolidation is clean.
For each finding, the agent categorizes it as:
Refactor Stop Hook (mandatory):
Any change the agent classifies as a refactor triggers an interactive prompt. The agent MUST:
The agent does not batch refactor proposals. Each refactor is presented individually so the human can approve, reject, or modify on a case-by-case basis.
[simplify-and-harden] Refactor proposal (1 of 2):
I want to merge duplicated validation logic from handleCreate() and
handleUpdate() into a shared validatePayload() function.
Why: Both functions validate the same fields with identical rules.
The duplication was introduced because I built handleUpdate as a
copy of handleCreate during implementation.
Files affected: src/api/handler.ts (lines 34-67)
Estimated diff: -22 lines, +14 lines
[approve] [reject] [show diff] [skip all refactors]
If the human selects skip all refactors, the agent skips remaining refactor proposals and moves to the Harden pass. Skipped refactors still appear in the output summary as flagged with status skipped_by_user.
Only changes proven behavior-preserving do not trigger the stop hook. The category label never overrides observable behavior: a rename, branch rewrite, or visibility reduction may be externally significant and must be approved when its effect is uncertain.
Objective: Close security and resilience gaps while the agent still understands the code's intent.
The agent reviews its own work and asks:
"If someone malicious saw this code, what would they try?"
Input validation -- Are all external inputs (user input, API params, file paths, environment variables) validated before use? Check for type coercion issues, missing bounds checks, and unconstrained string lengths.
Error handling -- Are catch blocks specific? Are errors logged with context but without leaking sensitive data? Are there any swallowed exceptions?
Injection vectors -- Check for SQL injection, XSS, command injection, path traversal, and template injection in any code that builds strings from external input.
Authentication and authorization -- Do new endpoints or functions enforce auth? Are permission checks present and correct? Is there any privilege escalation risk?
Secrets and credentials -- Are there hardcoded secrets, API keys, tokens, or passwords? Are connection strings parameterized? Check for credentials in log output.
Data exposure -- Does error output, logging, or API responses leak internal state, stack traces, database schemas, or PII?
Dependency risk -- Did the agent introduce new dependencies? If so, are they well-maintained, properly versioned, and free of known vulnerabilities?
Race conditions and state -- For concurrent code: are shared resources properly synchronized? Are there TOCTOU (time-of-check-to-time-of-use) vulnerabilities?
For each finding, the agent categorizes it as:
The same Refactor Stop Hook from the Simplify pass applies here. Security refactors are presented individually with the added context of severity and attack vector:
[simplify-and-harden] Security refactor proposal:
The new /admin/export endpoint inherits base authentication but has
no role-based access check. Any authenticated user can trigger a
full data export.
Severity: HIGH
Vector: Privilege escalation
Proposed fix: Add role guard requiring 'admin' role before the
handler executes. This changes the middleware chain for this route.
Files affected: src/api/routes/admin.ts (line 12)
Estimated diff: +8 lines
[approve] [reject] [show diff] [skip all security refactors]
Security patches (not refactors) are prioritized over simplification changes when budget is constrained.
Objective: Capture non-obvious decisions while the agent still remembers why it made them.
This is deliberately lightweight -- not a documentation pass, just decision capture.
Re-verification is mandatory before signaling completion.
verify-gate evidence may be
reused when it still covers the reviewed diff.not-run, set
review_followup_required: true, and do not claim the task is fully
verified.The skill produces a structured summary appended to the task output:
simplify_and_harden:
version: "0.1.0"
task_id: "<original task ID>"
execution:
mode: "interactive"
mode_source: "auto_detected" # "auto_detected", "config", "env_override"
human_present: true
scope:
files_reviewed: ["src/api/handler.ts", "src/utils/validate.ts"]
original_diff_lines: 142
additional_changes_lines: 18
budget_exceeded: false
simplify:
applied:
- file: "src/api/handler.ts"
line: 45
type: "consolidation"
category: "refactor"
approval: "approved_by_user"
description: "Merged duplicated validation logic from handleCreate and handleUpdate into shared validatePayload function"
flagged:
- file: "src/utils/validate.ts"
type: "over-abstraction"
category: "refactor"
approval: "skipped_by_user"
description: "ValidationStrategy interface may be unnecessary -- only one implementation exists. Consider inlining if no additional strategies are planned."
confidence: "medium"
cosmetic_applied:
- file: "src/api/handler.ts"
line: 12
type: "dead_code"
description: "Removed unused import of deprecated AuthHelper"
harden:
applied:
- file: "src/api/handler.ts"
line: 62
type: "input_validation"
severity: "high"
description: "Added bounds check on pageSize parameter -- previously accepted arbitrary integers"
flagged_critical:
- file: "src/api/handler.ts"
type: "authorization"
description: "New /admin/export endpoint inherits base auth but no role check -- any authenticated user can access it. Requires human decision on role policy."
flagged_advisory:
- file: "src/utils/validate.ts"
type: "error_handling"
description: "Catch block on L31 logs full request body which may contain PII in production"
document:
comments_added: 2
locations:
- file: "src/api/handler.ts"
line: 78
comment: "// Pagination uses cursor-based approach instead of offset -- offset breaks when items are deleted between pages"
- file: "src/api/handler.ts"
line: 93
comment: "// WORKAROUND: Legacy API returns dates as strings without timezone. Assuming UTC until migration completes (see TICKET-1234)"
verification:
command: "npm test -- src/api/handler.test.ts"
result: "pass" # pass | fail | not-run
evidence: "Targeted handler tests passed after review edits"
learning_loop:
target_skill: "self-improvement"
log_file: ".learnings/LEARNINGS.md"
candidates:
- pattern_key: "simplify.dead_code"
pass: "simplify"
finding_type: "dead_code"
severity: "low"
source_file: "src/api/handler.ts"
source_line: 12
suggested_rule: "Remove dead code and unused imports before finalizing a task."
- pattern_key: "harden.input_validation"
pass: "harden"
finding_type: "input_validation"
severity: "high"
source_file: "src/api/handler.ts"
source_line: 62
suggested_rule: "Validate and bound-check external inputs before use."
recurrence_window_days: 30
promotion_threshold:
min_occurrences: 3
min_distinct_tasks: 2
summary:
simplify_applied: 1
simplify_cosmetic_applied: 1
simplify_flagged: 1
simplify_rejected_by_user: 0
simplify_skipped_by_user: 1
harden_applied: 1
harden_flagged_critical: 1
harden_flagged_advisory: 1
harden_rejected_by_user: 0
comments_added: 2
total_additional_lines: 18
budget_utilization: "12.7%"
human_prompts_shown: 3
human_prompts_approved: 1
human_prompts_rejected: 0
human_prompts_skipped: 1
human_prompts_timed_out: 1
learning_candidates: 2
learning_promotions_recommended: 1
verification_result: "pass"
review_followup_required: true
Set review_followup_required to true when any unresolved finding remains
(critical/advisory flags, skipped or timed-out refactor proposals), when
budget_exceeded is true, or when verification is not pass. Set it to
false only when no follow-up is required.
Simplify & Harden feeds its recurring quality/security findings into the
self-improvement skill so repeated issues can become durable prompt rules.
After each run:
pattern_key:
simplify.dead_code, simplify.naming, simplify.control_flowharden.input_validation, harden.authorization, harden.error_handlingsimplify_and_harden.learning_loop.candidates.self-improvement, which logs or updates entries in
.learnings/LEARNINGS.md (instead of creating duplicate one-off notes).>= 3 occurrences across >= 2 distinct tasks in a 30-day window.CLAUDE.md, AGENTS.md, .github/copilot-instructions.md, or equivalent)
to reduce repeat issues.This keeps Simplify & Harden focused on per-task cleanup/hardening while
self-improvement owns cross-task memory and promotion.
This skill is for general coding-agent sessions where a human can approve refactors in-line.
Behavior:
[approve], [reject], [show diff], or [skip all refactors]For CI pipelines and headless automation, use simplify-and-harden-ci.
To activate this skill, reference it in your agent context file.
Agent-specific copy-paste snippets are in references/agent-context-snippets.md.
Load only the snippet for your active agent to keep context lean.
Core invariants for any agent integration:
Precaution: some agents may not reliably pause for approval in high-autonomy modes. Validate this behavior before production use.
This skill is designed to work with any coding agent that follows a task-based workflow. It is not tied to any specific agent framework or product.
Programmatic integration (agents with skill/hook APIs):
Prompt-based integration (chat-based agents without formal skill APIs):
The output schema is agent-agnostic YAML. Consuming tools only need to parse the structured summary.
This skill is agent-agnostic. It hooks into any coding agent that exposes a task completion lifecycle event. The examples below are generic -- adapt them to your agent's specific API.
The skill hooks into the agent's task completion lifecycle. Suggested integration pattern:
agent.on('task:complete', async (context) => {
if (context.diff.isNonTrivial() && !context.flags.includes('no-review')) {
const result = await skills.run('simplify-and-harden', {
diff: context.diff,
files: context.modifiedFiles,
budget: { maxLines: context.diff.linesChanged * 0.2, maxTime: 60000 }
});
context.appendOutput(result.summary);
}
});
Agents that support this skill should implement the following interface:
For agents that don't support programmatic skill hooks (e.g., chat-based coding agents like Claude Code, Cursor, Copilot Chat), this skill can be implemented as a post-task prompt injection:
After completing the task, run the Simplify & Harden review:
1. Review only the files you modified
2. Simplify: Your default action is cleanup. Apply only changes proven
behavior-preserving, such as removing a task-created unused import.
Naming, control-flow, visibility, API, policy, permission, deployment, and
security changes require approval when their effect is observable or
uncertain. Refactoring is NOT the default.
3. Harden: Check for input validation gaps, injection vectors, auth issues,
exposed secrets, and error handling problems. Apply a patch directly only
when the approved acceptance contract requires it and a targeted check can
verify it. Otherwise describe the issue with severity and ask for approval.
4. Document: Add up to 5 comments on non-obvious decisions.
5. Re-verify: Run the smallest existing checks that cover all review edits.
6. Output a summary of what you changed, what you flagged, what you left
alone, and the verification evidence.
For GitHub Actions or other CI/headless usage, run simplify-and-harden-ci.
# Example configuration (adapt path to your agent's config format)
# e.g., .agent/skills.yaml, .claude/skills.yaml, .cursor/skills.yaml
simplify-and-harden:
enabled: true
budget:
max_diff_ratio: 0.2 # Max additional changes as ratio of original diff
max_time_seconds: 60 # Hard time limit
simplify:
enabled: true
auto_apply_behavior_preserving: true
refactor_requires_approval: true # ALWAYS true -- cannot be disabled
harden:
enabled: true
auto_apply_acceptance_backed_patches: true
refactor_requires_approval: true # ALWAYS true -- cannot be disabled
document:
enabled: true
max_comments: 5
stop_hook:
mode: "interactive"
show_diff_preview: true
allow_skip_all: true
timeout_seconds: 300 # 5 min -- human is at the keyboard
timeout_action: "flag" # Assume they stepped away, don't discard
skip_patterns: # Glob patterns to exclude from review
- "**/*.test.*"
- "**/*.spec.*"
- "**/migrations/**"
Why post-completion and not continuous? Continuous review during implementation creates feedback loops that slow the agent down and can cause oscillation (simplify, then re-complicate, then re-simplify). Post-completion gives the agent a stable codebase to review against.
Why simplify-first, not refactor-first? Agents love to refactor. Given permission to "improve" code, they will restructure it. But most post-task improvements are cosmetic: a dead import, a bad name, a needlessly deep conditional. These account for 80%+ of the value with near-zero risk. Refactoring carries real risk -- it can introduce bugs, break tests, and bloat diffs. By making simplification the default and refactoring the exception, the skill delivers consistent value without surprise rewrites. The bar for a refactor should be "this is genuinely wrong" not "this could be slightly better."
Why a budget? Without constraints, agents will use review passes as license for unbounded refactoring. The 20% rule keeps the skill focused: improve what you built, don't rebuild it.
Why separate simplify from harden? They require different mindsets. Simplify asks "is this the clearest expression of my intent?" while Harden asks "how could this be exploited?" Conflating them leads to mediocre results on both. Running them sequentially also lets us prioritize security fixes when budget is tight.
Why the document micro-pass? Agents are terrible at documenting their reasoning unprompted. Humans reviewing agent-generated code consistently report that the biggest friction is understanding why a choice was made. Five comments is a trivial cost for enormous review-time savings.
Automatically, when a task matches. Use when a task is complete in a general agent session and you want a bounded quality and security sweep before signaling done. For CI pipeline execution, use simplify-and-harden-ci.
Published skills whose descriptions closely match this one, with their headline benchmark lift.
Skills that do similar work, with their headline benchmark lift.
From the same source and nearby in the catalogue.