https://github.com/jctosta/locadoc
Search and read devdocs.io documentation from the terminal. Offline-first, JSON-native, and built for both humans and AI agents. Bun + TypeScript.
https://github.com/jctosta/locadoc
ai-tools bun cli devdocs developer-tools documentation llm-tools offline-docs terminal typescript
Last synced: 21 days ago
JSON representation
Search and read devdocs.io documentation from the terminal. Offline-first, JSON-native, and built for both humans and AI agents. Bun + TypeScript.
- Host: GitHub
- URL: https://github.com/jctosta/locadoc
- Owner: jctosta
- License: other
- Created: 2026-04-23T14:48:31.000Z (21 days ago)
- Default Branch: main
- Last Pushed: 2026-04-23T16:31:41.000Z (21 days ago)
- Last Synced: 2026-04-23T17:00:13.939Z (21 days ago)
- Topics: ai-tools, bun, cli, devdocs, developer-tools, documentation, llm-tools, offline-docs, terminal, typescript
- Language: TypeScript
- Homepage:
- Size: 56.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# locadoc
CLI for [devdocs.io](https://devdocs.io) content — search and read development documentation from the terminal or from automated workflows (scripts, LLM tool-use loops, editor integrations).
Docsets are downloaded once, stored under `$LOCADOC_HOME`, and searched with the same scoring algorithm devdocs.io uses in-browser.
## Demo
[](https://asciinema.org/a/30n5kUWu4IUf0tDt)
Prefer a local replay? The raw asciicast is checked in:
```sh
asciinema play docs/demo.cast # replay at recorded speed
asciinema play -s 2 docs/demo.cast # 2× speed
bash scripts/demo.sh # run the demo live against your locadoc install
```
> **AI-assisted project.** This codebase was designed and implemented collaboratively with an AI coding agent (Claude Code). The initial research, architecture decisions, and full implementation were produced in a single session from the prompt below. Review the source before depending on it in production.
>
> **Original prompt:**
> > I want to create a cli powered version of devdocs.io, to allow searching and fetching development documents directly from the terminal or piped in automated workflows. We can use https://github.com/toiletbril/dedoc as reference, but I don't want to make a carbon copy of the codebase, the idea is to keep things simple and make the tool AI friendly. Look into devdocs repository as well if needed (https://github.com/freeCodeCamp/devdocs).
## Install
```sh
curl -fsSL https://raw.githubusercontent.com/jctosta/locadoc/main/install.sh | bash
```
Grabs the right prebuilt binary for your OS/arch from [GitHub Releases](https://github.com/jctosta/locadoc/releases), verifies its SHA-256, and drops `locadoc` into `~/.local/bin`. macOS and Linux (x64 and arm64) are supported.
Env overrides:
| Variable | Default | Purpose |
|---|---|---|
| `PREFIX` | `$HOME/.local/bin` | install directory (e.g. `PREFIX=/usr/local/bin sudo bash install.sh`) |
| `LOCADOC_VERSION` | `latest` | pin a specific release tag (e.g. `LOCADOC_VERSION=v0.1.0`) |
If `$PREFIX` isn't on your `PATH`, the installer prints a one-liner to add to your shell rc.
For Windows, download the binary directly from [the latest release](https://github.com/jctosta/locadoc/releases/latest).
## Install from source
```sh
bun install
bun link # exposes `locadoc` as a global command
```
Or run without linking:
```sh
bun run src/cli.ts
```
## Getting started
```sh
locadoc docs # fetch the manifest of available docsets
locadoc ls --all | head # browse what's available
locadoc download bun react # install one or more docsets
locadoc ls # see what's installed
locadoc search useEffect # search across all installed docsets
locadoc read react reference/react/useeffect
```
Page paths come from the `path` column of `search` output — don't guess them. They map directly to keys in the docset's `db.json`.
## Output modes
locadoc is TTY-aware. Pretty output goes to a terminal, JSON goes to a pipe:
```sh
locadoc search useEffect # human-friendly table
locadoc search useEffect | jq '.[0]' # structured JSON
```
Force either explicitly:
```sh
locadoc search useEffect --json
locadoc ls --all --text
```
Set `NO_COLOR=1` to disable ANSI styling.
## Commands
### `locadoc docs [--refresh]`
Fetch the manifest of available docsets from `https://devdocs.io/docs.json`. Cached for 24h; use `--refresh` to force re-fetch.
### `locadoc ls [--all]`
Default: list installed docsets. `--all` lists everything in the manifest (requires `locadoc docs` first).
### `locadoc download ...`
Install one or more docsets. Fetches `{slug}.tar.gz` from `downloads.devdocs.io` and falls back to the per-file JSON endpoints on `documents.devdocs.io` if the tarball is missing.
### `locadoc update [...]`
Re-download docsets whose `mtime` is older than the manifest. With no args, updates everything installed.
### `locadoc remove ...`
Delete docsets from disk and the registry.
### `locadoc search [--docset ] [--type ] [--limit N] `
Search installed docsets. Scoring is a port of devdocs' `searcher.js`: exact substring first, then fuzzy regex for queries ≥ 3 chars. Without `--docset`, searches across every installed docset.
### `locadoc read [#fragment] [--format md|ansi|html|raw]`
Render a docset page. Paths come from `search` output. Fragments slice the HTML to a heading and its siblings.
`--format` defaults:
- `ansi` when stdout is a TTY
- `md` when piped or `--json` is set
- `raw` returns the untouched HTML; `html` returns the stripped/sliced HTML
## JSON schemas
Stable shapes, safe to consume from scripts / LLM tool calls.
**`ls` / `ls --all`** — `LsRow[]`:
```ts
{ slug, name, version?, release?, mtime, installed, stale }
```
**`search`** — `SearchResult[]`:
```ts
{ docset, name, path, type, score }
```
**`read`** — `ReadResult`:
```ts
{ docset, path, fragment?, title, markdown, attribution? }
```
**`docs`** — `{ count, cachedAt, path }`
**`download` / `remove`** — per-slug status records.
## Exit codes
| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Not found (docset, page, search results) |
| 2 | Usage error |
| 3 | Network error |
| 4 | Storage error |
## Storage
```
$LOCADOC_HOME (default: ~/.locadoc/)
├── manifest.json # cached docs.json
├── docsets// # index.json, db.json, meta.json (+ html assets)
└── locadoc.db # SQLite: installed docsets + flattened entries index
```
Set `LOCADOC_HOME` or pass `--home ` to relocate.
## AI / automation usage
locadoc is designed to be called from LLM tool loops and scripts.
```sh
# Find a page, then read it, all as JSON
locadoc search 'promise.all' --json --limit 1 \
| jq -r '.[0] | "\(.docset) \(.path)"' \
| xargs -n2 locadoc read --json \
| jq -r '.markdown'
```
- `--json` / `--text` force the output format independent of TTY state.
- `--quiet` silences stderr progress.
- Schemas are stable — only additive changes within `0.x`.
- No prompts, no spinners when piped.
## Use with Claude Code
locadoc ships with a [Claude Code skill](https://docs.claude.com/en/docs/claude-code/skills) that teaches the model when and how to reach for locadoc. Install it once and any future Claude Code session picks it up automatically:
```sh
locadoc skill install # writes ~/.claude/skills/locadoc/SKILL.md
locadoc skill install --project # ./.claude/skills/locadoc/SKILL.md (this project only)
locadoc skill install --force # overwrite existing
locadoc skill install --dry-run # preview without writing
locadoc skill where # print the target path
locadoc skill show # dump the embedded SKILL.md
locadoc skill uninstall # remove it
```
The skill auto-triggers on API / library documentation questions (e.g. *"how does useEffect work"*, *"signature of Array.prototype.reduce"*) and includes `allowed-tools: Bash(locadoc:*)` so Claude doesn't need to ask for permission on every invocation.
JSON schemas (stable within `0.x`):
- `install` / `uninstall` / dry-run → `{ scope, path, action, bytes? }` where `action ∈ {installed, updated, skipped, removed, absent, dry-run}`.
- `where` → `{ scope, path, exists }`.
- `show` → raw SKILL.md to stdout (no wrapper).
The SKILL.md content is embedded in the compiled binary via Bun's text-import — installing works offline and is version-locked to your locadoc binary. Update the skill by re-running `locadoc skill install --force` after upgrading.
## License and attribution
locadoc is released under the [MIT License](./LICENSE), with one exception: `src/searcher.ts` is a TypeScript port of [devdocs.io](https://devdocs.io)'s `assets/javascripts/app/searcher.js` and remains under the Mozilla Public License 2.0 per MPL's file-level copyleft.
Documentation content fetched at runtime is © its respective upstream authors, aggregated by [devdocs.io](https://devdocs.io) under MPL 2.0. This project does not redistribute docset content; it downloads it on demand from the public devdocs CDN.
[dedoc](https://github.com/toiletbril/dedoc) (GPL-3.0) by toiletbril served as a reference for the command surface and storage model — no code was copied from it. locadoc is an independent Bun/TypeScript implementation with different design goals (TTY-aware JSON output, Markdown rendering, AI tool-use friendly schemas).
## Development
```sh
bun test # run the test suite
bunx tsc --noEmit # typecheck
LOCADOC_HOME=/tmp/x bun run src/cli.ts docs
```