Install
$ agentstack add skill-lool-ventures-founder-skills-deck-review ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ● Filesystem access Used
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Deck Review Skill
Help startup founders strengthen their pitch decks before sending them to investors. Produce a structured, scored review with specific, actionable recommendations grounded in current best practices from Sequoia, DocSend, YC, a16z, and Carta data. The tone is founder-first: a candid coaching session, not a VC evaluation.
Skill Metadata
- Author: lool-ventures
- Version: managed in
founder-skills/.claude-plugin/plugin.json - Compatibility: Python 3.10+ and
uvfor script execution. - Exports:
checklist.json→financial-model-review,ic-sim,fundraise-readiness
Skill Execution Model (READ FIRST)
This skill runs inline in the main thread (not as a sub-agent). The main thread has full tool access including Bash, and is responsible for orchestrating the full pipeline: running producer scripts, persisting artifacts, and dispatching the deck-review sub-agent at specific moments.
Two dispatch contexts for the sub-agent:
- Context A — Per-step analytical dispatch (Mitigation 1): Steps 4 and 5 dispatch the deck-review agent via the
Tasktool. The agent does deep analysis and returns structured JSON. The main thread captures the JSON and pipes it through the producer script (slide_reviews.pyorchecklist.py). The sub-agent does NOT write artifacts directly. - Context B — Post-compose coaching dispatch: Step 7 dispatches the sub-agent after
compose_report.pywritesreport.md. The sub-agent readsreport.md, appends## Coaching Commentary, verifies all canonical artifacts on disk, and returns a structured success payload.
Why this model: In Cowork, sub-agents have a restricted tool allowlist (no Bash). By keeping orchestration in the main thread and dispatching sub-agents only for analytical or post-compose tasks that use only Read/Edit/Glob/Grep, the pipeline works correctly in both Claude Code (CLI) and Cowork.
Tolerant JSON extraction protocol (Context A): After dispatching the sub-agent, capture its final assistant message. The sub-agent should return raw JSON, but may wrap it in `json ... ` fences or add a prose preamble. Extract JSON tolerantly:
- If the message is wrapped in a
`json ...`(or plain`...`) fence, strip the fence first. - Try to parse the stripped text directly as JSON.
- If that fails, walk through the text looking for the first
{character and tryjson.JSONDecoder().raw_decode(text[i:])— this is brace-aware and handles nested objects correctly (unlike regex, which truncates on the first}). - If extraction fails entirely, re-prompt the sub-agent with: "Your previous reply could not be parsed as JSON. Return ONLY the JSON object — no markdown fences, no prose preamble."
> See founder-skills/references/skill-execution-model.md for the full inline-skill execution model (3 dispatch contexts, Mitigation 1+2, producer contract, Cowork quirks, per-symptom triage).
Input Formats
Accept any format: PDF, PowerPoint (PPTX), markdown, or text descriptions of slides.
Available Scripts
All scripts are at ${CLAUDE_PLUGIN_ROOT}/skills/deck-review/scripts/:
checklist.py— Scores 35 criteria across 7 categories (pass/fail/warn/not_applicable)compose_report.py— Assembles artifacts into final report with cross-artifact validation;--strictexits 1 on high/medium warningsvisualize.py— Generates self-contained HTML with SVG charts (not JSON)
Also available from ${CLAUDE_PLUGIN_ROOT}/scripts/ (shared):
founder_context.py— Per-company context management (init/read/merge/validate)
Run with: python3 ${CLAUDE_PLUGIN_ROOT}/skills/deck-review/scripts/.py --pretty [args]
Available References
Read as needed from ${CLAUDE_PLUGIN_ROOT}/skills/deck-review/references/:
deck-best-practices.md— Full best practices: slide frameworks, stage-specific guidelines, design rules, AI-company requirementschecklist-criteria.md— Definitions for all 35 criteria with pass/fail/warn thresholdsartifact-schemas.md— JSON schemas for all artifacts
Artifact Pipeline
Every review deposits structured JSON artifacts into a working directory. The final step assembles all artifacts into a report and validates consistency. This is not optional.
| Step | Artifact | Producer | |------|----------|----------| | 1 | founder context | founder_context.py read/init | | 2 | deck_inventory.json | deck_inventory.py (agent provides JSON via stdin) | | 3 | stage_profile.json | stage_profile.py (agent provides JSON via stdin) | | 4 | slide_reviews.json | slide_reviews.py (agent provides JSON via stdin) | | 5 | checklist.json | checklist.py | | 6 | Report | compose_report.py (writes both report.json and report.md) |
Rules:
- Deposit each artifact before proceeding to the next step
- For producer-script artifacts (Steps 2-4), the agent supplies JSON on stdin and the script schema-validates against
references/schemas/.schema.json. Never write artifacts directly viaWriteorEdit— always pipe through the producer script sometadata.run_idis injected and the schema is enforced. - If a step is not applicable, deposit a stub:
{"skipped": true, "reason": "..."}
Keep the founder informed with brief, plain-language updates at each step. Never mention file names, scripts, or JSON. After each analytical step (4–5), share a one-sentence finding before moving on.
Workflow
Step 0: Path Setup
SCRIPTS="${CLAUDE_PLUGIN_ROOT}/skills/deck-review/scripts"
REFS="${CLAUDE_PLUGIN_ROOT}/skills/deck-review/references"
SHARED_SCRIPTS="${CLAUDE_PLUGIN_ROOT}/scripts"
ARTIFACTS_ROOT="${ARTIFACTS_ROOT:-$(pwd)/artifacts}"
mkdir -p "$ARTIFACTS_ROOT"
# Preliminary RUN_ID — used by Step 1 (founder_context init) before slug-aware
# setup_run.py runs. Will be reused by setup_run via --run-id, OR overwritten
# by gate_state.json on re-invocation (see below).
RUN_ID="${RUN_ID:-$(date -u +%Y%m%dT%H%M%SZ)}"
If CLAUDE_PLUGIN_ROOT is empty OR the path it resolves to does not exist in your environment (in Claude Cowork it substitutes to a host-side path that is not present inside the session VM — test with ls), fall back: Glob for **/skills/deck-review/scripts/checklist.py, strip to get SCRIPTS, derive REFS and SHARED_SCRIPTS. In Claude Cowork this is always the case — don't retry the substituted path; go straight to the Glob fallback. If Glob returns multiple matches, prefer the one under a plugin mount (.remote-plugins/ or the plugins cache) over any workspace copy. If Glob returns nothing, locate it with Bash: find / -path '*/skills/deck-review/scripts/checklist.py' 2>/dev/null | head -5.
After Step 1 (when the slug is known) — call setup_run.py to resolve REVIEW_DIR and clean stale state in one atomic step. Re-invocation special case: if the caller's task prompt indicated this is a resume (it includes REVIEW_DIR=... and / or RUN_ID=..., or $REVIEW_DIR/gate_state.json already exists with a non-empty answer), rehydrate RUN_ID from gate_state.json's metadata.run_id and skip the --clean flag:
# Resolve REVIEW_DIR (from prompt if provided, else derive)
if [ -z "$REVIEW_DIR" ]; then
REVIEW_DIR="$ARTIFACTS_ROOT/deck-review-$SLUG"
fi
mkdir -p "$REVIEW_DIR"
mkdir -p "$REVIEW_DIR/.staging" # for ad-hoc sub-agent JSON staging
IS_RESUMING=""
if [ -f "$REVIEW_DIR/gate_state.json" ]; then
GATE_ANSWER="$(python3 -c 'import json,sys;print(json.load(open(sys.argv[1])).get("answer",""))' "$REVIEW_DIR/gate_state.json")"
if [ -n "$GATE_ANSWER" ]; then
IS_RESUMING=1
RUN_ID="$(python3 -c 'import json,sys;print(json.load(open(sys.argv[1])).get("metadata",{}).get("run_id",""))' "$REVIEW_DIR/gate_state.json")"
fi
fi
if [ -z "$IS_RESUMING" ]; then
SETUP_JSON="$(python3 "$SCRIPTS/setup_run.py" \
--artifacts-root "$ARTIFACTS_ROOT" \
--slug "$SLUG" \
--run-id "$RUN_ID" \
--clean \
--pretty)"
REVIEW_DIR="$(echo "$SETUP_JSON" | python3 -c 'import json,sys;print(json.load(sys.stdin)["review_dir"])')"
# RUN_ID stays the preliminary value passed via --run-id; setup_run echoes it back.
fi
Pass RUN_ID to every producer script via --run-id. Producer scripts inject it into metadata.run_id automatically. compose_report.py enforces that all required artifacts share the same run_id and emits a MISSING_METADATA (high) warning for any artifact without one. The rehydration above is what keeps run_id stable across the gate — without it, a fresh RUN_ID on re-invocation would mismatch the pre-gate artifacts and trip STALE_ARTIFACT in compose.
On re-invocation ($IS_RESUMING is set): skip Steps 2 and 3 if deck_inventory.json and stage_profile.json already exist with a matching metadata.run_id. They were preserved across setup_run.py because that path was skipped, so re-running them would just overwrite identical content.
Step 1: Read or Create Founder Context
python3 "$SHARED_SCRIPTS/founder_context.py" read --artifacts-root "$ARTIFACTS_ROOT" --pretty
Exit 0 (found): Use the company slug and pre-filled fields. Proceed to Step 2.
Exit 1 (not found): This is normal for a first run — do not treat it as an error. Use AskUserQuestion (NOT plain chat) to ask for company name, stage, sector, and geography. Provide at least 2 options. Then create:
python3 "$SHARED_SCRIPTS/founder_context.py" init \
--company-name "Acme Corp" --stage seed --sector "B2B SaaS" \
--geography "US" --artifacts-root "$ARTIFACTS_ROOT" \
--run-id "$RUN_ID"
Exit 2 (multiple): Present the list, ask which company, re-read with --slug.
Step 2: Ingest Deck -> deck_inventory.json
Ingestion pitfalls — common issues that degrade review quality:
- PDF image-only slides: Some PDFs embed slides as images with no extractable text. If Read returns blank or garbled content, note
input_quality: "image_only"indeck_inventory.jsonand base the review on visual description + OCR-level best effort. Flag reduced confidence in coaching commentary. - PPTX speaker notes vs. slide content: Speaker notes often contain the real narrative; slide text is abbreviated. Extract both — notes go into
content_summary, slide text intoheadline. Do not discard notes. - Multi-file submissions: Founder sends v1 + v2, or deck + appendix as separate files. Ask which is the primary deck before proceeding. Do not merge or review both simultaneously.
- Partial decks: Deck has fewer than 5 slides or is clearly a subset. Proceed but set
confidence: "low"in stage_profile and note the limitation. Missing-slides detection still runs normally. - Wrong file type: File named
.pdfbut is actually a Word doc or image. If Read fails, try alternate format before asking the founder for a re-upload.
Read the provided deck. For each slide, extract: headline, content summary, visuals description, word count estimate. Then write the inventory through the producer script:
cat `stage_profile.json`
Determine pre-seed/seed/series-a from signals in the deck. Read `references/deck-best-practices.md` for stage-specific frameworks. Record: detected stage, confidence, evidence, whether AI company, expected slide framework, stage benchmarks.
**Stage signals:** Pre-seed: no revenue, LOIs/waitlist, prototype, ",
"question": "Does this stage detection look right?",
"options": ["Looks right", "Different stage", "Not sure — proceed anyway"],
"context_summary": "..."
},
"review_dir": "",
"run_id": ""
}
For out-of-scope stages (series_b, growth): use gate_id: "out_of_scope_choice", question "This looks out of scope. What should I do?", options ["Stop review", "Different stage", "Proceed anyway (best-effort)"].
After the gate (when gate_state.json already has an answer): read $GATE_ANSWER from the file and branch:
Looks right: proceed to Step 4 with the detected stage.Different stage: emit a second gate (gate_idstage_choice) viagate_state.py emitto ask which stage. Treat this as a fresh gate — return a newneeds_inputpayload and let the parent answer it the same way. When that one comes back answered, runstage_profile.py --rebuild-stageand re-emit the originalstage_confirmationgate to confirm.Not sure — proceed anyway: proceed with detected stage, setconfidence: "low"viastage_profile.py --rebuild-stage.Stop review(out-of-scope): exit. Do not run later steps.Proceed anyway (best-effort): rebuild profile with--rebuild-stage series_aand add a low-confidence note.
Sub-agent JSON staging
When a sub-agent returns JSON too large for bash heredoc, write it to $REVIEW_DIR/.staging/_input.json first, then pipe via:
cat "$REVIEW_DIR/.staging/_input.json" | python3 "$SCRIPTS/.py" ...
The .staging/ directory is created at setup and removed at cleanup. This avoids Operation not permitted errors that occur when writing to the session outputs mount (Cowork marks it read-only post-write).
Step 4: Review Each Slide -> slide_reviews.json (Context A dispatch)
Dispatch the deck-review sub-agent in Context A (SLIDE_REVIEWS). Do not do the slide analysis yourself in the main thread — dispatch it via the Task tool so the analysis runs in an isolated context with the full deck text and stage profile.
Dispatch prompt template:
CONTEXT: SLIDE_REVIEWS
REVIEW_DIR:
RUN_ID:
You are the deck-review agent dispatched in Context A (SLIDE_REVIEWS). Read
the deck at and the stage profile at
/stage_profile.json. Compare each slide against the stage-specific
framework and non-negotiable principles from
${CLAUDE_PLUGIN_ROOT}/skills/deck-review/references/deck-best-practices.md
and references/checklist-criteria.md.
For each slide: identify strengths, weaknesses, and specific recommendations.
Map to expected framework. Flag missing expected slides. Every critique must
cite a specific best-practice principle.
Return JSON only — exactly the shape expected by slide_reviews.py (no metadata
block; the producer script adds it):
{
"reviews": [
{"slide_number": 1, "maps_to": "...", "strengths": ["..."],
"weaknesses": ["..."], "recommendations": ["..."],
"best_practice_refs": ["..."]}
],
"missing_slides": [
{"expected_type": "...", "importance": "important", "recommendation": "..."}
],
"overall_narrative_assessment": "..."
}
After the sub-agent returns: apply the tolerant JSON extraction protocol (see "Skill Execution Model" preamble) to obtain the structured JSON from the sub-agent's final message. Then pipe through the producer script:
cat
REVIEWS_EOF
Step 5: Score Checklist -> checklist.json (Context A dispatch)
Dispatch the deck-review sub-agent in Context A (CHECKLIST). Dispatch via the Task tool.
Dispatch prompt template:
CONTEXT: CHECKLIST
REVIEW_DIR:
RUN_ID:
You are the deck-review agent dispatched in Context A (CHECKLIST). Evaluate all
35 criteria from ${CLAUDE_PLUGIN_ROOT}/skills/deck-review/references/checklist-criteria.md
using the deck content (read from deck file or from slide_reviews.json for
reference), the stage profile at /stage_profile.json, and the
deck inventory at /deck_inventory.json.
For non-AI companies (is_ai_company: false), mark the 4 AI criteria
(ai_retention_rebased, ai_cost_to_serve_shown, ai_defensibility_beyond_model,
ai_responsible_controls) as not_applicable.
Evidence quality rules:
- Every fail and warn MUST cite a specific best-practice principle or benchmark.
- Every pass MUST note what was checked.
- not_applicable items MUST include a reason.
Return JSON only — the items array without a summary (the producer script
computes the summary):
{"items": [{"id": "purpose_clear", "status": "pass", "evidence": "...", "notes": "..."}, ...all 35 items...]}
**After the sub-ag
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: lool-ventures
- Source: lool-ventures/founder-skills
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.