Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
bench:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-node@v7
Expand Down
12 changes: 8 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test --workspace --locked
Expand All @@ -32,7 +32,7 @@ jobs:
name: manifests, smoke, docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
with:
bun-version: '1.4.0'
Expand All @@ -41,8 +41,12 @@ jobs:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- run: bun install --frozen-lockfile
- name: Manifests agree on one version
run: bun scripts/check-version.ts
- name: Manifests agree on one version and one tagline
env:
GH_TOKEN: ${{ github.token }}
run: |
bun scripts/check-version.ts
bun scripts/check-tagline.ts "$(gh api "repos/$GITHUB_REPOSITORY" --jq .description)"
- name: Format and lints
run: cargo fmt --all --check && cargo clippy --workspace --locked -- -D warnings
- name: Build release binary
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
record:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-node@v7
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
with:
bun-version: '1.4.0'
Expand All @@ -41,4 +41,4 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v5
18 changes: 10 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
version: ${{ steps.v.outputs.version }}
publish: ${{ steps.v.outputs.publish }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- id: v
env:
GH_TOKEN: ${{ github.token }}
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:
- { key: linux-arm64-gnu, os: ubuntu-latest, target: aarch64-unknown-linux-gnu, zig: '2.17', bin: lockdocs }
- { key: win32-x64-msvc, os: windows-latest, target: x86_64-pc-windows-msvc, bin: lockdocs.exe }
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
Expand Down Expand Up @@ -98,7 +98,7 @@ jobs:
env:
V: ${{ needs.check.outputs.version }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: '22'
Expand All @@ -107,7 +107,7 @@ jobs:
with:
bun-version: '1.4.0'
- run: bun scripts/check-version.ts
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v8
with:
path: artifacts
- name: Stage natives
Expand All @@ -120,16 +120,18 @@ jobs:
chmod +x packages/npm/$key/*
done
cp README.md LICENSE packages/lockdocs/
- name: Publish to npm
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# npm trusted publishing (OIDC, id-token: write above): no long-lived
# token. Each package trusts SylphxAI/lockdocs .github/workflows/release.yml.
- name: npm with trusted publishing support
run: npm install -g npm@^11.15.0 && npm --version
- name: Publish to npm (OIDC, with provenance)
run: |
set -euo pipefail
pub() {
local dir=$1 name
name=$(node -p "require('./$dir/package.json').name")
if npm view "$name@$V" version >/dev/null 2>&1; then echo "= $name@$V already live"; return; fi
(cd "$dir" && npm publish --access public)
(cd "$dir" && npm publish --access public --provenance)
echo "+ $name@$V published"
}
for key in darwin-arm64 darwin-x64 linux-x64-gnu linux-arm64-gnu win32-x64-msvc; do pub packages/npm/$key; done
Expand Down
94 changes: 39 additions & 55 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions PROJECT.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ Bump with `bun scripts/set-version.ts X.Y.Z && cargo update -w`, add a
the npm version is new: 5 native targets on GitHub-hosted runners, the natives
and `@sylphx/lockdocs`, an `npx` smoke on a real project, the GitHub release,
and the MCP Registry entry.

npm publishing uses trusted publishing (OIDC): every package
(`@sylphx/lockdocs` and the five `@sylphx/lockdocs-*` natives) trusts
`SylphxAI/lockdocs` `.github/workflows/release.yml`; there is no npm token.
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

# lockdocs

**Context7 without rate limits: exact-version library docs for AI agents, straight from your lockfile, offline.**
**Exact-version library docs from your lockfile — local, offline, no rate limits.**

Reads your lockfile. Answers from the docs and type declarations of the exact version you installed.<br>
npm · PyPI · crates.io · Go. One Rust binary. No account, no API key, no rate limit. MIT.
npm · PyPI · crates.io · Go. MCP server + CLI in one Rust binary. No account, no API key. MIT.

[![npm](https://img.shields.io/npm/v/@sylphx/lockdocs?color=7c9cff&label=npm)](https://www.npmjs.com/package/@sylphx/lockdocs)
[![CI](https://github.com/SylphxAI/lockdocs/actions/workflows/ci.yml/badge.svg)](https://github.com/SylphxAI/lockdocs/actions/workflows/ci.yml)
Expand Down Expand Up @@ -68,7 +68,7 @@ lockdocs takes the version question off the table:

- **Exact version, zero config.** It reads `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lock`, `Cargo.lock`, `uv.lock`, `poetry.lock`, `Pipfile.lock`, `requirements*.txt` and `go.mod`. No library IDs, no "use v14" in the prompt.
- **Docs that ship with the code.** READMEs, changelogs and `docs/` folders, plus the API reference in the package itself: `.d.ts` declarations with JSDoc, Python docstrings and stubs, rustdoc comments, Go doc comments. If it is installed, it is documented, including your private and internal packages.
- **Offline and unlimited.** Everything is read from `node_modules`, your virtualenv, `~/.cargo/registry` and the Go module cache. No network, no account, no rate limit, and nothing about your dependencies leaves your machine.
- **Offline and unlimited.** Everything is read from `node_modules`, your virtualenv, `~/.cargo/registry` and the Go module cache. Offline after a one-time model download (129 MB, kept as 32 MB); keyword-only mode (`LOCKDOCS_EMBED=0`) needs no network at all. No account, no rate limit, and nothing about your dependencies leaves your machine.
- **Upstream docs at the exact tag, when you want them.** Packages like Next.js, Django and FastAPI ship no docs. `lockdocs fetch` pulls their docs folders from GitHub at the git tag of your pinned version, once, then stays offline.
- **Meaning, not just words.** Hybrid retrieval: BM25 fused with a small local embedding model (downloaded once, 32 MB on disk), plus API redirects from deprecation notes ("use `model_validate` instead").
- **Small, cited answers.** Packed into a token budget (1,200 by default), every section cited as `package@version path:line`.
Expand Down Expand Up @@ -119,16 +119,18 @@ Out of the box lockdocs reads only your disk (plus the one-time embedding model

## Benchmarks

70 questions whose correct answer depends on the version, over 14 libraries (zod, Next.js, React Router, pydantic, axum, tokio, Tailwind CSS, ESLint, Prisma, React, Vite, Express, SQLAlchemy, Django, FastAPI), each asked in a real project with that version installed. An answer passes when it contains the version-correct API and none of the other version's. Same questions and grader against Context7's anonymous API, on a GitHub-hosted runner ([run](https://github.com/SylphxAI/lockdocs/actions/runs/36125903106)):
<!-- bench:start -->
70 questions whose correct answer depends on the version, over 15 libraries (zod, Next.js, React Router, pydantic, axum, tokio, Tailwind CSS, ESLint, Prisma, React, Vite, Express, SQLAlchemy, Django, FastAPI), each asked in a real project with that version installed. An answer passes when it contains the version-correct API and none of the other version's. Same questions and grader against Context7's anonymous API, on a GitHub-hosted runner ([run](https://github.com/SylphxAI/lockdocs/actions/runs/36125903106)):

| | correct | older majors | newer majors | tokio | median tokens | median latency |
|---|---|---|---|---|---|---|
| **lockdocs + `lockdocs fetch`** | **55/70** | **24/33** | 29/34 | 2/3 | **875** | **87 ms** |
| lockdocs + `lockdocs fetch` | 55/70 | 24/33 | 29/34 | 2/3 | 875 | 87 ms |
| lockdocs, package files only | 46/70 | 22/33 | 22/34 | 2/3 | 915 | 49 ms |
| Context7 (anonymous) | 49/70 | 12/33 | **34/34** | **3/3** | 908 | 2,011 ms |
| Context7 (anonymous) | 49/70 | 12/33 | 34/34 | 3/3 | 908 | 2,011 ms |
<!-- bench:end -->

- **Where versions matter most, lockdocs wins by 2x.** On older majors Context7 often answers with the newest API (all five pydantic 1 questions got pydantic 2 answers).
- **Context7 still leads on the newest majors and on tokio.** Its index covers docs websites that no package or tag ships (Prisma's docs now describe a later major), and lockdocs has a few ranking misses. The benchmark page lists every question and answer.
- **Context7 is ahead on the newest majors (34/34 vs 29/34) and on tokio (3/3 vs 2/3)**, and we are working to close that. Its index covers docs websites that no package or tag ships (Prisma's docs now describe a later major), and lockdocs has a few ranking misses. The benchmark page lists every question and answer.
- **~23x faster, no quota.** lockdocs latency is a fresh CLI process per question; `lockdocs fetch` is a one-time 0.6-5 s per project (median 2.4 s).

Method, questions, per-question results and scripts: [benchmark page](https://sylphxai.github.io/lockdocs/benchmarks) and [`bench/`](bench/).
Expand Down Expand Up @@ -185,8 +187,7 @@ lockdocs reads files on your machine and answers over stdio. Network use: the em

- [**repomap**](https://github.com/SylphxAI/repomap): a map of your codebase for AI agents: code graph, search, call paths and change impact, with an interactive graph UI.
- [**anymd**](https://github.com/SylphxAI/anymd): any file to clean Markdown for your AI agent: PDF, Word, PowerPoint, Excel, EPUB, HTML, images, audio and video.

All three run locally, need no API key, and are MIT licensed.
- [**readme-mark**](https://github.com/SylphxAI/readme-mark): beautiful README images from one URL.

## Star history

Expand Down
Loading
Loading