okra-wiki — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited okra-wiki (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Turn any OkraPDF collection into a navigable wiki. Export pre-extracted markdown, synthesize wiki articles with cross-references, and deploy as a static site.
OkraPDF already extracts PDFs into clean markdown and groups them into collections. But extracted markdown is not a wiki — it's raw source text. The gap between "I have 20 parsed PDFs" and "I have a knowledge base I can browse and share" requires synthesis: summarizing documents, categorizing them, generating cross-references, and compiling into a navigable site.
This skill bridges that gap. It uses the collection API (export, query, sandbox) as building blocks and orchestrates them into a wiki pipeline — so users go from collection to deployed wiki without building the glue themselves.
OKRA_API_KEY environment variable setmkdocs installed (pip install mkdocs mkdocs-material) — or any static site generatorjq for JSON processingCollection (PDFs) → Export markdown → Synthesize articles → Build static site → DeployPull all documents as markdown from a collection:
# Stream NDJSON export, split into per-doc markdown files
COLLECTION_ID="col-xxx"
curl -sN "https://api.okrapdf.com/v1/collections/$COLLECTION_ID/export?format=markdown" \
-H "Authorization: Bearer $OKRA_API_KEY" \
| jq -r 'select(.type == "document") | "\(.doc_id)\t\(.file_name)\t\(.pages | map(.content) | join("\n\n---\n\n"))"' \
| while IFS=$'\t' read -r doc_id title content; do
slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
echo "$content" > "wiki/raw/${slug}.md"
echo "Exported: $title → wiki/raw/${slug}.md"
donecurl -s "https://api.okrapdf.com/v1/collections/$COLLECTION_ID" \
-H "Authorization: Bearer $OKRA_API_KEY" \
| jq '{name, description, doc_count: .document_count, docs: [.documents[] | {id, title: .file_name, pages: .pages_total}]}'Use the collection query endpoint to generate wiki-style summaries:
Per-document summaries (fanout):
curl -sN -X POST "https://api.okrapdf.com/v1/collections/$COLLECTION_ID/query" \
-H "Authorization: Bearer $OKRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Write a 300-500 word wiki article summarizing this document. Include: key contributions, methods, results, and significance. Use markdown headers. End with a See Also section listing related concepts."
}'Cross-document synthesis (sandbox mode):
curl -s -X POST "https://api.okrapdf.com/v1/collections/$COLLECTION_ID/query" \
-H "Authorization: Bearer $OKRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Analyze all documents and produce: 1) A list of 5-8 major themes/categories, 2) For each document, which categories it belongs to, 3) For each document, which other documents it most relates to and why. Return as JSON.",
"mode": "sandbox"
}'Use the sandbox to generate a wiki index and category structure server-side:
curl -s -X POST "https://api.okrapdf.com/v1/sandbox/run" \
-H "Authorization: Bearer $OKRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"apiKey": "'"$OKRA_API_KEY"'",
"code": "const docs = await DOCS.list(); const index = docs.map(d => ({ id: d.id, title: d.file_name, pages: d.total_pages, slug: d.file_name.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-|-$/g, \"\") })); return { wiki_name: \"My Wiki\", articles: index, generated: new Date().toISOString() };"
}' | jq '.result'Write an mkdocs.yml from the collection metadata:
WIKI_NAME=$(curl -s "https://api.okrapdf.com/v1/collections/$COLLECTION_ID" \
-H "Authorization: Bearer $OKRA_API_KEY" | jq -r '.name')
cat > mkdocs.yml << EOF
site_name: "$WIKI_NAME"
theme:
name: material
palette:
scheme: default
nav:
- Home: index.md
EOF
# Append each article to nav
for f in wiki/*.md; do
title=$(head -1 "$f" | sed 's/^# //')
echo " - \"$title\": $(basename $f)" >> mkdocs.yml
done
mkdocs build --clean# Cloudflare Pages
npx wrangler pages deploy site/ --project-name my-wiki --branch main
# Netlify
npx netlify deploy --dir site/ --prod
# GitHub Pages
gh-pages -d site/
# Or just serve locally
mkdocs serveFor richer wiki articles, use the OpenAI-compatible completion endpoint to have a multi-turn conversation with each document:
DOC_ID="doc-abc123"
curl -s -X POST "https://api.okrapdf.com/document/$DOC_ID/chat/completions" \
-H "Authorization: Bearer $OKRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "system", "content": "You are a wiki editor. Write concise, factual articles with headers, cross-references in [[wikilink]] format, and a See Also section."},
{"role": "user", "content": "Write a wiki article about this document."}
],
"stream": false
}' | jq -r '.choices[0].message.content'Extract structured metadata from each document to power categories, tags, and cross-references:
curl -s -X POST "https://api.okrapdf.com/document/$DOC_ID/chat/completions" \
-H "Authorization: Bearer $OKRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "Extract metadata for this document."}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "wiki_metadata",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"summary": {"type": "string", "description": "2-3 sentence summary"},
"categories": {"type": "array", "items": {"type": "string"}},
"key_concepts": {"type": "array", "items": {"type": "string"}},
"related_topics": {"type": "array", "items": {"type": "string"}},
"authors": {"type": "array", "items": {"type": "string"}},
"year": {"type": "integer"}
},
"required": ["title", "summary", "categories", "key_concepts"]
}
}
},
"stream": false
}' | jq '.choices[0].message.content | fromjson'Combine all steps into one script. Requires OKRA_API_KEY, jq, mkdocs:
#!/usr/bin/env bash
set -euo pipefail
COLLECTION_ID="${1:?Usage: okra-wiki.sh <collection-id>}"
OUT_DIR="${2:-wiki-out}"
mkdir -p "$OUT_DIR/docs"
echo "==> Fetching collection metadata..."
META=$(curl -s "https://api.okrapdf.com/v1/collections/$COLLECTION_ID" \
-H "Authorization: Bearer $OKRA_API_KEY")
WIKI_NAME=$(echo "$META" | jq -r '.name')
DOC_IDS=$(echo "$META" | jq -r '.documents[].id')
echo " $WIKI_NAME ($(echo "$META" | jq '.document_count') docs)"
echo "==> Generating wiki articles..."
for doc_id in $DOC_IDS; do
ARTICLE=$(curl -s -X POST "https://api.okrapdf.com/document/$doc_id/chat/completions" \
-H "Authorization: Bearer $OKRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "system", "content": "Write a concise wiki article about this document. Use markdown headers. Include key contributions, methods, and significance. Keep under 800 words."},
{"role": "user", "content": "Write the article."}
],
"stream": false
}' | jq -r '.choices[0].message.content // empty')
if [ -n "$ARTICLE" ]; then
TITLE=$(echo "$ARTICLE" | head -1 | sed 's/^#* *//')
SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g;s/--*/-/g;s/^-//;s/-$//')
echo "$ARTICLE" > "$OUT_DIR/docs/${SLUG}.md"
echo " ✓ $TITLE"
fi
done
echo "==> Building index..."
cat > "$OUT_DIR/docs/index.md" << EOF
# $WIKI_NAME
Generated from [OkraPDF collection]($( echo "$META" | jq -r '.public_url // "https://okrapdf.com"')).
## Articles
EOF
for f in "$OUT_DIR"/docs/*.md; do
[ "$(basename $f)" = "index.md" ] && continue
TITLE=$(head -1 "$f" | sed 's/^#* *//')
echo "- [$TITLE]($(basename $f))" >> "$OUT_DIR/docs/index.md"
done
echo "==> Writing mkdocs.yml..."
cat > "$OUT_DIR/mkdocs.yml" << EOF
site_name: "$WIKI_NAME"
docs_dir: docs
site_dir: site
theme:
name: material
palette:
scheme: default
EOF
echo "==> Building site..."
cd "$OUT_DIR" && mkdocs build --clean
echo "==> Done! Site at $OUT_DIR/site/"
echo " Preview: cd $OUT_DIR && mkdocs serve"[[Article Name]] syntax, then resolve to relative paths in a post-processing step~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.