Semantic search for your company's content. Connect your markdown repos, Notion workspace, Google Docs, and Dropbox — then search everything with a single API.
Angler pulls content from multiple sources, chunks it, generates embeddings, and serves a search API powered by ChromaDB. It finds content by meaning, not just keywords — so searching "what did we discuss about pricing" will find relevant passages even if they never use the word "pricing."
| Source | What it indexes | Auth |
|---|---|---|
| Git | Markdown files from a git repo | GitHub token (for private repos) |
| Notion | Pages and database entries | Internal integration token |
| Google Docs | Documents in a Drive folder | Service account credentials |
| Dropbox | Text files in a Dropbox folder | Access token |
| SQLite | Rows from SQLite tables | File path to .db |
Copy angler.yaml.example to angler.yaml and enable the sources you need:
sources:
- type: git
repo_url: https://github.com/yourorg/docs.git
- type: notion
# token set via NOTION_TOKEN env var
- type: google_docs
folder_id: "1a2b3c..."
- type: dropbox
# token set via DROPBOX_TOKEN env var
folder_path: "/Documents" # optional, "" = root
- type: sqlite
db_path: "~/agency/agency.db"
tables:
- table: employees
text_columns: [name, role, notes]
id_column: id
updated_column: updated_atpip install -r requirements.txt
uvicorn app:app --reloadFor simple deployments, skip the config file and use env vars:
| Variable | Source | Description |
|---|---|---|
REPO_URL |
Git | URL of your markdown repo |
GITHUB_TOKEN |
Git | For private GitHub repos |
NOTION_TOKEN |
Notion | Internal integration token |
NOTION_DATABASES |
Notion | Comma-separated database IDs (optional) |
GOOGLE_DOCS_FOLDER_ID |
Google Docs | Root folder to index |
GOOGLE_CREDENTIALS_JSON |
Google Docs | Service account JSON |
DROPBOX_TOKEN |
Dropbox | App access token |
DROPBOX_FOLDER_PATH |
Dropbox | Folder to index (optional, default: root) |
SQLITE_DB_PATH |
SQLite | Path to .db file |
SQLITE_TABLES |
SQLite | JSON array of table configs (see below) |
CHROMA_DIR |
— | Where to persist the index (default: /data/chroma) |
PORT |
— | Server port (default: 8000) |
- Fork this repo
- Connect it to Railway
- Set your source env vars
- Railway will use the included
Dockerfileandrailway.toml
Search your content. Returns ranked results with relevance scores.
{
"query": "your query",
"results": [
{
"id": "git://docs/meeting-notes.md::chunk_3",
"score": 0.82,
"content": "...matching text...",
"metadata": {
"source": "git",
"path": "docs/meeting-notes.md",
"title": "Meeting Notes"
}
}
]
}Filter by source type:
GET /search?q=pricing+discussion&source=notion
Re-fetch all sources and rebuild the index.
Check service status, configured sources, and index size.
Just set REPO_URL. For private repos, also set GITHUB_TOKEN.
- Create an internal integration at notion.so/my-integrations
- Copy the integration token
- Share your top-level workspace pages with the integration (this grants access to all child pages)
- Set
NOTION_TOKEN
- Create a service account in Google Cloud Console
- Enable the Google Drive and Google Docs APIs
- Share your target folder with the service account's email address
- Set
GOOGLE_DOCS_FOLDER_IDandGOOGLE_CREDENTIALS_JSON
- Create an app at dropbox.com/developers/apps
- Generate an access token
- Set
DROPBOX_TOKENand optionallyDROPBOX_FOLDER_PATH
By default it indexes .md, .txt, .csv, .json, .yaml, .xml, .html, and .rtf files. You can customize this with the extensions config option.
Point Angler at any SQLite database and tell it which tables and columns to index:
- type: sqlite
db_path: "~/agency/agency.db"
tables:
- table: employees
text_columns: [name, role, notes]
id_column: id # default: rowid
updated_column: updated_at # optional, enables incremental indexing
- table: projects
text_columns: [name, notes]
id_column: idEach row becomes a document with the text columns concatenated. The updated_column is optional — if provided, incremental reindexing will only fetch rows modified since the last run.
Create a skill at ~/.claude/skills/search-docs/SKILL.md:
---
name: search-docs
description: Search our team's docs, notes, and knowledge base.
user_invocable: true
---
Use the Bash tool to query the search API:
\```bash
curl -s "https://your-deployment.up.railway.app/search?q=QUERY&n=5" | python3 -m json.tool
\```Then use /search-docs in Claude Code to search your content naturally.
MIT