LLM Wiki — Complete Guide¶
The definitive guide to AI-Parrot's machine-first knowledge graph: build it, query it, teach it what you know, federate multiple corpora, and wire it into Claude Code, Codex, and Gemini so every coding session starts smarter.
Table of Contents¶
- What Is LLM Wiki
- Quick Start
- Building the Wiki
- Repository Scan (default)
- Obsidian Vault Scan
- Incremental Updates
- Querying
- query — Search the Knowledge Graph
- page — Read a Full Page
- related — Follow Typed Edges
- status — Check Graph Health
- Architectural Decisions (adr)
- Persistent Memory
- remember — Save Durable Knowledge
- note — Annotate an Existing Page
- link — Connect Two Pages
- memories — List Saved Knowledge
- audit — Review the Write Log
- Coding Assistant Integration
- Claude Code
- Codex (OpenAI)
- Gemini (Google)
- MCP Server (Native Tools)
- Git Hooks — Auto-Refresh on Commit
- Namespaces — Multi-Wiki Federation
- Namespace Kinds
- Registering a Namespace
- Querying Across Namespaces
- How Federation Works
- Roblox and Luau Support
- Setup
- Scanning Luau Code
- Acquiring the Roblox API Plane
- Checking Roblox API Status
- Code-to-API References
- Known Limitations (Roblox)
- Obsidian Vaults as Wiki Sources
- Document Ingestion
- Supervised Ingestion (wikitoolkit ingest)
- Inbox ingestion (wikitoolkit inbox)
- Jira Ticket Extraction (wikitoolkit ingest-jira)
- Storage Backends
- SQLite (default)
- ArangoDB
- InMemory / OKF Bundle
- Backend Comparison
- Exporting the Wiki
- Configuration Reference
- Project Config (.parrot/wiki.json)
- Environment Variables
- CLI Reference
- Architecture
What Is LLM Wiki¶
Classic RAG re-synthesizes an answer from raw text on every query and throws the work away. An LLM Wiki (after Andrej Karpathy's framing) flips that: the system compiles sources into durable, cross-linked pages and files its own knowledge back into the repository. Each conversation can leave the knowledge base better than it found it.
AI-Parrot's LLM Wiki is a machine-first knowledge graph built from your codebase, documents, Obsidian vaults, and Jira tickets. It stores:
- Pages — one per source file, directory, document, ticket, or memory. Each has a concept ID, category, summary, body, and token count.
- Typed edges —
contains,references,embeds,tagged,defines,extends,mentions,explains. - Full-text search — BM25-ranked retrieval via FTS5 (SQLite) or ArangoSearch (ArangoDB).
- Vector embeddings — optional per-page embeddings for semantic re-ranking.
The CLI is wikitoolkit (also available as parrot wiki). It runs
deterministically and offline — no LLM, no API key, no network for the
default build path.
Quick Start¶
Install the wiki stack and its PDF, DOCX, EPUB, and MOBI loaders together:
The wiki extra includes ai-parrot-loaders[documents] and the required parser
dependencies. No separate loader installation is needed for these four formats.
OCR, audio/video, and other specialized loader extras remain opt-in.
# 1. Build the knowledge graph from the current repo (offline, no LLM)
wikitoolkit build
# 2. Install the coding-assistant integration (Claude Code)
parrot claude install
# 3. Query it
wikitoolkit query "how does the ingest pipeline work?"
wikitoolkit page file:parrot/knowledge/wiki/cli.py
wikitoolkit related file:parrot/knowledge/wiki/cli.py
# 4. Save something you learned
wikitoolkit remember "The sweep watermark lives in .parrot/jira_sync.json" \
--category decision --link file:parrot/knowledge/wiki/jira_sync.py
From now on, every git commit auto-refreshes the graph via the post-commit
hook, and every Claude Code session consults it before grepping raw files.
Building the Wiki¶
Repository Scan (default)¶
Scans the repository deterministically — no LLM, no embeddings, no network —
and writes the wiki plane under .parrot/wiki/:
- One
file:<path>page per source file: extracted summary (module docstring / first heading), a Python API outline (classes, functions, docstrings viaast), and the content head for lexical search. - One
dir:<path>overview page per directory, listing children. containsedges (directory → file) andreferencesedges between Python files derived from their imports (src-layouts resolve correctly).
File discovery respects .gitignore (via git ls-files), skips binaries,
lockfiles, and oversized files. Re-builds are incremental: sources are tracked
with SHA-1 + mtime, so unchanged files are skipped and deleted files are
pruned.
Language support¶
The scanner produces API outlines for:
| Language | Method |
|---|---|
| Python | ast-based (built-in) |
| JavaScript / TypeScript | tree-sitter |
| Rust | tree-sitter |
| PHP | tree-sitter |
| Perl | tree-sitter |
Other file types get a summary (first heading / docstring) and content body only.
Build options¶
wikitoolkit build [OPTIONS]
--path DIR Repo root (auto-detected)
--name TEXT Wiki name (default: repo directory name)
--backend TEXT sqlite | memory | arangodb (default: sqlite)
--force Re-ingest every file, ignoring staleness
--no-git Do not use git for file discovery
--vault / --no-vault Force Obsidian vault mode (auto-detected via .obsidian/)
--no-export Skip OKF markdown bundle export
--no-graph Skip graph.html / graph.json generation
--graph-kinds TEXT Page categories in graph.html (default: module,document,overview)
-q, --quiet Only the final summary line
Build also produces:
- OKF markdown bundle (index.md + per-page files) — human-browsable
- Interactive graph (graph.html / graph.json) — visual knowledge map
- Build report (wiki_stats.json) — statistics and language breakdown
Obsidian Vault Scan¶
When the target directory contains .obsidian/, the build switches to
vault mode automatically (or force it with --vault):
# Auto-detected (has .obsidian/)
wikitoolkit build --path ~/vaults/my-notes
# Forced
wikitoolkit build --vault --path ~/some/markdown/folder
Vault scan produces:
- One file:<relpath> page per .md note
- [[wikilink]] → references edges
- ![[embed]] → embeds edges
- #tag → tagged edges + tag:<tagname> tag pages
- Folder containment → contains edges
Excluded directories: .obsidian, .trash, .git, .hg, .svn, .parrot.
See Obsidian Vaults as Wiki Sources for more details.
Incremental Updates¶
# Update specific files
wikitoolkit upsert path/to/file.py path/to/other.py
# Update files changed in the last commit (used by the git hook)
wikitoolkit upsert --changed
# Quiet mode (for hooks)
wikitoolkit upsert --changed --quiet
The upsert command:
- Gets changed files via git diff-tree HEAD (handles merge commits)
- Filters through the same relevance checks as full build
- Removes pages for deleted files
- Waits up to 3 seconds for the write lock (skips if a full build is running)
Querying¶
query — Search the Knowledge Graph¶
Returns ranked, token-budgeted page stubs — enough context to decide which pages to read in full, without dumping entire files into your context.
wikitoolkit query QUESTION [OPTIONS]
-n, --top-k INT Max results to rank (default: 12)
--budget INT Token budget for packed context (default: 1200)
--category TEXT Filter by page category
--ns TEXT Namespace: a name, comma-list, "all", or "local"
--body / -b Also fetch the full body of the top-ranked page
--table Render a human-facing Rich table
--json Emit raw JSON results
--store DIR Read a pre-built store directly
--backend TEXT Backend for --store (default: sqlite)
page — Read a Full Page¶
Progressive disclosure: read one page in full (file summary, API outline, content).
wikitoolkit page PAGE_ID [OPTIONS]
--max-tokens INT Truncate the body to roughly this many tokens
--ns TEXT Namespace selector
--json Emit raw JSON
--store DIR Read a pre-built store directly
--backend TEXT Backend for --store
Page IDs may carry a namespace prefix: issues::file:NAV-9372.md,
notes::file:Retro.md. Local IDs stay bare.
related — Follow Typed Edges¶
wikitoolkit related file:parrot/knowledge/wiki/cli.py
wikitoolkit related file:parrot/knowledge/wiki/cli.py --rel contains --direction out
Walks the graph from a page along typed edges.
wikitoolkit related PAGE_ID [OPTIONS]
--rel TEXT Filter by edge relation (e.g. contains, references)
--direction TEXT out | in | both (default: both)
--ns TEXT Namespace selector
--json Emit raw JSON
--store DIR Read a pre-built store directly
--backend TEXT Backend for --store
status — Check Graph Health¶
Reports: wiki name, backend, storage dir, page/edge/token counts, categories, language breakdown, tracked/stale sources, and registered namespaces.
Architectural Decisions (adr)¶
The decision plane extracts Architectural Decision Records (ADRs) from your codebase and answers "why" questions with cited decision excerpts. Candidates are labeled inferred and accepting one does not make it documented history.
# Look up decisions that apply to a symbol
wikitoolkit adr lookup sym:parrot.knowledge.wiki.cli.WikiStore
# Answer a "why" question with cited decisions
wikitoolkit adr why "why does the wiki use SQLite?"
# Review a candidate (accept/reject/revise/link)
wikitoolkit adr review ADR-42-candidate-abc123 --action accept --expected-revision 1 --actor "human:jlara"
For full details on ADR parsing, citation extraction, generation, and review policies, see docs/guides/wiki-adr-decisions.md.
Persistent Memory¶
The wiki is also your durable memory — what you save here survives sessions
and is found by future wikitoolkit query calls. The agent forgets; the graph
does not.
remember — Save Durable Knowledge¶
# Save a decision
wikitoolkit remember "We chose SQLite over Postgres for the wiki store \
because the typical scale is 10^3-10^4 pages" --category decision
# Save a lesson and link it to relevant pages
wikitoolkit remember "The sweep watermark must NOT advance on partial failure" \
--category lesson \
--link file:parrot/knowledge/wiki/jira_sync.py --rel references
# Save a concept with a custom title
wikitoolkit remember "OKF frontmatter is the deterministic metadata contract \
for all wiki documents" --category concept --title "OKF frontmatter contract"
wikitoolkit remember TEXT [OPTIONS]
--title TEXT Short title (default: first 80 chars of TEXT)
--category TEXT note | decision | lesson | concept (default: note)
--link ID Page ID to link the memory to (repeatable)
--rel TEXT Relation for --link edges (default: references)
--ns TEXT Target namespace (writes to ONE plane; "all" rejected)
--source TEXT Citation URI
--by TEXT Identity asserting this memory (auto-resolved)
--extract Run LLM entity/relation extraction (requires WIKI_EXTRACT_LLM)
--json Emit raw JSON
--store DIR Target store
--backend TEXT Backend for --store
How it works:
- Page ID is deterministic:
mem-+ SHA1({title}::{category}), first 12 hex chars. Re-remembering the same title+category updates instead of duplicating. - Identity is auto-resolved: explicit
--by>CLAUDE_AGENT_ID/PARROT_AGENT_IDenv (prefixedagent:) > local user (prefixedhuman:). - When
sync_graphis enabled in.parrot/wiki.json, the memory is also mirrored into the GraphIndex plane as an audited commit.
note — Annotate an Existing Page¶
wikitoolkit note file:parrot/tools/__init__.py \
"The meta_path finder redirects parrot.tools.<x> -> parrot_tools.<x>"
Appends a dated, attributed note to the page body:
Note (2026-08-24, human:jesus): The meta_path finder redirects parrot.tools.\
-> parrot_tools.\<x>
wikitoolkit note PAGE_ID TEXT [OPTIONS]
--by TEXT Identity asserting this note (auto-resolved)
--ns TEXT Target namespace
--json Emit raw JSON
--store DIR Target store
--backend TEXT Backend
link — Connect Two Pages¶
Creates a typed, asserted edge between two existing pages. Both pages must live in the same plane (no cross-namespace edges).
wikitoolkit link SRC DST [OPTIONS]
--rel TEXT Edge relation (default: references)
--by TEXT Identity (auto-resolved)
--ns TEXT Namespace (both pages must be in the same plane)
--json Emit raw JSON
--store DIR Target store
--backend TEXT Backend
memories — List Saved Knowledge¶
Lists memories and agent-authored pages, newest first.
wikitoolkit memories [OPTIONS]
--category TEXT Filter by category (note, decision, lesson, concept)
--limit INT Max rows (default: 50)
--json Emit raw JSON
--store DIR Target store
--backend TEXT Backend
audit — Review the Write Log¶
Shows the WikiBookkeeper operation log and GraphIndex commit history — every write is attributed and timestamped.
wikitoolkit audit [OPTIONS]
--limit INT Max entries per plane (default: 30)
--json Emit raw JSON
--store DIR Target store
--backend TEXT Backend
Coding Assistant Integration¶
Claude Code¶
The full-featured integration. Install with:
This performs 7 idempotent steps:
| Step | Artifact | Purpose |
|---|---|---|
| 1 | .parrot/wiki.json |
Project config (created if missing) |
| 2 | CLAUDE.md managed section |
Instructs Claude to prefer wikitoolkit query over raw file scans |
| 3 | PreToolUse hook in .claude/settings.json |
Nudges Claude toward the wiki before Grep/Glob/Read/Bash |
| 4 | Permission rules in .claude/settings.local.json |
Auto-allows Bash(wikitoolkit:*) and Bash(parrot wiki:*) |
| 5 | .mcp.json entry |
Registers the wikitoolkit MCP stdio server |
| 6 | /parrotwiki slash command |
.claude/commands/parrotwiki.md |
| 7 | Git post-commit hook |
Runs wikitoolkit upsert --changed --quiet after every commit |
Options:
parrot claude install [OPTIONS]
--path DIR Repo root (auto-detected)
--git-hook / --no-git-hook Install git post-commit hook (default: yes)
--gitignore / --no-gitignore Add .parrot/ to .gitignore (default: yes)
--build / --no-build Build the wiki now if not already built (default: yes)
Other commands:
parrot claude status # Show what's installed
parrot claude uninstall # Remove all managed artifacts (keeps the wiki plane)
How a Claude Code session flows¶
- You ask: "how does the wiki ingest pipeline work?"
- Claude reaches for Grep → the PreToolUse hook fires and injects a nudge.
- Claude runs
wikitoolkit query "wiki ingest pipeline"— gets ranked stubs for a few hundred tokens instead of several full files. wikitoolkit page file:…ingest.pygives the API outline and content;wikitoolkit relatedwalks imports.- On
git commit, the post-commit hook upserts changed files so the graph is already fresh for the next question.
The /parrotwiki slash command¶
Available actions:
/parrotwiki query <question> # Search the knowledge graph
/parrotwiki page <id> # Read a full page
/parrotwiki related <id> # Follow edges
/parrotwiki status # Graph health
/parrotwiki build # Rebuild
/parrotwiki remember <fact> # Save knowledge
/parrotwiki note <id> <text> # Annotate a page
/parrotwiki link <src> <dst> # Connect two pages
/parrotwiki memories # List saved knowledge
/parrotwiki audit # Review write log
/parrotwiki --wiki [dir] # Export human-readable markdown wiki
PreToolUse hook details¶
The hook (wikitoolkit claude-hook) reads the tool payload from stdin and
emits a non-blocking additionalContext nudge. It:
- Only fires when the repo has a built wiki
- Throttles: at most one nudge per cooldown window (default 60 seconds,
configurable via
claude.nudge_cooldown_secondsin.parrot/wiki.json) - Never blocks the permission flow
- Always exits 0 — a broken hook can never break a session
Codex (OpenAI)¶
Writes:
- A managed instruction block in AGENTS.md
- A skill file at .codex/skills/parrot-wiki/SKILL.md
- A PreToolUse hook in .codex/hooks.json matching Bash|Grep|Glob|Read
The hook emits an advisory systemMessage nudge toward wikitoolkit query.
Gemini (Google)¶
Writes:
- A managed instruction block in GEMINI.md
- A skill file at .gemini/skills/parrot-wiki/SKILL.md
- An AfterTool hook in .gemini/settings.json matching
run_shell_command|read_file|read_many_files|grep_search|search_file_content|glob|list_directory
MCP Server (Native Tools)¶
The wikitoolkit MCP server exposes six native tools that appear alongside
Grep, Read, and other built-in tools — no shell overhead, no competing
for tool-selection:
| Tool | Description |
|---|---|
wiki_query |
Search the knowledge graph. Returns ranked page stubs. |
wiki_page |
Read a full wiki page by ID. |
wiki_related |
Follow typed edges from a page. |
wiki_remember |
Save durable knowledge (decisions, gotchas, cross-file relationships). |
wiki_note |
Append a dated note to an existing page. |
wiki_status |
Check graph health: page count, staleness, last build time. |
When an Obsidian vault is configured, an additional vault_ingest tool is
available for rebuilding the vault plane.
Configuration in .mcp.json:
{
"mcpServers": {
"wikitoolkit": {
"command": "${CLAUDE_PROJECT_DIR}/.venv/bin/wikitoolkit",
"args": ["mcp"],
"env": {}
}
}
}
The MCP server resolves registered namespaces at startup, so all federated corpora are available through the native tools with no extra configuration.
Git Hooks — Auto-Refresh on Commit¶
The parrot claude install command (and wikitoolkit codex install) installs
a git post-commit hook that keeps the wiki fresh:
# What the hook runs after every commit:
wikitoolkit upsert --changed --quiet >/dev/null 2>&1 || true
The hook:
- Uses an absolute binary path so it works in git worktrees
- Is silent (stdout/stderr redirected to /dev/null)
- Never fails the commit (|| true)
- Chains politely into existing hooks (checks shebang compatibility)
- Skips gracefully if a full build holds the write lock
What upsert --changed does:
- Gets the file list from git diff-tree HEAD (handles merge commits via
-m --first-parent)
- Re-ingests modified/added files through the same pipeline as build
- Removes pages for deleted files
- Waits up to 3 seconds for the write lock, then skips if busy
Manual hook installation¶
If you did not use parrot claude install, add this to
.git/hooks/post-commit:
#!/bin/sh
# Keep the LLM-wiki knowledge graph in sync with the last commit.
/path/to/.venv/bin/wikitoolkit upsert --changed --quiet >/dev/null 2>&1 || true
Make it executable: chmod +x .git/hooks/post-commit
Namespaces — Multi-Wiki Federation¶
Namespaces let you federate multiple wiki planes behind a single query surface. Your codebase wiki, Obsidian notes, Jira tickets, and external documentation can all be searched together.
Namespace Kinds¶
| Kind | CLI flag | What it points at | Use case |
|---|---|---|---|
path |
--project <dir> |
Root of another wiki project (loads its .parrot/wiki.json) |
Another repo's codebase wiki |
store |
--store <dir> |
Pre-built store directory (wiki.db inside) |
Off-repo corpus (Jira issues, generated docs) |
database |
--database <name> |
ArangoDB (default) or a satellite-registered backend's database holding the plane | Server-hosted shared wiki |
vault |
--vault <dir> |
Obsidian vault root (requires .obsidian/) |
Personal/team notes |
Registering a Namespace¶
# Register an Obsidian vault
wikitoolkit ns add notes --vault ~/vaults/my-notes \
--description "Personal notes" --global
# Register a pre-built store (e.g. Jira issues)
wikitoolkit ns add issues --store ~/.parrot/wikis/issues/.parrot/wiki \
--description "Jira ticket corpus" --global
# Register another project's codebase wiki
wikitoolkit ns add asyncdb --project ~/proyectos/asyncdb \
--description "AsyncDB codebase"
# Register an ArangoDB-hosted wiki
wikitoolkit ns add legislation --database wiki_legislation \
--credentials-env LEGAL_ARANGO \
--description "Legislation corpus" --weight 0.8
# Register a --database entry on a satellite-registered backend instead of
# arangodb (FEAT-449 M7 — e.g. parrot_tools.legal's "ontology_legal")
wikitoolkit ns add legal --database legal_db --backend ontology_legal \
--description "Legal ontology tenant, read-only"
# List registered namespaces
wikitoolkit ns list
# Remove a namespace
wikitoolkit ns remove notes --global
Full ns add options:
wikitoolkit ns add NAME [OPTIONS]
--project DIR Another wiki project root (kind: path)
--store DIR Pre-built store directory (kind: store)
--backend TEXT For --store: sqlite | memory (default: sqlite).
For --database: arangodb (default) or a
satellite-registered backend name (e.g.
ontology_legal, FEAT-449 M7); not validated
against the registry here — an unknown name
surfaces as a ValueError when the namespace is
actually opened.
--database TEXT ArangoDB (or registered extra backend) database name (kind: database)
--credentials-env TEXT Env var prefix for ArangoDB credentials (default: ARANGODB)
--vault DIR Obsidian vault root (kind: vault; requires .obsidian/)
--description TEXT What this namespace holds
--weight FLOAT Score multiplier when merging results (0.0-1.0, default: 1.0)
--global Write to ~/.parrot/wikis.json instead of the repo's wiki.json
Exactly one of --project / --store / --database / --vault is required.
Registry files¶
- Repo-local:
.parrot/wiki.json→namespacesfield - Per-user global:
~/.parrot/wikis.json(atPARROT_HOME/wikis.json)
Repo declarations win over global ones on a name clash.
Querying Across Namespaces¶
# Default: search ALL registered namespaces
wikitoolkit query "forms tenant problem"
# Search only one namespace
wikitoolkit query --ns issues "forms tenant problem"
# Search a subset
wikitoolkit query --ns "issues,notes" "forms tenant problem"
# Search only the local (codebase) wiki
wikitoolkit query --ns local "forms tenant problem"
# Foreign page IDs come back prefixed
wikitoolkit page issues::file:NAV-9372.md
wikitoolkit related notes::file:Retro.md
Foreign page IDs are always qualified (<namespace>::<id>); local IDs stay
bare. Pass a qualified ID verbatim to page / related.
How Federation Works¶
The FederatedWikiStore:
1. Reads fan out concurrently to local + all namespace stores
2. Results are normalized per namespace (min-max [0,1]), weighted, and
merged
3. Writes go to the local plane only
4. Foreign planes are always opened read-only
5. A broken namespace is a note, not a failure — the query proceeds without it
Namespace name rules: ^[A-Za-z0-9][A-Za-z0-9_.:-]*$, no ::, not all or
local (reserved).
Roblox and Luau Support¶
FEAT-532 adds first-class Luau/Roblox coverage on top of everything above:
.lua/.luau files scan and index like any other language, and an
independently-generated, federated Roblox API plane (one page per
official engine class/enum) links to your code via references edges —
without ever mixing platform docs into your project's own local search corpus.
Two entirely separate planes, two separate lifecycles:
- Your code (
.lua/.luaufiles) — scanned bywikitoolkit buildlike every other language, offline, no network, every time. - The Roblox API (one page per class/enum from the official dump +
creator-docs) — acquired only on an explicit
--refresh, published as an immutable, versioned generation, and queried as a federated namespace (default nameroblox).
Setup¶
The Luau grammar is optional, matching every other tree-sitter language in
this guide — install it via the wiki-languages extra:
uv pip install "ai-parrot[wiki-languages]"
# or, from the workspace root:
uv sync --package ai-parrot --extra wiki-languages
Without it, .lua/.luau files still get a bounded, regex-based heuristic
outline (functions, colon methods, type annotations, require(...)
specifiers) — never a hard failure, and never a sym: structural page (Luau
has no structural symbol plane in this release; see
Known Limitations).
Scanning Luau Code¶
.lua and .luau are discovered by default — no extra CLI flag needed:
require() calls resolve through, in order: sourcemap.json (a Rojo
sourcemap, preferred), then default.project.json (a static Rojo project
file, only when the sourcemap is absent or invalid — never both blended),
then a relative-string fallback (require("./Sibling")), which works
regardless of mapping mode. A resolved DataModel instance path (e.g.
game.ServerScriptService.Main) and its Roblox className are rendered
into the file's own page body — never a separate/renamed identity, the
page is still addressed as file:src/Main.luau.
Acquiring the Roblox API Plane¶
The API plane is never fetched implicitly — wikitoolkit build never makes
a network request for it. The first acquisition (and every refresh
afterwards) is explicit:
# First use: fetch the current Studio API dump + creator-docs, publish
# a new generation. This is the ONLY command that ever touches the network
# for this plane.
wikitoolkit ingest roblox-api --refresh
# Every subsequent call, with no --refresh: a pure offline read of the
# last published generation. Zero network requests.
wikitoolkit ingest roblox-api
A --refresh compares the resolved Studio version, the creator-docs commit,
and the renderer's own schema version against the currently active
generation: unchanged on all three means the existing generation is reused
outright (no re-render, no re-publish); a change in any of them rebuilds and
atomically republishes a brand-new, immutable generation. Older generations
are retained on disk for any reader still using them — there is no automatic
garbage collection.
After a successful --refresh, register the plane as a namespace exactly
like any other (see
Registering a Namespace) — ingest roblox-api
never registers it for you, and never silently replaces an existing
roblox declaration:
~/.parrot/roblox/current is a stable path (an atomically re-pointed
symlink) — it always resolves to whichever generation is currently active,
so this registration never needs updating across future refreshes.
Checking Roblox API Status¶
wikitoolkit status includes the Roblox plane's recorded download
timestamp and Studio/creator-docs versions — a pure local-manifest read,
never a network probe of any kind:
wikitoolkit status --path /path/to/your/roblox-project
# ...
# Roblox API : Studio 0.123.0.456789, creator-docs 1a2b3c4d5e6f,
# downloaded 2026-09-06T00:00:00+00:00 (625 classes, 120 enums)
Before any --refresh has ever run, this line instead reads:
Code-to-API References¶
Once the roblox namespace is registered, three code shapes resolve to a
qualified references edge on your Luau file's page:
- Literal service lookups:
game:GetService("Players") - Explicit API type annotations:
local p: Player,function f(p: Player) - Chained instance access on the known, unshadowed
game/workspaceroots, at every level of the chain:workspace.Terrain,game.Workspace.Terrain
wikitoolkit related file:src/Main.luau --path /path/to/your/roblox-project
# → roblox::class/Players (references)
wikitoolkit page roblox::class/Players --path /path/to/your/roblox-project
A candidate that doesn't resolve to a real class/enum in the active generation is never guessed into a fabricated page — it's silently dropped (logged as a diagnostic), not a build failure. Removing an API use, or deleting the file entirely, removes the corresponding edge on the next build — never a dangling reference.
Known Limitations (Roblox)¶
- No Luau
sym:structural symbol plane —outline()always returns emptysymbols/refsin every mode (ast-grep cannot register the Luau grammar from the current wheel). - No expression type inference — only the three literal shapes above ever produce a reference; a value passed through a variable or a function return is never traced.
- Chained-access recognition (
workspace.Terrain) intentionally accepts a false-positive tradeoff for coverage — a local variable that happens to shadowgame/workspaceanywhere in the same file suppresses reference detection for that root file-wide, not just at the shadowed call site (a deliberate, documented simplification, not true per-block lexical scoping). - The DataModel mapping for a partial
wikitoolkit upsert(as opposed to a fullbuild) is resolved from the currently-scanned files plus every file already known to the source manifest from a previous full build — a project that has never had a fullbuildand is only ever touched via partialupsertwill see an incomplete mapping until its next full build. wikitoolkit ingest roblox-apinever runs a background refresh and has no TTL — an out-of-date generation stays active until the next explicit--refresh.
Standup Briefs and Typed Entities¶
The standup subsystem (wikitoolkit standup) generates deterministic day/week/month
briefs from Jira issues, decisions and entity changes. Key concepts:
Attributes Ingest and Back-fill¶
Entity attributes (type, status, project, date, due, owner) are extracted during
ingest and stored as page frontmatter. The wikitoolkit entity reindex --store <path>
command back-fills attributes into an existing wiki plane from its stored pages,
useful for migrating legacy data or syncing foreign planes.
Personal and Team Filtering¶
--teamincludes all team members' activity; default shows only your identity.- Identity is resolved from
~/.parrot/identity.json(orWIKI_IDENTITYenv var) ashuman:<username>, without requiring email access. - Use
--me <identity>to override the default identity for a single run.
Period Roll-ups and Delta Meaning¶
day— activity since yesterday 00:00 UTCweek— activity since Monday of the current weekmonth— activity since the 1st of the current month
The brief includes a "delta" section showing net changes: new, updated and closed items. Delta is computed per-period and does not accumulate across periods.
Model Fallback and Read-Only MCP Defaults¶
- By default, standup requests an LLM summary (
--no-llmdisables it). - If the model fails, the brief still renders with raw data; no partial summary is stored.
- MCP tool calls default to read-only (
--no-store --no-file) when invoked via MCP. Use explicit--storeor--outto persist output.
Cron Scheduling¶
Run at 07:00 UTC after the 06:17 Jira sweep. Example cron entry (deployment-specific paths marked):
0 7 * * 1-5 cd /path/to/project && /path/to/venv/bin/wikitoolkit standup --period day --language en --out /var/log/standups/$(date +\%Y-\%m-\%d).md >> /var/log/standup.log 2>&1
Consult the wiki standup runbook for identity configuration, failure recovery and back-fill recipes.
Obsidian Vaults as Wiki Sources¶
Obsidian vaults are first-class wiki sources. The vault scanner
(vault_scan.py) understands Obsidian's conventions:
What gets extracted¶
| Obsidian feature | Wiki representation |
|---|---|
.md note |
file:<relpath> page (category "document") |
[[wikilink]] |
references edge (resolved within the vault) |
![[embed]] |
embeds edge |
#tag |
tagged edge + tag:<tagname> tag page |
| Folder structure | contains edges + dir:<path> overview pages |
| YAML frontmatter | Preserved in page body (queryable via FTS) |
| Aliases | Included in the page title/body for search |
Unresolved wikilinks (pointing outside the vault) are dropped from edges but counted in the build stats.
Building from a vault¶
# Auto-detected (has .obsidian/)
wikitoolkit build --path ~/vaults/work-notes
# Manual vault mode
wikitoolkit build --vault --path ~/some/markdown/folder
Registering as a namespace¶
# Register so the vault is searchable from your repo
wikitoolkit ns add notes --vault ~/vaults/work-notes \
--description "Work notes vault" --global
Vault ingestion via MCP¶
When a vault is configured in .parrot/wiki.json (field vault_dir), the
MCP server exposes a vault_ingest tool that rebuilds the vault plane:
Document Ingestion¶
Supervised Ingestion (wikitoolkit ingest)¶
For ingesting document corpora (PDF, DOCX, PPTX, XLSX, HTML, EPUB, MOBI, Markdown, plain text) with editorial control:
# Dry run — see what would be ingested
wikitoolkit ingest ~/documents/specs/ --dry-run
# Interactive — approve each document
wikitoolkit ingest ~/documents/specs/ --interactive
# Automatic — charter-driven thresholds decide
wikitoolkit ingest ~/documents/specs/ --auto --charter .parrot/charter.yaml
# Ingest a single URL
wikitoolkit ingest https://example.com/paper.pdf --interactive
wikitoolkit ingest SOURCE [OPTIONS]
--charter PATH Editorial charter YAML (default: .parrot/charter.yaml)
--dry-run Triage all, emit manifest, ingest nothing
--review PATH Apply human-edited decisions from a manifest.jsonl
--interactive Prompt per-document before applying
--auto Charter thresholds decide; flags audit sample
--extract EXPERIMENTAL: include extracted claims in manifest
--lightweight-model TEXT Stage-1 triage model (default: $WIKI_LIGHTWEIGHT_MODEL)
--model TEXT Stage-2 escalation model (default: $WIKI_MODEL)
--audit-rate FLOAT Fraction of --auto decisions flagged for audit (default: 0.1)
--manifest PATH Manifest output path
--recursive / --no-recursive Walk directories recursively (default: yes)
--fetch-timeout FLOAT URL fetch timeout in seconds (default: 30)
Exactly one mode required: --dry-run, --review, --interactive, or
--auto.
Inbox ingestion (wikitoolkit inbox)¶
Drop documents into the repository's inbox directory (default inbox/), then
run wikitoolkit inbox. For each document, the command:
- acquires and triages it;
- ingests it with the heavy model;
- classifies it against the charter taxonomy with the lightweight model;
- links it to existing pages;
- writes the document page, its tags and the Markdown projection;
- verifies what was written;
- only then archives the original.
wikitoolkit inbox --dry-run --json # preview: triage, classify, plan links (models are still called)
wikitoolkit inbox # process the inbox, oldest first
wikitoolkit inbox --no-archive # persist and verify, but keep the originals in place
The processor never commits. Review git status afterwards. Exit codes:
1: a document failed;2: usage or path-layout error;3: the wiki write lock is busy.
The full reference covers pipeline stages, triage outcomes, the inbox
config block, the taxonomy, the pages and edges written, archive naming and
the JSON report: docs/wiki/inbox.md.
Jira Ticket Extraction (wikitoolkit ingest-jira)¶
Extract your Jira ticket corpus into a federated issues namespace. See the
Jira Ticket Extractor guide for full setup
instructions.
# Full backfill
wikitoolkit ingest-jira
# Incremental daily sweep (what the cron runs)
wikitoolkit ingest-jira --quiet
wikitoolkit ingest-jira [OPTIONS]
--jql TEXT JQL scope (default: $JIRA_WIKI_JQL)
--project TEXT Shorthand for `project = <KEY>`
--since DATE Override the stored watermark (ISO-8601)
--issues-dir PATH Output directory (default: $JIRA_WIKI_ISSUES_DIR)
--build / --no-build Build the plane after emitting (default: build)
--enrich Opt-in LLM summary (default: off)
--force Re-render everything, ignoring watermark
--dry-run Report what would change; write nothing
--json Emit SweepReport as JSON
-q, --quiet Only the final summary line
Storage Backends¶
The wiki supports three storage backends. Choose based on your deployment needs.
SQLite (default)¶
Zero deployment, single-file, recommended for most uses.
| Property | Detail |
|---|---|
| Storage | Single wiki.db file in WAL journal mode |
| FTS engine | FTS5 with BM25 ranking, unicode61 tokenizer |
| Vector search | Brute-force cosine scan (appropriate at wiki scale) |
| Dependency | aiosqlite (included in base install) |
| Multi-writer | WAL mode (single machine) |
| Scale | 10³–10⁴ pages |
The SQLite backend stores everything in .parrot/wiki/wiki.db:
- 6 tables: meta, sources, pages, edges, pages_fts (FTS5), embeddings
- Read-only mode (for federated namespaces) uses a connection ladder:
immutable=1 for quiescent planes → mode=ro when a writer is active
Configuration:
// .parrot/wiki.json
{
"wiki_name": "codebase",
"backend": "sqlite",
"storage_dir": ".parrot/wiki"
}
ArangoDB¶
Server-hosted, multi-language FTS, native graph edges. For teams sharing a wiki or projects needing multi-language search.
| Property | Detail |
|---|---|
| Storage | ArangoDB server (5 collections prefixed wiki_) |
| FTS engine | ArangoSearch with BM25, configurable text analyzers |
| Multi-language FTS | Yes — comma-separated analyzers (e.g. text_en,text_es) |
| Vector search | Brute-force cosine (no native ArangoDB vector index) |
| Dependency | asyncdb[arangodb] (in databases extras) |
| Multi-writer | Server-managed multi-client |
| Scale | Server-scale, shareable across projects |
| Graph features | Native edge collection (graph traversal possible) |
Installation¶
# Install the ArangoDB driver
pip install 'ai-parrot[databases]'
# or specifically:
uv pip install 'asyncdb[arangodb]'
Environment variables¶
The connection credentials are resolved from environment variables with a
configurable prefix (default: ARANGODB):
| Variable | Default | Description |
|---|---|---|
ARANGODB_HOST |
127.0.0.1 |
ArangoDB server host |
ARANGODB_PORT |
8529 |
ArangoDB server port |
ARANGODB_PROTOCOL |
http |
Connection protocol (http or https) |
ARANGODB_USERNAME |
root |
Authentication username |
ARANGODB_PASSWORD |
(empty) | Authentication password |
You can use a different prefix per wiki (useful when connecting to multiple ArangoDB instances):
# Production wiki credentials
export PROD_ARANGO_HOST=arango.prod.internal
export PROD_ARANGO_PORT=8529
export PROD_ARANGO_USERNAME=wiki_svc
export PROD_ARANGO_PASSWORD=secret
Configuration¶
// .parrot/wiki.json
{
"wiki_name": "my-project",
"backend": "arangodb",
"storage_dir": ".parrot/wiki",
"arango_database": "wiki_my_project",
"arango_credentials_env": "ARANGODB",
"arango_text_analyzer": "text_en"
}
| Field | Default | Description |
|---|---|---|
arango_database |
wiki_{wiki_name} |
ArangoDB database name |
arango_credentials_env |
ARANGODB |
Env var prefix for connection credentials |
arango_text_analyzer |
text_en |
ArangoSearch text analyzer(s); comma-separated for multi-language |
Multi-language search¶
ArangoDB's key advantage is native multi-language full-text search. Configure multiple analyzers:
This creates an ArangoSearch view with all three analyzers, so queries in English, Spanish, or Portuguese all match correctly with language-aware stemming and stop-word removal.
Available built-in analyzers: text_en, text_es, text_de, text_fr,
text_pt, text_it, text_zh, text_ja, text_ko, and
many more.
ArangoDB collections¶
The backend creates 5 collections (prefixed wiki_):
| Collection | Type | Purpose |
|---|---|---|
wiki_pages |
Document | Page bodies (keyed by percent-encoded concept_id) |
wiki_edges |
Edge | Typed relations (_from/_to for native graph traversal) |
wiki_embeddings |
Document | Per-page vector arrays |
wiki_sources |
Document | Source tracking (SHA-1 + mtime) |
wiki_meta |
Document | Metadata (schema version, wiki name) |
Plus an ArangoSearch view: {wiki_name}_pages_view for BM25 lexical search.
Registering an ArangoDB namespace¶
# Register a remote ArangoDB wiki as a namespace
wikitoolkit ns add legislation \
--database wiki_legislation \
--credentials-env LEGAL_ARANGO \
--description "Legislation corpus" \
--weight 0.8
# The namespace store opens read-only with a connection probe + timeout
Read-only federation with ArangoDB¶
When a namespace is registered with --database, the federation layer:
1. Probes the database from _system (no provisioning on foreign namespaces)
2. Verifies the wiki_pages collection exists
3. Opens the store read-only — no database or collection creation
4. Applies a configurable timeout (default: 5 seconds) so an unreachable
ArangoDB server doesn't block the query
InMemory / OKF Bundle¶
File-based, human-browsable markdown. For development, testing, and OKF-compatible export.
| Property | Detail |
|---|---|
| Storage | Directory of OKF v0.1 markdown files with YAML frontmatter |
| FTS engine | TF-IDF (in-process, title boosted 3×) |
| Vector search | Brute-force cosine |
| Dependency | pyyaml (included in base install) |
| Human-browsable | Yes (plain markdown files) |
| Scale | 10³–10⁴ pages |
Backend Comparison¶
| Feature | SQLite | ArangoDB | InMemory |
|---|---|---|---|
| Deployment | Zero (single file) | Requires server | Zero (directory) |
| FTS engine | FTS5 / BM25 | ArangoSearch / BM25 | TF-IDF |
| Multi-language FTS | No (unicode61 only) |
Yes (configurable analyzers) | No |
| Vector search | Brute-force cosine | Brute-force cosine | Brute-force cosine |
| Edges | SQL table | Native edge collection | In-memory adjacency |
| Human-browsable | No (binary) | ArangoDB Web UI | Yes (markdown files) |
| Multi-writer | WAL (single machine) | Server-managed | No locking |
| Read-only federation | Yes (immutable/ro) | Yes (probe + verify) | Yes |
| Dependency | aiosqlite (base) |
asyncdb[arangodb] (extras) |
pyyaml (base) |
| Best for | Single dev, CI, most repos | Teams, multi-language, shared corpus | Dev, testing, export |
Note: There is no PostgreSQL wiki backend. Postgres/pgvector is used elsewhere in AI-Parrot for vector stores (
parrot.stores.pgvector), but the wiki retrieval plane uses SQLite or ArangoDB only.
Exporting the Wiki¶
Export the knowledge graph as a human-readable markdown bundle:
# Default: export to docs/wiki/
wikitoolkit export
# Custom output directory
wikitoolkit export -o docs/knowledge-base
Writes one markdown file per page (YAML frontmatter + body) plus a root
index.md. Automatically adds the export directory to exclude_dirs in the
config so subsequent builds don't ingest the exported markdown back.
Use /parrotwiki --wiki from Claude Code for the same operation.
Configuration Reference¶
Project Config (.parrot/wiki.json)¶
Created by wikitoolkit build or parrot claude install. Located at the
repo root: .parrot/wiki.json.
{
"wiki_name": "codebase",
"storage_dir": ".parrot/wiki",
"backend": "sqlite",
"include_suffixes": [],
"exclude_dirs": [],
"body_max_chars": 16000,
"max_file_kb": 512,
"sync_graph": false,
"vault_dir": null,
"arango_database": null,
"arango_credentials_env": "ARANGODB",
"arango_text_analyzer": "text_en",
"claude": {
"nudge_cooldown_seconds": 60,
"nudge_tools": ["Grep", "Glob", "Read", "Bash"]
},
"namespaces": {
"notes": {
"vault": "~/vaults/work-notes",
"description": "Work notes",
"weight": 1.0
},
"issues": {
"store": "~/.parrot/wikis/issues/.parrot/wiki",
"description": "Jira ticket corpus",
"weight": 1.0
},
"shared-docs": {
"database": "wiki_shared_docs",
"credentials_env": "DOCS_ARANGO",
"description": "Shared documentation wiki",
"weight": 0.8
}
}
}
| Field | Default | Description |
|---|---|---|
wiki_name |
repo dir name | Wiki identifier |
storage_dir |
.parrot/wiki |
Where the plane lives |
backend |
sqlite |
sqlite / memory / arangodb |
include_suffixes |
[] |
Only scan files with these suffixes (empty = all) |
exclude_dirs |
[] |
Skip these directories |
body_max_chars |
16000 |
Max chars per page body |
max_file_kb |
512 |
Skip files larger than this |
sync_graph |
false |
Mirror writes to the GraphIndex plane |
vault_dir |
null |
Obsidian vault path (enables vault_ingest MCP tool) |
arango_database |
wiki_{name} |
ArangoDB database name |
arango_credentials_env |
ARANGODB |
Env var prefix for ArangoDB credentials |
arango_text_analyzer |
text_en |
ArangoSearch text analyzer(s) |
claude.nudge_cooldown_seconds |
60 |
Min seconds between PreToolUse nudges |
claude.nudge_tools |
["Grep","Glob","Read","Bash"] |
Tools the hook intercepts |
namespaces |
{} |
Federated namespace declarations |
Environments — per-env overlays, precedence, and sync (FEAT-461)¶
The committed base .parrot/wiki.json is one config, but a repo often
needs a different plane per environment: a local, zero-VPN SQLite plane
when a teammate has no ENV exported, and the shared ArangoDB plane under
ENV=dev/ENV=prod. Per-environment overlay files — optional,
partial configs — layer on top of the base without duplicating it.
Env resolution¶
The active environment is resolved, on every call, in this order:
WIKI_ENV is the escape hatch for when the wiki's plane and navconfig's
credential environment must differ. This repo commits
.parrot/wiki.local.json = {"backend": "sqlite"}, so an unset ENV
gets you a fully offline, no-VPN sqlite plane out of the box — the
payoff this feature exists for.
Overlay files¶
.parrot/wiki.{env}.json is a partial config — every field optional,
shallow-merged over the base at load time (namespaces merges per-key;
every other field the overlay sets replaces the base's value verbatim).
Overlays carry no credential fields (no host/port/username/password)
— those always resolve via navconfig from env/{ENV}/.env, never from a
committed JSON file. An unknown or secret-like key in an overlay is a
hard load error, not a silent pass-through.
// .parrot/wiki.dev.json (generated by `wikitoolkit build` if missing)
{
"backend": "arangodb",
"arango_database": "wiki_ai-parrot",
"arango_credentials_env": "ARANGODB",
"arango_text_analyzer": "text_en"
}
- Missing overlay → read commands (
query/page/related/status) fall back to the base config silently;statusreportsbase (no overlay). wikitoolkit buildgenerates the ACTIVE env's overlay when it does not exist yet:local→{"backend": "sqlite"}; every other env → the base's Arango settings mirrored verbatim (same database name — environments never get a suffixed database; separation comes from the per-ENVserver/credentials, not the name). An existing overlay is never clobbered, and a one-off--backendflag is never frozen into a freshly generated overlay's derivation.
Backend precedence¶
One rule, applied everywhere a backend is chosen (build, _open_store,
the read/write store resolvers):
⚠️ Plane selection is not credential selection¶
An unset ENV selects the local plane (sqlite) — it does NOT change
which credentials navconfig loads. Any shared namespace or sync target
that still reaches ArangoDB in local mode resolves its host/user/password
from env/.env (the dev credentials) exactly as it would with
ENV=dev set — navconfig's own "no ENV ⇒ env/.env" convention is
untouched by this feature; only the wiki's plane choice diverges from
it. In local mode, an unreachable shared namespace degrades gracefully
(skipped with a one-line note, bounded connect timeout, local results
still returned) — the PRIMARY plane never falls back automatically.
Sync — moving authored knowledge between planes¶
wikitoolkit sync push|pull moves memory pages (remember), attributed
notes, and the asserted edges between them — never repo-scanned
(ingest) pages, and never deletes (no tombstones in v1: a memory
deleted locally reappears on the next pull if it still exists remotely
— recover with the git history of .parrot/wiki.local.json's plane, or
delete it on both sides).
# Push local memories/notes to the shared dev plane
wikitoolkit sync push --env dev
# Pull from the shared plane — excludes YOUR OWN records by default
wikitoolkit sync pull --env dev
# Pull everything, including records you authored yourself
wikitoolkit sync pull --env dev --all
# Preview without applying anything
wikitoolkit sync push --env dev --dry-run
- Conflict rule: last-write-wins per record by
updated_at— the side with the newer stamp wins; the loser is still recoverable from the bookkeeper audit log (wikitoolkit audit). - Author filter (
pullonly): records whoseasserted_bymatches your local identity (human:<user>) are excluded by default, so syncing never lets a stale remote copy silently overwrite your own freshly-authored memory.--allswitches to pure last-write-wins. - Note merge: notes are never dropped by a sync. Both sides' notes on a page are unioned (date-ordered, keyed by author+date+text) into whichever side's body wins the conflict — a note added on either plane survives every subsequent push/pull.
- Every applied change is logged to the bookkeeper (
SYNC_PUSH/SYNC_PULL);--dry-runcomputes and prints the report but applies and logs nothing.
Sync — mirroring wiki planes into an Obsidian vault¶
wikitoolkit sync obsidian is the third sync direction: a one-way
projection of wiki planes into an Obsidian vault as markdown notes
(the reverse of vault ingestion via build --vault or a vault-kind
namespace). Which page categories sync and which vault folder
each one maps onto is configuration, under obsidian_sync in
.parrot/wiki.json:
{
"obsidian_sync": {
"vault_dir": "~/vaults/notes", // target vault (falls back to vault_dir)
"root_folder": "LLM Wiki", // subtree holding every synced note
"categories": ["concept", "entity"], // empty = all categories
"folders": {"concept": "Concepts"}, // category -> folder override
"namespaces": ["local", "issues"], // planes to mirror ('all' = local + every ns)
"prune": false // delete notes whose page vanished
}
}
# Mirror the configured planes/categories into the vault
wikitoolkit sync obsidian
# Ad-hoc overrides (flags win over config for this run)
wikitoolkit sync obsidian --vault ~/vaults/notes --ns local,issues \
--category concept --category entity
# Preview, then apply with pruning of vanished pages
wikitoolkit sync obsidian --dry-run -v
wikitoolkit sync obsidian --prune
- Layout:
<root_folder>/[<namespace>/]<category folder>/<page>.md— the local plane writes directly under the root folder; each foreign namespace gets its own subtree. Category folders default to the OKF export pluralization (entity→entities/) unless overridden viafolders. - Frontmatter marker: every synced note carries
wiki_sync: <wiki_name>,wiki_scope: <wiki_name>@<repo-root digest>,wiki_id: <concept_id>andnamespace: <plane>(plusaliases,tags: [wiki/<category>],summary,updated), so notes are searchable in Obsidian and safely identifiable as managed. - Edges become wikilinks: edges between two synced pages render as a
## Relatedsection of[[wikilinks]], so the wiki graph shows up in Obsidian's graph view. - Idempotent: rendering is deterministic — an unchanged page is
reported
unchangedand never rewritten. - Prune is marker-guarded:
--prune(or"prune": true) deletes only notes whosewiki_scopematches THIS project exactly (name + repo-root digest — two projects sharing a vault, even with the samewiki_name, can never prune each other) and whose page vanished or is no longer selected; hand-written notes are never touched, and a namespace that was skipped this run is left alone. - Applied runs are logged to the bookkeeper as
SYNC_OBSIDIAN;--dry-runapplies and logs nothing.
Environment Variables¶
| Variable | Default | Description |
|---|---|---|
PARROT_HOME |
~/.parrot |
Root for all parrot data (wikis, registries) |
WIKI_ENV |
(none) | Active wiki environment override — WIKI_ENV > ENV > "local" (FEAT-461) |
WIKI_STORE |
(none) | Override: read a pre-built store directly |
WIKI_STORE_BACKEND |
sqlite |
Backend for WIKI_STORE (also honoured by build, FEAT-461) |
WIKI_MODEL |
(none — auto-detects a Claude Code/Codex CLI session if available; see below) | LLM for ingest stage-2 and page generation |
WIKI_LIGHTWEIGHT_MODEL |
(none — auto-detects a Claude Code/Codex CLI session if available; see below) | LLM for ingest stage-1 triage |
WIKI_EXTRACT_LLM |
(none — auto-detects a Claude Code/Codex CLI session if available; see below) | LLM for remember --extract entity extraction |
PARROT_NO_AUTO_LLM |
(none) | Set to disable coding-agent CLI auto-detection for WIKI_MODEL/WIKI_LIGHTWEIGHT_MODEL/WIKI_EXTRACT_LLM and PARROT_BOOKSTORE_LLM |
CLAUDE_AGENT_ID |
(none) | Identity for remember/note/link attribution |
PARROT_AGENT_ID |
(none) | Fallback identity for attribution |
ARANGODB_HOST |
127.0.0.1 |
ArangoDB host (prefix configurable) |
ARANGODB_PORT |
8529 |
ArangoDB port |
ARANGODB_PROTOCOL |
http |
ArangoDB protocol |
ARANGODB_USERNAME |
root |
ArangoDB username |
ARANGODB_PASSWORD |
(empty) | ArangoDB password |
When WIKI_MODEL/WIKI_LIGHTWEIGHT_MODEL (together) or WIKI_EXTRACT_LLM are left
unset, wikitoolkit auto-detects an available coding-agent CLI session — a Claude Code
CLI session is preferred, falling back to Codex — and defaults to it, printing a visible
message naming the auto-selected model and which env var to set to override it. This
also applies to bookstore's PARROT_BOOKSTORE_LLM. Set PARROT_NO_AUTO_LLM=1 to
disable this auto-detection entirely and restore the previous strict degraded
(BM25/catalog-only) behavior when no LLM is explicitly configured.
CLI Reference¶
Quick reference for all wikitoolkit commands:
| Command | Description |
|---|---|
build |
Generate/refresh the knowledge graph from the repo or vault |
upsert [paths] [--changed] |
Incrementally re-ingest specific files or last-commit changes |
query <question> |
BM25-ranked search → token-budgeted page stubs |
page <id> |
Read one page in full |
related <id> |
Follow typed edges from a page |
status |
Plane statistics, namespaces, staleness |
remember <text> |
Save a fact/decision/lesson to the graph (persistent memory) |
note <page_id> <text> |
Append an attributed note to a page |
link <src> <dst> |
Connect two pages with a typed edge |
memories |
List saved memories and authored pages |
audit |
Review the write log and graph commits |
export [-o dir] |
Export as human-readable markdown bundle |
ingest <source> |
Supervised charter-driven document ingestion |
ingest-jira |
Extract Jira tickets into the issues namespace |
communities |
Show detected code communities |
ground <claim> |
Check a claim against the knowledge graph |
ns list |
List registered namespaces |
ns add <name> |
Register a new namespace |
ns remove <name> |
Remove a namespace |
claude install/status/uninstall |
Full Claude Code integration |
codex install |
Codex (OpenAI) integration |
gemini install |
Gemini (Google) integration |
mcp |
Start the MCP stdio server |
claude-hook |
PreToolUse hook runtime (internal) |
All read commands accept --store, --backend, and --ns for direct store
access and namespace scoping.
Architecture¶
┌─────────────────────────────────┐
│ Coding Assistants │
│ Claude Code · Codex · Gemini │
└──────────┬──────────────────────┘
│
┌──────────────┼──────────────┐
│ │ │
PreToolUse MCP Server /parrotwiki
hook nudge (6 tools) slash command
│ │ │
└──────────────┼──────────────┘
│
┌──────────▼──────────────┐
│ wikitoolkit CLI │
│ query · page · related │
│ remember · note · link │
│ build · upsert · ingest │
└──────────┬──────────────┘
│
┌──────────▼──────────────┐
│ FederatedWikiStore │
│ (concurrent fan-out, │
│ normalize, weight, │
│ merge, qualify) │
└──────────┬──────────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
┌────────▼────────┐ ┌───────▼────────┐ ┌───────▼────────┐
│ Local plane │ │ Namespace A │ │ Namespace B │
│ (SQLite/Arango) │ │ (store/vault) │ │ (database) │
│ read + write │ │ read-only │ │ read-only │
└─────────────────┘ └────────────────┘ └────────────────┘
Data flow:
Source code ──→ build ──→ wiki.db (pages + edges + FTS + embeddings)
Obsidian vault ──→ build --vault ──→ wiki.db (notes + wikilinks + tags)
Documents ──→ ingest ──→ wiki.db (charter-driven, LLM-triaged)
Jira tickets ──→ ingest-jira ──→ markdown → build --vault → wiki.db
Agent knowledge ──→ remember/note/link ──→ wiki.db (attributed, auditable)
git commit ──→ post-commit hook ──→ upsert --changed ──→ wiki.db (incremental)
See Also¶
-
Remote MCP server (serve, proxy, install) — share a wiki over HTTPS without exposing ArangoDB (FEAT-569)
-
LLM Wiki architecture (3-layer) — PageIndex + GraphIndex
- Ontology composition
- WikiToolkit as Claude Code infrastructure — focused guide on the Claude Code integration
- Jira Ticket Extractor — setup guide for
the
issuesnamespace - Jira Wiki Agent Integration — adding the issues namespace to an existing agent
- PageIndex — tree-based RAG for structured documents