Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when studying a SaaS web product from the outside in order to rebuild, clone or copy it (ClickUp, Pipedrive, Notion, a CRM, a project tool), when documenting its UX, screens, components, data model, business rules or API through a browser the agent drives, when assessing what would block a clone from launching (permissioned integrations, regulation, certifications), or when an agent must explore a live SaaS account without damaging production data or notifying real people.
SkillScore92/100
Test results 92
3/3 safety checks passed
13%92%of test cases passed +79 pts
Passed 22 of 24 test cases with the skill, and 3 of 24 without it.
19 fixed3 passed either way2 still failing0 broke1 errored
One test taskWe observed that clicking 'Archive' in Linear immediately hides an issue from the active board and issues a GraphQL request to `archiveIssue`. Formulate the rule entry for the rules directory, including the required tag format showing where the behavior was verified.
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add alextnetto-reverse-engineering-saas
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("alextnetto-reverse-engineering-saas")
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 alextnetto-reverse-engineering-saasThe 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/alextnetto-reverse-engineering-saas/SKILL.md https://app.decimal.ai/s/alextnetto-reverse-engineering-saas/SKILL.md.claude/skills/alextnetto-reverse-engineering-saas/SKILL.mdThis gets SKILL.md only. The skill's 10 other files are 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 alextnetto-reverse-engineering-saasimport 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are 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 alextnetto-reverse-engineering-saasfrom 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are 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 alextnetto-reverse-engineering-saasimport 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are 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 alextnetto-reverse-engineering-saasimport 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are 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 alextnetto-reverse-engineering-saasfrom 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are 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 alextnetto-reverse-engineering-saasfrom 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are 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 alextnetto-reverse-engineering-saasimport 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/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 10 other files are 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 alextnetto-reverse-engineering-saasfrom 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are 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 alextnetto-reverse-engineering-saasfrom 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are not included.
Deep Agents' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" deepagents
decimalai skills add alextnetto-reverse-engineering-saasimport 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are not included.
Its own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" agent-framework
decimalai skills add alextnetto-reverse-engineering-saasimport 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are not included.
Strands' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" strands-agents
decimalai skills add alextnetto-reverse-engineering-saasfrom 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("alextnetto-reverse-engineering-saas")
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/alextnetto-reverse-engineering-saas/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/alextnetto-reverse-engineering-saas/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 10 other files are 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 alextnetto-reverse-engineering-saasNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/alextnetto-reverse-engineering-saas/SKILL.md https://app.decimal.ai/s/alextnetto-reverse-engineering-saas/SKILL.md.agents/skills/alextnetto-reverse-engineering-saas/SKILL.mdThis gets SKILL.md only. The skill's 10 other files are not included.
Give its text to your model as instructions. No account or package needed.
This gets SKILL.md only. The skill's 10 other files are not included.
Raw files: /s/alextnetto-reverse-engineering-saas/SKILL.md · /s/alextnetto-reverse-engineering-saas.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/alextnetto-reverse-engineering-saas/SKILL.mdcurl -fsSL https://app.decimal.ai/s/alextnetto-reverse-engineering-saas.jsonThis gets SKILL.md only. The skill's 10 other files are 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.
The output is a knowledge base (KB) on disk from which a team that never used the product can rebuild it and take it to production. It is delivered as REPORT.html, the report a person reads, and a zip the user can hand to any coding agent. Two rules are absolute:
The KB is the only memory between sessions. Context ends before the work does, so write to disk after every feature.
<skill> below means this skill's directory. Run scripts as node <skill>/scripts/<name>.mjs.
Do not use this skill when the source code is available (read the code), for native binaries or Electron internals (use a decompiler or REA), or for a single question about one feature.
STATUS.md, sandbox/environment.md and the open rows of sandbox/ledger.csv. Close or verify every open row before new exploration. Run node <skill>/scripts/check-kb.mjs <kb>.node <skill>/scripts/init-kb.mjs --product "<Name>" --git from the working directory. It creates ./re-<product>/; pass a directory first to choose another place. Then fill 00-charter.md from the user's request. Artifact templates (screen, component, entity, flow, rules, topic, session log) are copied to <kb>/_templates/.STATUS.md under "Residuals" as pre-existing.references/safety.md before anything else.| Phase | Output | Browser writes |
|---|---|---|
| 1 Charter | 00-charter.md: goal, scope, priorities, clone target market, unattended or attended | None |
| 2 Environment and preflight | sandbox/environment.md | None until the preflight passes |
| 3 Recon from public sources | sources.md, glossary.md, seeds of inventory/features.md and data-model/, barrier scan in clone/barriers.md | None (use web fetch, not the browser) |
| 4 Map | inventory/screens.md, routes, stack, token baseline | A0, A1 |
| 5 Deep dive, one feature at a time | screens/, components/, rules/, flows/, data-model/, api/, topics/ | Per the matrix below |
| 6 Synthesis | clone/prd.md, clone/parity.md, clone/barriers.md, clone/implications.md, design/tokens.md | None |
| 7 Close | Updated STATUS.md, reconciled ledger, check-kb passes; at the end of the study, the handoff zip | Restore and teardown only |
Details per phase: references/exploration.md. KB layout, IDs and formats: references/knowledge-base.md.
Use the highest level available. Record it in sandbox/environment.md.
| Level | What it is | Who creates it |
|---|---|---|
| L1 Dedicated account | Trial or sandbox account with its own login, open in a separate browser profile that has no production session | The user. The agent never creates accounts and never types passwords |
| L2 Separate workspace | A new workspace or company under the user's login, with no other members | The agent, when the user asked for a test environment and creation is free (no billing step, no terms to accept). Creating it is an A4 action with a ledger row |
| L3 Sandbox container | One list, project or pipeline inside production, named 🧪 [RE] Sandbox, private where the product allows | The agent, when the user asked for a test environment. Creating it is an A2 action with a ledger row. A container the user already designated keeps its name |
| L4 Observe only | Production, no writes | Default when the user gave no permission to write |
The user asked for a test environment when they say so, or tell you to test or try features ("test everything", "try the automations"), in any language. A request to look, read or document only is not permission to write: use L4.
When the user asked for a test environment and no L1 exists: create L2 if free, otherwise L3, and add "Needs human: dedicated trial account in a separate browser profile (L1)" to STATUS.md. If creating a workspace or company starts a subscription or a trial (Pipedrive "Add company", for example), it is A5: use L3.
At L3, "inside the sandbox" means the container plus records the agent created with the [RE] prefix that link only to sandbox records (a person created from a sandbox deal). When other members can see the container, remove all A2 records, the container included, at the end of every session, and in unattended mode finish the teardown before the team's working hours.
An unattended L3 session that starts during the team's working hours (from the charter; otherwise 08:00 to 18:00 on weekdays in the account's time zone) writes only when the team cannot see the records: a private container, or records set to operator-only visibility (references/safety.md, L3). The container's name may stay visible. Otherwise do the phases without writes first (recon, map) and put the writes under "Next actions" for a session outside working hours. In both cases keep the sandbox up as briefly as possible and tear it down in the same session. Record the start time and the choice in environment.md.
| Class | Examples |
|---|---|
| A0 Read | Navigate, open, hover, read the DOM, screenshot |
| A1 Transient UI | Open a menu or dialog and cancel, unsaved filter or sort, resize the window |
| A2 Sandbox data | Create, edit, delete records the agent created inside the sandbox, including views and fields scoped to the container |
| A3 Personal preference | Theme, layout toggles, notification settings, dismissing banners, marking notifications as read |
| A4 Shared configuration | Custom fields, statuses or tags above the container (or of unknown scope), automations, integrations, webhooks, permissions, workspace settings, imports, shared templates, creating a workspace |
| A5 Outbound or irreversible | Any email, message, notification or invite that reaches anyone except the operator; assigning, mentioning, sharing with or following anyone except the operator; billing, plan or trial changes; API tokens; connecting integrations; deleting anything not in the ledger; accepting terms; entering passwords |
| L1 | L2 | L3 | L4 | |
|---|---|---|---|---|
| A0 | Yes | Yes | Yes | Yes |
| A1 | Yes | Yes | Revert in the same session | Revert in the same session |
| A2 | Yes | Yes | Inside the container only | No |
| A3 | Yes | Ledger row with before-value, restore before the session ends | Same as L2 | No |
| A4 | Yes | Creating the workspace, then changes inside it only | No | No |
| A5 | No | No | No | No |
A5 is forbidden at every level. Integrations: the agent may open an OAuth consent screen to record the scopes it asks for, then cancel; it never approves one. At L1 the user connects test accounts they own (a test mailbox, a test calendar), and the agent may then exercise the integration between those accounts only. Tests that need a second person (collaboration, permissions, notifications) go to "Needs human": they belong at L1, where the user adds a second account of their own. Adding a member to production is the user's decision (often a paid seat). Features gated by a plan the environment lacks are blocked: plan in coverage; starting a trial is the user's decision.
An automation that emails or notifies only the operator is A4, not A5. Disable time-triggered automations before the session ends.
environment.md.[RE] fake data in a container the product cannot make private; nothing else.sandbox/ledger.csv, with the before-value when an existing thing changes.If one check fails, do not act. Mark the item blocked in inventory/coverage.md with the reason and continue with another item.
These change data or state without a Save button. Treat them as writes of the class they touch:
Check persistence by reloading. Never experiment on shared views: rebuild the case inside the sandbox.
Do not click through. Log the item as blocked and move on when you see: billing, upgrade or trial dialogs; any "send", "invite", "notify", "share", "apply to all" or "cannot be undone"; login, 2FA or CAPTCHA prompts; a location mismatch; any change that appears outside the sandbox.
Exception: deleting your own ledger items inside the sandbox. Their delete dialogs often say the action cannot be undone. Confirm when the dialog names only those items, sends or notifies nothing, and the write gate passes. A dialog that would also delete or change anything else is still a stop.
In unattended mode never ask the user. Write the item under "Needs human" in STATUS.md and continue. "Don't ask me anything" changes how blocks are reported. It does not widen what you may touch.
After a mistake: undo it at once if the undo itself reaches nobody, then add a ledger row with class incident, what happened and what remains. If the undo would notify someone again (unassigning, deleting a comment), leave it and write it under "Needs human". Procedure: references/safety.md.
Record in environment.md: members who could be notified; active automations, webhooks, integrations, email and calendar sync in the write scope; plan and trial end date; baseline counts of the container and of the operator's own records, by filter or count endpoint, never by pulling full record lists. If any automation, webhook, integration or sync would fire on records in the write scope, do not write there. Checklist: references/safety.md.
[RE]. Emails at example.com. No real customer or teammate names.[customer] or [person].scripts/page/mask.js before each screenshot that can show real data. Pass the containers of popovers, menus and lists as selectors: they stay masked when they render later. Company configuration (type names, reasons, field labels) matches no pattern: pass it as names or crop it out. A screenshot that shows unmasked personal data is deleted at once and retaken; it never enters the KB.Procedures for each level, the ledger format, teardown and incidents: references/safety.md.
For each feature, in the order of inventory/coverage.md:
sandbox/fixtures.md, create the records, add ledger rows.R-### rule in Given/When/Then form.api-shapes.js installed, map each action to its endpoint and payload shape.coverage.md. Restore A1 and A3 state.Do not start the next feature while findings exist only in context. A finding without evidence goes to questions.md as "Confirm: ...", never into a rule.
A clone that cannot launch is not a clone. Scan for barriers during recon and update them during the deep dive:
Record each one as BR-### in clone/barriers.md with category, features blocked, gatekeeper, severity (blocks launch, blocks feature, adds lead time, adds cost, moat), market weight (how much buyers in the target market need the blocked feature), lead time and cost, mitigation and evidence. Put launch blockers and long approvals first in the PRD build order. This is not legal advice: a legal reading without a source is [inf] with a question for counsel. Categories, sources and format: references/barriers.md.
| Tag | Meaning |
|---|---|
[obs EV-012] | The agent saw it in the product; the evidence file exists |
[net EV-013] | Network capture (shape file or request list) |
[doc SRC-004] | Public documentation listed in sources.md |
[inf] | Inference. The same line must cite the Q-### that would confirm it |
Rules, barriers and data model fields need obs, net or doc; [inf] with a Q-### is allowed while the question is open (the checker warns). Every screen, component, flow and topic file ends with a "Not tested" list. Record each evidence file in evidence/index.csv (date, session, route, what it shows, masked).
Paste the file content into the browser's JavaScript tool. Each script returns JSON and stores nothing outside the page. Page scripts return structure, counts and shapes. Known exceptions, filtered but not eliminated: test-ID values and route segments that look like identifiers, and short configuration values (statuses, types) in api-shapes.js; review them before saving at L3 and L4.
| Script | Returns |
|---|---|
scripts/page/inventory.js | Framework, component tag names, test IDs, ARIA roles, internal route patterns, third-party SDKs |
scripts/page/tokens.js | CSS variables and the most frequent colors, type sizes, radii, spacing and shadows |
scripts/page/api-shapes.js | Installs a recorder; __re.api.dump() returns endpoint templates and JSON shapes; set __re.api.enumSamples = false to drop the short enum values too |
scripts/page/mask.js | Blurs emails, phones, money, Brazilian tax IDs, small avatars, given names, matching placeholders, and given selectors as CSS rules that also cover elements rendered later; __re.mask.clear() removes it |
scripts/page/annotate.js | Numbered outlines on given elements for anatomy screenshots |
To show progress before the end, run node <skill>/scripts/build-report.mjs <kb> and send REPORT.html.
Tool-specific notes (saving screenshots, network, profiles, drag and drop): references/extraction.md and references/tools.md.
STATUS.md: header (date, session, phase, environment, open ledger rows), Summary, Next actions (three), Needs human, Blocked, Last session, Residuals.log/<date>-s<NN>.md.node <skill>/scripts/check-kb.mjs <kb> and fix every error.STATUS.md, then run check-kb --closing.node <skill>/scripts/pack-kb.mjs <kb>. It writes REPORT.html (one self-contained page for people, in reading order: overview, what the product does, screens, flows, rules, data model, API, design, build plan, what to prepare before launch, evidence; it tells agents to read BUILD.md instead) and the zip. Send both to the user in the chat, the report first as the main deliverable. Attach them with the agent's file-sending tool when there is one; otherwise give their paths. The zip holds the KB and BUILD.md, a brief any coding agent can follow, and leaves out sandbox/ and log/ except a copy of the ledger without object IDs, locations or URLs. With them, send the three-line summary from STATUS.md, the "Needs human" list, and one line: "Open REPORT.html to read the study; unzip the zip and give the folder to a coding agent, starting at BUILD.md."The study ends when coverage is complete or the user says to stop. When the user stops early, write the Phase 6 files from what exists, close, and pack: STATUS.md tells the reader what is missing. At L1 the trial account may keep its fixtures as kept ("trial kept for the developers"); ending the trial is the user's action. pack-kb runs the regular check, so rows marked human do not block the handoff; list them under "Needs human".
Every ledger row ends the session as restored, removed, fixture (test data left for the next session), kept (the user decided to keep it) or human (only the user can resolve it; the note says what to do). --closing fails on open, fixture and human.
When time or context runs short, stop exploring and do this, in order: (1) ledger rows for every change not yet recorded, unknown where the before-value is not known; (2) undo what affects other people (shared views, assignments); (3) findings to files, unverified ones as Q-###; (4) STATUS.md with next actions and needs human; (5) check-kb and commit. Stop exploring early enough to finish all five.
Rebuild from behavior, not from assets. Do not copy source code, icons, illustrations, logos, brand names or long passages of text into the clone. Record microcopy as reference and write new copy for the clone. Use only the user's own account. Do not bypass access controls or read other customers' data. Keep request rates human.
Most SaaS terms forbid reverse engineering or using the service to build a competing product. Record the clause and its URL in 00-charter.md and add it to "Needs human" in STATUS.md. The decision belongs to the user; the study follows the user's original instruction until the user decides otherwise.
| Thought | Reality |
|---|---|
| "I didn't click Save, so nothing changed" | Autosave, drag, toggles and read receipts write. Reload and check |
| "It's a sandbox task, assigning a teammate is harmless" | Assignments and mentions notify real people. Operator only |
| "The shared board is the best example" | Rebuild the case in the sandbox. Shared views are read-only |
| "The user said don't ask, so I'll do it in production" | "Don't ask" changes reporting, not permissions |
| "I'll remember what I changed" | Ledger row before the next action |
| "I'll write the docs at the end" | Context ends first. Write after each feature |
| "The docs say so" | That is [doc], not [obs]. Tag it |
| "It's only screens, we can copy it" | Approvals, licenses and certifications decide whether the clone can launch. Scan barriers |
| "Opening the editor is read-only" | Many editors autosave. Cancel, reload and check |
| "I'll rebuild the shared view's old filters from memory" | A guess can make it worse. Ledger incident, "Needs human" |
| "The undo is the polite thing" | Unassigning or deleting can notify the person again. Check first |
Skills that do similar work, with their headline benchmark lift.
From the same source and nearby in the catalogue.