Competitor Teardown & Positioning Brief
MIT↓ 0 downloadsFans out an analyst agent per competitor to fetch and dissect each rival's site — pricing, positioning, messaging, gaps — then a strategist synthesizes the teardowns into a single positioning brief with sharp, defensible angles for your product.
Topology
Disclosures
Everything below runs on your machine or inside the sandbox when you use this workflow. Mismatches between these declarations and the actual code block publishing.
Host hooks
Commands executed on YOUR host machine by Sandcastle lifecycle hooks.
cp .env.example .env
Sandbox hooks
Commands executed inside the sandbox container.
None declared.
Network access
Each analyst runs `curl` inside the sandbox to fetch the public HTML of the competitor URL it was assigned. No other hosts are contacted.
Shell expansion
Prompt files contain !`command` blocks — the agent CLI executes these commands at prompt-load time. They are highlighted amber in the prompt files below.
Files
Competitor teardown: {{COMPETITOR_SLUG}}
You are a competitive-intelligence analyst. Tear down a single competitor and write a structured brief. Be specific and cite the evidence you found.
The competitor's landing page
!curl -sL --max-time 30 {{COMPETITOR_URL}}
Your task
Using the fetched HTML above (and only public information), produce a teardown of
{{COMPETITOR_SLUG}} ({{COMPETITOR_URL}}). Write it to
competitors/{{COMPETITOR_SLUG}}.md with these sections:
- One-line positioning — how do they describe themselves above the fold?
- Target customer — who is the page written for?
- Core value props — the 3–5 benefits they lead with, in their words.
- Pricing & packaging — tiers, anchors, free plan / trial, anything you can infer.
- Messaging & tone — the vocabulary and emotional angle they lean on.
- Proof — social proof, logos, metrics, guarantees they cite.
- Gaps & weaknesses — what they under-serve, over-promise, or stay silent on.
Quote the page rather than paraphrasing when the exact wording matters. If the
fetch returned little usable content, say so explicitly rather than inventing
details. Commit the file with a message like research: teardown {{COMPETITOR_SLUG}}.
When the teardown file is written and committed, output <promise>COMPLETE</promise>.
Diff vs the stock Sandcastle 0.12.0 template Dockerfile — green lines were added by the author, red lines were removed from stock.
+# Sandbox image for the Competitor Teardown workflow.+# Node 22 + git + curl (analysts fetch competitor pages) + the Claude Code CLI,+# running as a non-root `agent` user.FROM node:22-bookworm-# System dependencies.RUN apt-get update && apt-get install -y --no-install-recommends \git \curl \jq \ca-certificates \&& rm -rf /var/lib/apt/lists/*# Claude Code CLI (the agent runtime).RUN npm install -g @anthropic-ai/claude-code# Non-root agent user. `sandcastle docker build-image` aligns AGENT_UID/GID to# the host user via --build-arg to avoid permission errors on bind mounts.ARG AGENT_UID=1000ARG AGENT_GID=1000RUN groupadd --gid ${AGENT_GID} agent \&& useradd --uid ${AGENT_UID} --gid ${AGENT_GID} --create-home --shell /bin/bash agentUSER agentWORKDIR /workspace
Show full Dockerfile (highlighted)
# Sandbox image for the Competitor Teardown workflow.
# Node 22 + git + curl (analysts fetch competitor pages) + the Claude Code CLI,
# running as a non-root `agent` user.
FROM node:22-bookworm
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
curl \
jq \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Claude Code CLI (the agent runtime).
RUN npm install -g @anthropic-ai/claude-code
# Non-root agent user. `sandcastle docker build-image` aligns AGENT_UID/GID to
# the host user via --build-arg to avoid permission errors on bind mounts.
ARG AGENT_UID=1000
ARG AGENT_GID=1000
RUN groupadd --gid ${AGENT_GID} agent \
&& useradd --uid ${AGENT_UID} --gid ${AGENT_GID} --create-home --shell /bin/bash agent
USER agent
WORKDIR /workspace
# Auth for the Claude Code analyst and strategist agents.
# Run `claude setup-token` on your host to generate a token, then paste it here
# in your local .sandcastle/.env (never commit the real .env).
CLAUDE_CODE_OAUTH_TOKEN=
import { run, claudeCode } from "@ai-hero/sandcastle";
import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
const IMAGE = "sandcastle:competitor-teardown";
// Edit this list to your real competitor set. Each entry fans out into its own
// analyst on its own branch, so add or remove freely.
const COMPETITORS = [
{ slug: "rival-a", url: "https://example.com" },
{ slug: "rival-b", url: "https://example.org" },
{ slug: "rival-c", url: "https://example.net" },
];
// 1. Teardown — fan out one Sonnet analyst per competitor, each on its own
// branch. Distinct branches make the parallel fan-out safe. The host hook
// seeds .env into every worktree. Each analyst fetches its assigned URL with
// `curl` (see analyst-prompt.md) and writes competitors/<slug>.md.
const teardowns = await Promise.all(
COMPETITORS.map((c) =>
run({
name: `teardown-${c.slug}`,
agent: claudeCode("claude-sonnet-4-6"),
sandbox: docker({ imageName: IMAGE }),
promptFile: ".sandcastle/analyst-prompt.md",
promptArgs: { COMPETITOR_SLUG: c.slug, COMPETITOR_URL: c.url },
branchStrategy: { type: "branch", branch: `research/${c.slug}` },
maxIterations: 2,
hooks: {
host: {
onWorktreeReady: [{ command: "cp .env.example .env" }],
},
},
}),
),
);
console.log(`Completed ${teardowns.length} competitor teardown(s).`);
// 2. Synthesize — a single Opus strategist reads every committed teardown and
// writes the positioning brief. (In a real pipeline you would merge the
// research/* branches to HEAD first; here the strategist runs on HEAD and the
// prompt points it at the competitors/ directory the analysts produced.)
const brief = await run({
name: "synthesize-brief",
agent: claudeCode("claude-opus-4-8", { effort: "high" }),
sandbox: docker({ imageName: IMAGE }),
promptFile: ".sandcastle/synthesize-prompt.md",
maxIterations: 1,
});
console.log(`Positioning brief written in ${brief.commits.length} commit(s).`);
Synthesize a positioning brief
You are a product marketing strategist. Read every competitor teardown in the
competitors/ directory and turn them into one sharp positioning brief for our
product.
Write positioning/BRIEF.md with these sections:
- Market map — a compact table of each competitor: positioning, target customer, price anchor, and their single biggest weakness.
- White space — the unmet needs and shared blind spots across the field. These are the openings.
- Our wedge — 2–3 defensible angles we can own, each tied to a specific gap you found. For each, give the angle, why it's credible, and who it wins.
- Messaging pillars — 3 headline-ready statements that express the wedge in customer language, with a one-line proof point under each.
- Traps to avoid — claims or framings where competitors are strong and we should not fight head-on.
Ground every claim in the teardowns — reference the competitor and the specific detail. Do not invent competitors or features that aren't in the source files. If a teardown is thin or missing, note the gap rather than guessing.
Commit positioning/BRIEF.md with the message marketing: positioning brief,
then output <promise>COMPLETE</promise>.
README
Competitor Teardown & Positioning Brief
Turn a list of competitor URLs into a strategist-grade positioning brief — without spending a day in browser tabs. This workflow fans out one analyst per competitor, tears down each rival's public site, then synthesizes the findings into a single brief with defensible angles you can actually ship copy against.
What it does
You give it a handful of competitor URLs. For each one, a Claude Code analyst
fetches the live landing page and dissects it: one-line positioning, target
customer, the value props they lead with, pricing and packaging, messaging and
tone, the proof they cite, and — most usefully — their gaps and weaknesses. Every
teardown is written to competitors/<slug>.md.
A Claude Code strategist then reads all of the teardowns and produces
positioning/BRIEF.md: a market map, the white space nobody is serving, 2–3
wedges your product can own (each tied to a specific gap), headline-ready
messaging pillars, and the traps to avoid where rivals are strong.
How it works
main.ts fans out the analysts with Promise.all, each on its own
research/<slug> branch so the parallel runs never collide. Each analyst pulls
its page with a !`curl` block inside the prompt — this is why the manifest
discloses network access and shell expansion. The strategist then runs once to
synthesize. The topology is a fan-out (analyst ×N → strategist).
Requirements
Set CLAUDE_CODE_OAUTH_TOKEN in .sandcastle/.env (run claude setup-token).
Edit the COMPETITORS list at the top of .sandcastle/main.ts to your real
rivals. Build the image once with npx @ai-hero/sandcastle docker build-image,
then run npx tsx .sandcastle/main.ts. Everything the agents fetch is public web
content; nothing is sent anywhere but the model.