by KnockOutEZ
The go-to web for your AI coding agent — local-first search, fetch, crawl & research over MCP. No API keys, no cloud, $0/query. Public beta.
# Add to your Claude Code skills
git clone https://github.com/KnockOutEZ/wigoloLast scanned: 7/15/2026
{
"issues": [
{
"type": "npm-audit",
"message": "esbuild: esbuild allows arbitrary file read when running the development server on Windows",
"severity": "low"
},
{
"type": "npm-audit",
"message": "fastembed: Vulnerability found",
"severity": "high"
},
{
"type": "npm-audit",
"message": "protobufjs: protobufjs : Schema-derived names can shadow runtime-significant properties",
"severity": "high"
},
{
"type": "npm-audit",
"message": "tar: node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Traversal",
"severity": "high"
},
{
"type": "npm-audit",
"message": "vite: launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows",
"severity": "high"
},
{
"type": "npm-audit",
"message": "ws: ws: Memory exhaustion DoS from tiny fragments and data chunks",
"severity": "high"
}
],
"status": "WARNING",
"scannedAt": "2026-07-15T06:13:25.541Z",
"npmAuditRan": true,
"pipAuditRan": true,
"promptInjectionRan": true
}wigolo is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by KnockOutEZ. The go-to web for your AI coding agent — local-first search, fetch, crawl & research over MCP. No API keys, no cloud, $0/query. Public beta. It has 4,501 GitHub stars.
wigolo returned warnings in SkillsLLM's automated security scan. It has no critical vulnerabilities, but review the flagged issues in the Security Report section before adding it to your workflow.
Clone the repository with "git clone https://github.com/KnockOutEZ/wigolo" and add it to your Claude Code skills directory (see the Installation section above). wigolo ships a SKILL.md manifest, so compatible agents can discover and load it automatically.
wigolo is primarily written in TypeScript. It is open-source under KnockOutEZ on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh wigolo against similar tools.
No comments yet. Be the first to share your thoughts!
Requires a passing catalog security scan. Resolve the flagged issues and resubmit to enable featuring.
name: wigolo description: Local-first web intelligence MCP server for AI coding agents. Ten tools for search, fetch, crawl, cache, extract, find similar, research, agent-driven data gathering, page diffing, and change watching. No API keys. Results cached in a local knowledge store. author: KnockOutEZ license: AGPL-3.0-only repository: https://github.com/KnockOutEZ/wigolo transport: stdio install: npx wigolo runtime: node min_runtime_version: "20" tools:
Local-first web intelligence MCP server for AI coding agents. Ships ten tools over stdio. All network results land in a local knowledge cache.
Wigolo has no internal LLM. It returns structured evidence so the calling model (you) writes the final answer. Fold structure into your reply rather than collapsing it away:
search with format: "highlights" — ML-scored passages + citations. Quote and cite [N].research — when MCP sampling is unavailable (common), the output carries a brief with topics, highlights, key_findings. Use it as the scaffold for the report you write.find_similar — may return a cold_start string. Pass it to the user; it explains why results came from the web and how to warm the cache.extract with mode: "structured" — one call for tables + <dl> definitions + JSON-LD + chart hints + key-value pairs.fetch metadata — surfaces og_type, canonical_url, and og_image; use canonical_url to dedupe tracked/canonical URLs.Claude Code:
claude mcp add wigolo -- npx wigolo
Cursor / VS Code / any MCP client:
{
"mcpServers": {
"wigolo": {
"command": "npx",
"args": ["wigolo"]
}
}
}
Warmup (recommended, one-time):
npx wigolo warmup # installs browser engine + bootstraps search engine
npx wigolo warmup --all # also installs Firefox, WebKit, ML reranker, and embeddings
npx wigolo warmup --force # wipe search engine state and rebuild
Warmup flags: --force, --all, --reranker, --firefox, --webkit, --embeddings, --no-searxng, --verify.
Fetch a single URL and return clean markdown. Use when you already have a specific URL.
Parameters:
url (string, required)render_js: "auto" (default) | "always" | "never"use_auth: boolean (default false) — reuses the user's browser sessionmax_chars: numbersection: string — return only the content under a headingsection_index: number (default 0) — which heading match when multiple hitscreenshot: boolean (default false)headers: objectforce_refresh: boolean — bypass cacheactions: array of {type, selector, text, ms, timeout, direction, amount} — click, type, wait, wait_for, scroll, screenshot. Forces browser rendering when present.Example:
{ "url": "https://react.dev/reference/react/useState", "section": "Parameters" }
Tip: section is much cheaper than reading the full page. Repeat fetches of the same URL are free from cache unless force_refresh: true.
Search the web and return extracted markdown per result. Use when you don't have a URL yet.
Parameters:
query (string OR string[], required) — array runs variants in parallel and dedupesmax_results: number (default 5, cap 20)include_content: boolean (default true)content_max_chars: number (default 30000)max_total_chars: number (default 50000)time_range: "day" | "week" | "month" | "year"include_domains / exclude_domains: string[]from_date / to_date: ISO YYYY-MM-DDcategory: "general" | "news" | "code" | "docs" | "papers" | "images"language: stringsearch_engines: string[] — override engine selectionformat: "full" (default) | "context" (token-budgeted string) | "highlights" (ML-scored passages + citations) | "answer" (synthesized via MCP sampling; falls back to highlights when unsupported) | "stream_answer" (answer + phase progress notifications)max_highlights: number (default 10) — cap when format: "highlights"force_refresh: booleanExample:
{ "query": ["react server components patterns", "RSC data fetching", "react server components streaming"], "category": "docs", "include_domains": ["react.dev"], "max_results": 5 }
Tip: keyword queries beat natural-language questions. A 3–5 item query array usually finds more unique sources than one longer query.
Crawl a site starting from a seed URL.
Parameters:
url (string, required)strategy: "bfs" (default) | "dfs" | "sitemap" | "map" (URL-only discovery, no content)max_depth: number (default 2)max_pages: number (default 20)include_patterns / exclude_patterns: regex string[]use_auth: boolean (default false)extract_links: boolean (default false) — returns inter-page link graphmax_total_chars: number (default 100000)Example:
{ "url": "https://docs.python.org/3/library/", "strategy": "sitemap", "max_pages": 30, "include_patterns": ["^https://docs\\.python\\.org/3/library/asyncio"] }
Tip: strategy: "sitemap" is faster and more complete than BFS on doc sites. strategy: "map" returns URLs only — cheap way to scope before targeted fetches.
Search previously fetched content without hitting the network.
Parameters:
query: full-text search — supports AND, OR, NOT, "exact phrase"url_pattern: glob (e.g. "*react.dev*")since: ISO datestats: boolean — returns total URLs, size, date rangeclear: boolean — deletes matching entries (requires one of query, url_pattern, since)check_changes: boolean — re-fetches matching URLs, reports changed/unchanged with diff summariesExample:
{ "query": "useState OR useReducer", "url_pattern": "*react.dev*" }
Tip: cache hits are instant and cross-session. Run this before search or fetch when you suspect the content is already on disk.
Structured extraction from URL or raw HTML.
Parameters:
url OR html (one required; url wins if both provided)mode: "metadata" (default) | "selector" | "tables" | "schema" | "structured" (tables + <dl> definitions + JSON-LD + chart hints + microdata/data-attr/grid key-value pairs in one call)css_selector: string — required for mode: "selector"multiple: boolean (default false) — return all matches, selector mode onlyschema: JSON Schema object with properties — required for mode: "schema"Example:
{ "url": "https://example.com/product", "mode": "schema", "schema": { "type": "object", "properties": { "price": { "type": "string" }, "name": { "type": "string" }, "sku": { "type": "string" } } } }
Tip: mode: "schema" does heuristic matching over CSS classes, ARIA labels, microdata, and JSON-LD — no LLM call required. mode: "structured" returns every structured pattern on the page (tables, definitions, jsonld, chart_hints, key_value_pairs) in one response — prefer it over chaining multiple extract calls.
Find pages related to a URL or a free-text concept.
Parameters:
url OR concept (one required)max_results: number (default 10, cap 50)include_domains / exclude_domains: string[]include_cache: boolean (default true)include_web: boolean (default true)Example:
{ "url": "https://react.dev/reference/react/useState", "max_results": 8, "include_domains": ["react.dev", "developer.mozilla.org"] }
Tip: uses hybrid 3-way RRF fusion — keyword search + semantic embeddings + live web search. Each result carries match_signals with embedding_rank, fts5_rank, and fused_score. If the cache is empty or embeddings aren't set up, the response includes a cold_start string — pass it to the user to explain why results came from the web.
Multi-step research pipeline with decomposition, parallel search, and cited synthesis.
Parameters:
question (string, required)depth: "quick" (~15s, 2 sub-queries, 5–8 sources) | "standard" (~40s, default) | "comprehensive" (~80s, 7 sub-queries, 20–25 sources)max_sources: number (cap 50) — overrides depth defaultinclude_domains / exclude_domains: string[]schema: JSON Schema — if present, report is structured to fill these fieldsstream: boolean — emit progress notifications per phaseExample:
{ "question": "How do modern JS bundlers tree-shake ESM vs CJS?", "depth": "standard", "include_domains": ["webpack.js.org", "rollupjs.org", "esbuild.github.io", "vitejs.dev"] }
Tip: research checks cache internally — no need to pre-probe. With MCP sampling, the tool synthesizes the report directly. Without sampling (the common case), the output ships a brief with topics, highlights, and key_findings, plus the raw sources — the host LLM writes the final report from the brief.
Natural-language data gathering. Plans queries and URLs from a prompt, runs them in parallel within budget, optionally applies a schema.
Parameters:
prompt (string, required)urls: string[] — seed URLs to includeschema: JSON Schema — extract structured fields per page and mergemax_pages: number (default 10, cap 100)max_time_ms: number (default 60000, cap 600000)stream: booleanExample:
{ "prompt": "Compare pricing tiers for Supabase, Firebase, and Clerk", "schema": { "type": "object", "properties": { "provider": { "type": "string" }, "free_tier": { "type": "string" }, "paid_start": { "type": "string" } } }, "max_pages": 12 }
Tip: output includes a steps array showing every action (plan, search, fetch, extract, synthesize) with timings. Use this to debug why an agent run produced a weak result.
Compare two versions of a page. Point it at a live URL and its cached copy, two URLs, or two markdown blobs.
Parameters:
old (object, required): one of { url, markdown, content_hash }new (object, required): one of { url, markdown }output: "unified" (default), "hunks", or "summary"granularity: "line" (default), "word", or "section"Example:
{ "old": { "url": "https://docs.example.com/api" }, "new": { "url": "https://docs.example.com/api" }, "output": "hunks", "granularity": "section" }
Tip: same URL on both sides diffs the cached copy against a fresh fetch. Use output: "summary" for counts only.
Monitor a page for changes over time. Lazy execution — checks run when you call check or when an overdue job is picked up during another tool run.
Parameters:
action (string, required): "create", "list", "check", "pause", "resume", "delete"url or urls: single-URL or batch create (mutually exclusive)interval_seconds: required for create (min 60)selector: create-only CSS selector to scope the diffnotification: "inline" (default) or an SSRF-guarded webhook URLjob_id: required for check/pause/resume/deleteExample:
{ "action": "create", "url": "https://nodejs.org/en/blog", "interval_seconds": 21600 }
Tip: webhook destinations are SSRF-guarded — a job cannot be pointed at internal or loopback addresses.
Quick routing:
search — you need information but don't have a URL.fetch — you already have the URL.crawl — you need multiple pages from one site.cache — you want to check whether something is already on disk.extract — you need specific fields, tables, or metadata, not the whole page.find_similar — you have a good page/concept and want related content.research — a question needs decomposition and multi-source synthesis.agent — a natural-language task needs multi-step data gathering.diff — you need to see what changed between two versions of a page.watch — you want to monitor a page for changes over time.Cache-first lookup. Before any fetch or search, probe the cache.
cache({ "query": "oauth2 pkce", "url_pattern": "*auth0.com*" })
// empty? fall through to search
search({ "query": "oauth2 pkce flow", "include_domains": ["auth0.com"] })
Fresh content (news, dashboards, changelogs). Bypass cache explicitly.
search({ "query": "node.js 22 release notes", "force_refresh": true, "time_range": "week" })
fetch({ "url": "https://nodejs.org/en/blog", "force_refresh": true })
Scoped documentation research. Crawl the relevant slice, then query cache.
crawl({ "url": "https://docs.astro.build", "strategy": "sitemap", "max_pages": 40 })
cache({ "query": "server islands hydration", "url_pattern": "*docs.astro.build*" })
Broad exploration. Pass a query array; dedup is automatic.
search({ "query": ["rust async runtimes comparison", "tokio vs async-std vs smol", "rust executor benchmarks"], "max_results": 8 })
More like this. Start with a known-good URL, widen via find_similar.
find_similar({ "url": "https://react.dev/reference/react/useMemo", "max_results": 6, "include_domains": ["react.dev"] })
Complex synthesis. One research call replaces 5+ manual search/fetch cycles.
research({ "question": "Tradeoffs of vector DBs for RAG at 100M+ embeddings", "depth": "comprehensive" })
Structured data from multiple sources. Use agent with a schema.
agent({ "prompt": "Find latency and pricing for top 5 edge compute providers", "schema": { "type": "object", "properties": { "provider": {"type":"string"}, "cold_start_ms": {"type":"string"}, "price_per_million": {"type":"string"} } } })
Table extraction. Skip markdown entirely.
extract({ "url": "https://en.wikipedia.org/wiki/List_of_programming_languages", "mode": "tables" })
One-shot structured brief. Tables + definition lists + JSON-LD + chart hints + key-value pairs in one call.
extract({ "url": "https://example.com/product-page", "mode": "structured" })
Direct quotes with citations. ML-scored passages are ideal for host-LLM synthesis.
search({ "query": "react server components data fetching", "format": "highlights", "max_highlights": 6, "include_domains": ["react.dev", "nextjs.org"] })
| Situation | Tool + parameters |
|---|---|
| Focused lookup, known site | search + max_results: 3 + include_domains |
| Broad topic survey | search + query: [...3-5 variants] + max_results: 8 |
| Fresh content required | any tool + force_refresh: true |
| Doc site indexing | crawl + strategy: "sitemap" |
| Site URL inventory only | crawl + strategy: "map" |
| Single heading from long page | fetch + section: "..." |
| Behind login | fetch / crawl + use_auth: true |
| Direct answer (sampling client) | search + format: "answer" |
| ML-scored passages + citations | search + format: "highlights" |
| LLM-ready context blob | search + format: "context" |
| Complex question, multi-source | research + depth: "standard" |
| Structured multi-page extraction | agent + schema |
| One-page structured data | extract + mode: "structured" (everything) or "schema" / "tables" (targeted) |
| Change tracking | cache + check_changes: true |
Do not skip the cache. Running search or fetch without probing cache wastes time on content already on disk. research and agent check cache internally; manual search/fetch do not.
Do not send natural-language questions to search. Use keywords. "how do I debounce in React hooks" loses to "react useDebounce hook custom".
Do not retry an identical failing query. Reformulate keywords, swap category, or add include_domains. Same query → same empty result.
Do not use agent or research for one-URL lookups. Use fetch. agent is for multi-source gathering; research is for decomposable questions.
Do not crawl max_pages: 100 without filters. Always add include_patterns to stay in-scope. Unfiltered crawls fetch nav, footer, and sitemap garbage.
Do not fetch whole pages when you need one section. fetch + section reads under one heading only.
Do not set force_refresh: true by default. It defeats the cache. Use it for news, status, changelogs — content that actually churns.
Do not pass a JSON Schema to extract without properties. The handler rejects schemas that lack a properties key.
wigolo # default: start MCP server on stdio
wigolo mcp # explicit: start MCP server
wigolo warmup [flags] # install browser engine, bootstrap search engine, optional extras
wigolo serve # start HTTP daemon on WIGOLO_DAEMON_PORT (default 3333)
wigolo health # health probe, exits 0 if ok
wigolo doctor # environment diagnostics
wigolo auth discover # list CDP sessions (needs WIGOLO_CDP_URL)
wigolo auth status # show configured auth paths
wigolo plugin add <git-url> # clone plugin into ~/.wigolo/plugins/
wigolo plugin list # list installed plugins
wigolo plugin remove <name> # remove a plugin
wigolo shell [--json] # interactive REPL against subsystems
Top environment variables. All optional — defaults are safe.
| Variable | Default | Purpose |
|---|---|---|
WIGOLO_DATA_DIR |
~/.wigolo |
Cache DB, search engine state, plugins, embeddings |
SEARXNG_URL |
unset | Point at an existing search engine (skips native bootstrap) |
SEARXNG_MODE |
native |
native runs local Python search engine; docker runs container |
WIGOLO_CHROME_PROFILE_PATH |
unset | Chrome profile for use_auth: true |
WIGOLO_CDP_URL |
unset | Chrome DevTools endpoint (e.g. http://localhost:9222) |
MAX_BROWSERS |
3 |
Browser pool size |
WIGOLO_BROWSER_TYPES |
chromium |
Comma list: chromium,firefox,webkit |
WIGOLO_RERANKER |
none |
flashrank for ML reranking |
WIGOLO_EMBEDDING_MODEL |
BAAI/bge-small-en-v1.5 |
Used by find_similar |
CACHE_TTL_CONTENT |
604800 (7d) |
Seconds before cached pages expire |
LOG_LEVEL |
info |
debug | info | warn | error |
Full list: see src/config.ts.
Local-first web intelligence for AI agents — no keys, no cloud, no metered bill.
works with Claude Code · Cursor · Codex · Gemini CLI · OpenCode · VS Code · Windsurf · Zed · Antigravity and beyond LangChain · CrewAI · LlamaIndex · Vercel AI SDK · n8n & self-hosted agents · any MCP client · plain REST
Quickstart · Tools · Why wigolo · Benchmark · Docs · Examples · Feedback · FAQ
New features and updates ship steadily. Follow @yourtowhid on X for all of it and new ways to use wigolo, and reach out there for collaborations or feedback · also on LinkedIn
wigolo gives an AI agent one surface for everything web-related: search, fetch, crawl, extract, cache, find-similar, research, and autonomous gather loops. It runs wherever your agent runs — as an MCP server next to your coding agent, as a REST/MCP endpoint on the box where your self-hosted agents live, or embedded through an SDK inside your own app. The core tools need no API keys, nothing it touches leaves ~/.wigolo/, and no bill grows with how much your agent thinks.
npx wigolo init # set up the local engine — any system
npx wigolo init --agents=claude-code,cursor # …or set up + wire your day-to-day agents in one command
Requires Node ≥ 20 and ~1.5 GB of free disk on macOS, Linux, or Windows. Bare init sets up the local engine: it downloads the browser engine and on-device models, runs a health check, and reports each component. Adding --agents wires the named agents in the same run, so a coding agent you use daily is ready in one command.
--agents takes any of claude-code · cursor · codex · gemini-cli · opencode · vscode · windsurf · zed · antigravity (comma-separated); wigolo writes the MCP config and, where supported, instructions for each.npx -y wigolo in its own MCP config. The installation guide has the exact config block for every client, plus Docker, Homebrew, and single-file-binary channels.--interactive is a plain-text flow; --wizard is the full terminal TUI.--no-warmup waits until first use. A failed component download never fails setup; init reports what's not ready with the exact fix and still completes.init is unattended by default, so it's safe in scripts and CI, and any setup problem surfaces right here in the per-component report, before your agent's first call. Search, fetch, crawl, extract, cache, and find-similar work with no API key. Check it's healthy anytime:
npx wigolo doctor
To remove everything cleanly, run npx wigolo config --uninstall --yes. You can also paste the installation guide into any AI assistant and let it do the setup; it's written to be self-contained.
research & agentSearch, fetch, crawl, extract, cache, and find-similar are fully keyless. research, agent, and search format=answer use an LLM to write the synthesized, cited answer. Without one they hand back a raw brief and evidence for your agent to assemble. A free Gemini key turns that into a finished answer:
export WIGOLO_LLM_PROVIDER=gemini
export GEMINI_API_KEY=<free-key> # grab one at aistudio.google.com/apikey — the free tier is plenty
Any provider works (anthropic · openai · groq), or stay fully local and keyless with WIGOLO_LLM_PROVIDER=ollama (or any OpenAI-compatible URL). Set it in your shell or your agent's MCP env block. Providers, models, and the keyless local-model ladder are in the configuration guide.
Every search result is evidence the agent can act on. It carries a verbatim excerpt pinned to its exact position in the source, a citation ID the agent can quote, and a score it can inspect (abridged real shape):
{
"results": [{
"title": "Logical replication - PostgreSQL docs",
"url": "https://www.postgresql.org/docs/current/logical-replication.html",
"excerpt": "Logical replication is a method of replicating data objects…",
"citation_id": "src-1",
"source_span": { "start": 1042, "end": 1305 }, // byte-exact provenance
"evidence_score": { "final": 0.86, "semantic": 0.91, "lexical": 0.78, "engine_consensus": 3 }
}],
"citations": [{ "id": "src-1", "url": "…" }],
"freshness_signal": { "published": "2026-05-12", "confidence": "high" }
}
Weak results get flagged as junk by wigolo's own scorer. Failed engines are reported and stale cache is labeled, so the agent always knows what it's standing on. Full response contracts per tool are in the tools reference.
| Tool | What it does |
|---|---|
🔎 search |
Multi-engine web search (18 direct adapters) with rank fusion, ML reranking, and an explainable per-result score. Pass a query array for parallel breadth. Scope by domain and time range, match an exact phrase, or return image results. |
📄 fetch |
Load one URL through a tiered router that auto-escalates from plain HTTP to a headless browser engine on anti-bot challenges or SPA shells. Clean markdown + metadata + links. Handles PDFs, a single-heading section, authenticated sessions, and page actions (click / type / scroll / screenshot). |
🕸️ crawl |
Multi-page crawl — BFS, DFS, sitemap, or map-only. Per-domain rate limits, robots.txt respect, boilerplate dedup. |
🧩 extract |
Structured data from a page: tables, metadata, JSON-LD, brand identity, named schemas (Article / Recipe / Product / …), or any custom JSON Schema. |
💾 cache |
Query everything already seen — keyword or hybrid semantic. Plus stats, clear, and change detection. |
🧲 find_similar |
Pages similar to a URL or a concept, via 3-way fusion of keyword + semantic + live web. |
🧠 research |
Decompose a question → fan out sub-queries → fetch sources → synthesize a cited report (or a structured brief the host LLM writes from). |
🤖 agent |
Autonomous gather loop: plan → search → fetch → extract → synthesize, with a step log, time budget, and optional output schema. |
🔁 diff + ⏱️ watch |
See exactly what changed on a page since last visit; re-check on demand and deliver changes to a webhook. |
Every tool also runs from the terminal (wigolo search "…" --json), from an interactive shell with NDJSON piping (wigolo shell), over REST, and through the SDKs — CLI reference. Per-tool guides with the full parameter set are in docs/tools.md; runnable examples are in examples/.
wigolo isn't a free stand-in for the paid tools — it's built to match them. It's a focused web layer for your agents: an MCP and REST surface they call directly, with the search and extraction quality the paid services charge for. What separates it:
blocked_by_challenge failure, not a challenge shell returned as content.