Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "crawlio",
"description": "AI skills for website crawling, observation, and analysis — powered by Crawlio",
"version": "1.1.0",
"description": "AI skills and intelligence runtime for website crawling, investigation, and analysis — powered by Crawlio",
"version": "1.2.0",
"author": { "name": "Crawlio" },
"homepage": "https://crawlio.app",
"repository": "https://github.com/Crawlio-app/crawlio-plugin",
"license": "MIT",
"keywords": ["crawling", "web-scraping", "site-analysis", "observation", "mcp", "agent-skills"]
"keywords": ["crawling", "web-scraping", "site-analysis", "observation", "mcp", "agent-skills", "intelligence-runtime", "investigation"]
}
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@

---

5 skills, 1 agent, and an MCP server — packaged as a plugin that follows the [Agent Skills](https://agentskills.io) open standard. The skills are plain Markdown files that encode domain judgment: when to use which settings, how to interpret observations, what constitutes a finding. The plugin format is just the distribution mechanism.
6 skills, 3 commands, 1 agent, and an MCP server — packaged as a plugin that follows the [Agent Skills](https://agentskills.io) open standard. The skills are plain Markdown files that encode domain judgment: when to use which settings, how to interpret observations, what constitutes a finding. The plugin format is just the distribution mechanism.

## Table of Contents

- [Prerequisites](#prerequisites)
- [Setup](#setup)
- [Intelligence Runtime](#intelligence-runtime)
- [Skills](#skills)
- [Agent](#agent)
- [How It Works](#how-it-works)
Expand Down Expand Up @@ -90,6 +91,22 @@ Or edit `.mcp.json` to use a full path:

Launch the Crawlio macOS app. It starts a local HTTP control server automatically.

## Intelligence Runtime

The plugin includes two orchestration layers for structured web investigation:

| Command | Layer | Description |
|---------|-------|-------------|
| `/crawlio:crawlio-loop` | **Crawlio Loops** | AI-orchestrated multi-phase pipelines via Claude Code agents. Deep, flexible. ~2-5 min, $0.05-0.50/run |
| `/crawlio:crawlio-seq` | **Crawlio Sequences** | Deterministic Swift state machines with local AI inference. Fast, free. ~5-30 sec, $0.00-0.01/run |
| `/crawlio:help` | — | Explain the intelligence runtime |

Both layers produce interchangeable `EvidenceEnvelope<T>` evidence across 7 investigation families:

**investigate** · **monitor** · **extract** · **compare** · **clone** · **test** · **compose**

Crawlio Loops use [crawlio-browser-agent](https://github.com/Crawlio-app/crawlio-browser-agent) for browser-side intelligence. Crawlio Sequences use the native [Crawlio](https://crawlio.app) macOS app with optional local AI inference via Apple Neural Engine.

## Skills

| Skill | Description |
Expand All @@ -99,6 +116,7 @@ Launch the Crawlio macOS app. It starts a local HTTP control server automaticall
| [`observe`](#crawlioobserve) | Query the observation timeline with filters |
| [`finding`](#crawliofinding) | Create and query evidence-backed findings |
| [`audit-site`](#crawlioaudit-site) | Multi-pass site audit with findings report |
| [`crawlio-seq`](#crawliocrawlio-seq) | Manage the intelligence runtime — create loops and sequences |

### `/crawlio:crawl-site`

Expand Down
48 changes: 48 additions & 0 deletions commands/crawlio-loop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
description: "Run a Crawlio Loop — AI-orchestrated multi-phase investigation via deep agents"
allowed-tools: Agent, Read, Write, Bash, Glob, Grep
argument-hint: "<family> <url>"
---

# Crawlio Loop

Run an AI-orchestrated investigation loop against a target URL. Loops use Claude Code agents to reason through multi-phase pipelines, producing typed `EvidenceEnvelope<T>` evidence.

## Arguments

`$ARGUMENTS` should be `<family> <url>`.

**Families:** `investigate` `monitor` `extract` `compare` `clone` `test` `compose`

## Execution

1. Read the loop definition from `loops/$FAMILY.json`
2. Generate a runId: `run-<family>-<hostname>`
3. For each phase in the loop:
- Spawn the phase agent via `Agent()` tool
- Pass the prior phase's evidenceId in the prompt
- Capture the output `EVIDENCE_ID=<id>`
4. Run `auditEvidence()` on all produced evidence
5. Report results

## Evidence

All evidence is written to `.crawlio/evidence/runs/<runId>/` as `EvidenceEnvelope<T>` JSON files. Evidence must be produced via `wrapEvidence()` + `writeEvidence()`.

## Families

| Family | Output | Key Phases |
|--------|--------|------------|
| `investigate` | TechBlueprint | crawl, analyze, network, synthesize |
| `monitor` | DiffReport | baseline, recapture, diff |
| `extract` | DesignTokens / AuthFlow / APIMap | crawl, extract, synthesize |
| `compare` | ComparisonReport | crawl-a, crawl-b, compare, synthesize |
| `clone` | CloneBlueprint | crawl, analyze, extract-design, synthesize |
| `test` | TestSuite | crawl, analyze, audit, synthesize |
| `compose` | CompetitiveDossier | 8 phases including audit + extraction |

## Prerequisites

- [crawlio-browser-agent](https://github.com/Crawlio-app/crawlio-browser-agent) Chrome extension + MCP server
- Loop JSON definitions in `loops/` directory
- Phase agents in `.claude/agents/`
43 changes: 43 additions & 0 deletions commands/crawlio-seq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
description: "Run a Crawlio Sequence — deterministic Swift-native investigation pipeline"
allowed-tools: Read, Bash, Glob, Grep
argument-hint: "<family> <url>"
---

# Crawlio Sequence

Run a deterministic investigation sequence using the native Swift runtime. Sequences execute as state machines — no LLM in the orchestration loop. Local AI inference (ANE) handles reflex tasks; API calls handle synthesis.

## Arguments

`$ARGUMENTS` should be `<family> <url>`.

**Families:** `investigate` `monitor` `extract` `compare` `clone` `test` `compose`

## Execution

1. Read the sequence definition from `sequences/$FAMILY.json`
2. Invoke `CrawlSequenceRunner` via the Crawlio CLI:
```bash
crawlio sequence <family> <url>
```
3. The runner manages the state machine:
- Phases execute as Swift async functions
- Reflex tasks route to local ANE inference (Tier 2)
- Synthesis tasks route to Claude API via MCP (Tier 3)
- Evidence is chained automatically
4. Report results with evidence IDs

## Tiered Cognition

| Tier | Handler | Cost | Latency |
|------|---------|------|---------|
| **1. Deterministic** | Swift parsers (CrawlioCore) | $0.00 | <100ms |
| **2. Local AI** | mentu-ane (Apple Neural Engine / CPU) | $0.00 | ~200ms |
| **3. Cloud AI** | Claude via MCP | $0.01-0.10 | 2-10s |

## Prerequisites

- [Crawlio](https://crawlio.app) macOS app running locally
- For Tier 2: SmolLM2-135M model downloaded (~269MB) via Crawlio Settings
- For Tier 3: Valid API credentials configured
36 changes: 36 additions & 0 deletions commands/help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
description: "Explain the Crawlio Intelligence Runtime — loops, sequences, and evidence"
allowed-tools: Read
---

# Crawlio Intelligence Runtime

Two orchestration layers for structured web investigation:

## Crawlio Loops (`/crawlio:crawlio-loop`)
AI-orchestrated multi-phase pipelines via Claude Code agents.
- **Runtime:** crawlio-browser-agent (TypeScript, npm)
- **Cost:** $0.05-0.50 per run | **Speed:** ~2-5 minutes
- **Best for:** Complex reasoning, browser interaction, creative analysis

## Crawlio Sequences (`/crawlio:crawlio-seq`)
Deterministic Swift state machines running natively in the Crawlio macOS app.
- **Runtime:** Crawlio-app (Swift 6, macOS 15+)
- **Cost:** $0.00-0.01 per run | **Speed:** ~5-30 seconds
- **Best for:** High-volume crawl+parse, monitoring, deterministic extraction

## The 7 Families

| Family | What It Produces |
|--------|-----------------|
| **investigate** | Full-depth TechBlueprint of a site's stack |
| **monitor** | DiffReport showing what changed between visits |
| **extract** | Design tokens, auth flows, or API maps |
| **compare** | Side-by-side analysis of two websites |
| **clone** | Blueprint for reproducing a site's design system |
| **test** | Security / accessibility / performance test suite |
| **compose** | Comprehensive competitive dossier |

## Evidence

Both layers produce interchangeable `EvidenceEnvelope<T>` with typed payloads, gap detection, quality derivation, and provenance tracking. A Loop can consume evidence from a Sequence and vice versa.
36 changes: 36 additions & 0 deletions hooks/evidence-gate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# evidence-gate.sh — PostToolUse hook
# Warns when files are written directly to .crawlio/evidence/ without using
# wrapEvidence(). Direct writes bypass gap detection and quality derivation.
#
# Hook contract: receives JSON on stdin with tool_name, tool_input, tool_output.
# Exit 0 = allow (with optional warning message).

set -euo pipefail

INPUT=$(cat)

# Extract the file path from the tool input
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""' 2>/dev/null)

# Check if writing to evidence directory
if [[ "$FILE_PATH" == *".crawlio/evidence/"* || "$FILE_PATH" == *"evidence/runs/"* ]]; then
# Check if it's a known safe caller (wrapEvidence writes via writeEvidence)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""' 2>/dev/null)

# Bash tool running writeEvidence/wrapEvidence is OK
if [[ "$TOOL_NAME" == "Bash" ]]; then
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null)
if [[ "$COMMAND" == *"writeEvidence"* || "$COMMAND" == *"wrapEvidence"* ]]; then
exit 0
fi
fi

# Direct Write/Edit to evidence directory — warn
echo "WARNING: Direct write to evidence directory detected." >&2
echo " File: $FILE_PATH" >&2
echo " Use wrapEvidence() + writeEvidence() instead for proper gap detection and quality derivation." >&2
echo " Direct writes bypass: detectNullGaps(), deriveQuality(), metadata stamps." >&2
fi

exit 0
17 changes: 17 additions & 0 deletions hooks/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"hooks": [
{
"event": "PostToolUse",
"matcher": "Write|Edit",
"type": "command",
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/evidence-gate.sh\"",
"timeout": 5
},
{
"event": "Stop",
"type": "command",
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/session-handoff.sh\"",
"timeout": 10
}
]
}
50 changes: 50 additions & 0 deletions hooks/session-handoff.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# session-handoff.sh — Stop hook
# Writes a handoff summary when a Crawlio session ends.
# Captures git state, recent changes, and session context.
#
# Hook contract: receives JSON on stdin. Exit 0 = allow stop.

set -euo pipefail

# Only write handoff if we're in a project with .crawlio/ or .ralph/
AGENT_DIR=""
if [[ -d ".crawlio/agent" ]]; then
AGENT_DIR=".crawlio/agent"
elif [[ -d ".ralph/agent" ]]; then
AGENT_DIR=".ralph/agent"
else
exit 0
fi

HANDOFF_FILE="${AGENT_DIR}/handoff.md"
SUMMARY_FILE="${AGENT_DIR}/summary.md"

# Write handoff
{
echo "# Session Handoff"
echo ""
echo "_Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)_"
echo ""
echo "## Git Context"
echo ""
echo "- **Branch:** $(git branch --show-current 2>/dev/null || echo 'unknown')"
echo "- **HEAD:** $(git log --oneline -1 2>/dev/null || echo 'unknown')"
echo ""
echo "## Recent Changes"
echo ""
echo '```'
git diff --stat HEAD~1 2>/dev/null || echo "(no recent changes)"
echo '```'
} > "$HANDOFF_FILE" 2>/dev/null

# Write summary
{
echo "# Session Summary"
echo ""
echo "- **Ended:** $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "- **Branch:** $(git branch --show-current 2>/dev/null || echo 'unknown')"
echo "- **Commits this session:** $(git log --oneline --since='1 hour ago' 2>/dev/null | wc -l | tr -d ' ')"
} > "$SUMMARY_FILE" 2>/dev/null

exit 0
Loading