Anna's Archive Skill
SkillSearchAnna's Archive integration for academic paper and book retrieval. Search shadow libraries (Library Genesis, Z-Library, Sci-Hub) via unified API with GF(3) balanced caching.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Anna's Archive Skill skill
What this skill tells your AI
The instructions your AI receives, as published by plurigrid/asi in skills/anna-archive/SKILL.md and read by ahel’s review.
Trit: 0 (ERGODIC - coordinates retrieval across sources) Foundation: Anna's Archive API + academic-research skill Principle: Unified access to shadow libraries for research
Overview
Anna's Archive is a search engine for shadow libraries:
- Library Genesis (LibGen) - books and papers
- Z-Library - ebooks
- Sci-Hub - academic papers
- Internet Archive - open library
This skill integrates with the ANNA_SELF token for authenticated access.
Configuration
# In ~/.topos/.env
export ANNA_SELF="your_anna_archive_key"
API Reference
Search Operations
// Using archive_of_anna (Node.js)
const ArchiveOfAnna = require('archive_of_anna');
// Search for books
const results = await ArchiveOfAnna.search({
text: "category theory",
lang: "en",
content: "book_nonfiction",
ext: "pdf",
sort: "newest"
});
// Result structure
// [{
// title: "Category Theory for Programmers",
// authors: ["Bartosz Milewski"],
// md5: "abc123...",
// coverUrl: "https://...",
// filesize: "5.2 MB",
// extension: "pdf"
// }]
Content Fetching
// Fetch download links by MD5 hash
const content = await ArchiveOfAnna.fetch_by_md5("abc123...");
// Returns detailed metadata + download links
// {
// title: "...",
// downloadLinks: {
// libgenRsFork: "https://...",
// ipfs: "ipfs://...",
// tor: "http://..."
// }
// }
Babashka Integration
#!/usr/bin/env bb
;; anna-search.bb - Search Anna's Archive
(require '[babashka.http-client :as http]
'[cheshire.core :as json])
(def anna-self (System/getenv "ANNA_SELF"))
(defn anna-search [query & {:keys [lang ext limit]
:or {lang "en" ext "pdf" limit 10}}]
(let [base-url "https://annas-archive.org/search"
params {:q query :lang lang :ext ext}]
;; Note: Anna's Archive doesn't have official API
;; This would scrape or use unofficial wrapper
(println (format "Searching Anna's Archive: %s" query))
{:query query :params params}))
(defn fetch-by-md5 [md5]
(let [url (format "https://annas-archive.org/md5/%s" md5)]
(println (format "Fetching: %s" url))
{:md5 md5 :url url}))
;; GF(3) balanced search: 3 queries in parallel
(defn triadic-search [queries]
(let [results (pmap anna-search queries)
trits (cycle [-1 0 1])]
{:searches (map #(assoc %1 :trit %2) results trits)
:gf3-sum (reduce + (take (count queries) trits))}))
(when (= *file* (System/getProperty "babashka.file"))
(let [query (or (first *command-line-args*) "category theory")]
(println (anna-search query))))
Python Integration
#!/usr/bin/env python3
"""anna_archive.py - Anna's Archive Python client"""
import os
import httpx
from bs4 import BeautifulSoup
from dataclasses import dataclass
from typing import List, Optional
ANNA_SELF = os.getenv("ANNA_SELF")
BASE_URL = "https://annas-archive.org"
@dataclass
class SearchResult:
title: str
authors: List[str]
md5: str
extension: str
filesize: str
trit: int = 0 # GF(3) assignment
def search(
query: str,
lang: str = "en",
ext: str = "pdf",
content: str = "book_nonfiction"
) -> List[SearchResult]:
"""Search Anna's Archive."""
url = f"{BASE_URL}/search"
params = {
"q": query,
"lang": lang,
"ext": ext,
"content": content
}
# Note: Would need to parse HTML response
# or use unofficial API wrapper
print(f"Searching: {query}")
return []
def fetch_download_links(md5: str) -> dict:
"""Get download links for a document by MD5."""
url = f"{BASE_URL}/md5/{md5}"
# Parse page for download links
return {
"md5": md5,
"url": url,
"sources": ["libgen", "ipfs", "tor"]
}
# GF(3) balanced batch search
def triadic_batch(queries: List[str]) -> dict:
"""Search 3 queries with GF(3) conservation."""
trits = [-1, 0, 1]
results = []
for i, q in enumerate(queries[:3]):
result = search(q)
for r in result:
r.trit = trits[i % 3]
results.extend(result)
trit_sum = sum(trits[:len(queries)])
return {
"results": results,
"gf3_sum": trit_sum,
"balanced": trit_sum % 3 == 0
}
Ruby Integration
# anna_archive.rb - Ruby client for Anna's Archive
require 'httpx'
require 'nokogiri'
module AnnaArchive
ANNA_SELF = ENV['ANNA_SELF']
BASE_URL = 'https://annas-archive.org'
class << self
def search(query, lang: 'en', ext: 'pdf', content: 'book_nonfiction')
url = "#{BASE_URL}/search"
params = { q: query, lang: lang, ext: ext, content: content }
# Would parse HTML response
puts "Searching Anna's Archive: #{query}"
[]
end
def fetch_by_md5(md5)
url = "#{BASE_URL}/md5/#{md5}"
{ md5: md5, url: url }
end
# GF(3) triadic search
def triadic_search(queries)
trits = [-1, 0, 1].cycle
results = queries.take(3).map.with_index do |q, i|
{ query: q, trit: trits.next, results: search(q) }
end
sum = results.sum { |r| r[:trit] }
{ results: results, gf3_sum: sum, balanced: sum % 3 == 0 }
end
end
end
Integration with academic-research Skill
;; Combine with academic-research for comprehensive search
(defn comprehensive-search [query]
(let [;; Academic sources (via academic-research skill)
arxiv-results (arxiv-search query)
semantic-results (semantic-scholar-search query)
;; Shadow libraries (via anna-archive skill)
anna-results (anna-search query)
;; Triadic assignment
all-results [{:source :arxiv :trit -1 :results arxiv-results}
{:source :semantic-scholar :trit 0 :results semantic-results}
{:source :anna-archive :trit 1 :results anna-results}]]
{:triadic all-results
:gf3-sum (reduce + (map :trit all-results))
:total-count (reduce + (map #(count (:results %)) all-results))}))
DuckDB Caching
-- Cache search results in DuckDB
CREATE TABLE IF NOT EXISTS anna_cache (
md5 VARCHAR PRIMARY KEY,
title VARCHAR,
authors VARCHAR[],
extension VARCHAR,
filesize VARCHAR,
download_links JSON,
trit TINYINT,
cached_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Insert cached result
INSERT INTO anna_cache (md5, title, authors, extension, trit)
VALUES ('abc123', 'Category Theory', ARRAY['Mac Lane'], 'pdf', 0);
-- Query with GF(3) balance
SELECT trit, COUNT(*) as count
FROM anna_cache
GROUP BY trit
ORDER BY trit;
CLI Usage
# Search for books
bb anna-search.bb "category theory"
# Search with filters
bb anna-search.bb "homotopy type theory" --lang en --ext pdf
# Fetch by MD5
bb anna-fetch.bb abc123def456
# Triadic batch search (3 queries, GF(3) balanced)
bb anna-triadic.bb "category theory" "type theory" "topos theory"
Content Types
| Content Type | Description | Trit |
|---|---|---|
book_nonfiction | Academic books | 0 |
book_fiction | Fiction books | +1 |
journal_article | Papers/articles | -1 |
magazine | Magazines | 0 |
comic | Comics | +1 |
standards | Standards docs | -1 |
GF(3) Triads
academic-research (-1) ⊗ anna-archive (0) ⊗ depth-search (+1) = 0 ✓
mathpix-ocr (-1) ⊗ anna-archive (0) ⊗ pdf (+1) = 0 ✓
sheaf-cohomology (-1) ⊗ anna-archive (0) ⊗ topos-generate (+1) = 0 ✓
Legal Notice
Anna's Archive indexes content from various sources. Users are responsible for complying with copyright laws in their jurisdiction. This skill is for research and educational purposes.
References
- Anna's Archive - Main site
- archive_of_anna - Unofficial JS API
- annas_archive_api - Dart/Flutter package
- academic-research skill - Complementary academic search
Autopoietic Marginalia
The interaction IS the skill improving itself.
Every use of this skill is an opportunity for worlding:
- MEMORY (-1): Record what was learned
- REMEMBERING (0): Connect patterns to other skills
- WORLDING (+1): Evolve the skill based on use
Add Interaction Exemplars here as the skill is used.
Signals
- GitHub stars
- 64
- Forks
- 12
- Last commit
- Jul 2026
Advanced
- Catalog kind
- skill
- Gateway key
anna-archive- Source
- github.com/plurigrid/asi