Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
31dd61d
refactor(cli): extract confirm and bulk-command helpers
RobertLD Oct 7, 2026
8b3b806
refactor(mcp,api): dedupe sync/async tool formatting and route matching
RobertLD Oct 7, 2026
937a288
refactor(connectors): hoist repeated work and share fetch helpers
RobertLD Oct 7, 2026
c1c2bea
Merge branch 'worktree-agent-af06a94e4d1793ec2' into refactor/simplif…
RobertLD Oct 7, 2026
e2d5afb
Merge branch 'worktree-agent-a46823e9623b847a8' into refactor/simplif…
RobertLD Oct 7, 2026
ba699cd
Merge branch 'worktree-agent-a690b8d36e8952dcc' into refactor/simplif…
RobertLD Oct 7, 2026
87b28e2
refactor(core): share search row mapping and chunk-embedding cleanup
RobertLD Oct 7, 2026
bc2d09c
Merge branch 'worktree-agent-a548ee7f617a2eefb' into refactor/simplif…
RobertLD Oct 7, 2026
e939eed
fix(mcp): include document, chunk, and link IDs in tool output
RobertLD Oct 7, 2026
3a8a0ea
fix(logger): write logs to stderr so MCP stdio stream stays clean
RobertLD Oct 7, 2026
e1647e1
fix(webhooks): fire webhooks from core mutations and share one delive…
RobertLD Oct 7, 2026
a90a569
fix(db): only backfill chunks_fts when the FTS index is empty
RobertLD Oct 7, 2026
fc7129b
fix(config): env overrides no longer reset file settings
RobertLD Oct 7, 2026
d6b8342
fix(connectors): track all existing doc-site pages, not just the firs…
RobertLD Oct 7, 2026
79914d2
fix(cli): rename subcommand --version flags shadowed by global --version
RobertLD Oct 7, 2026
ab199cd
perf(db): key chunks_fts by chunk rowid (schema v18)
RobertLD Oct 7, 2026
6544115
perf(db): index documents.title for the dedup lookup
RobertLD Oct 7, 2026
6c3c4bf
fix(mcp): make task cancellation real and report final status accurately
RobertLD Oct 7, 2026
5da0482
fix(config): one API-key rule for embedding and LLM providers
RobertLD Oct 7, 2026
e122e30
fix(topics): delete vectors when deleteTopic removes documents
RobertLD Oct 7, 2026
f870f67
fix(config): config set/get/unset for every key, preserve config.json
RobertLD Oct 7, 2026
94b0c06
fix(core): embed the same text on every chunk write path
RobertLD Oct 7, 2026
6871c42
fix(core): parse import-batch and watch files through the parser regi…
RobertLD Oct 7, 2026
10b4f4d
Merge branch 'worktree-agent-aa95b4277402e96c4' into fix/audit-defects
RobertLD Oct 7, 2026
492cb02
Merge branch 'worktree-agent-aa832e10512550dcd' into fix/audit-defects
RobertLD Oct 7, 2026
0e6f8d5
fix(cli): make import-batch work on Node 20 with a shared glob matcher
RobertLD Oct 7, 2026
4d28dbb
fix(api,cli): accept every core link type via shared LINK_TYPES
RobertLD Oct 7, 2026
489ea3c
fix(db): one database location rule for CLI, MCP, REST and SDK
RobertLD Oct 7, 2026
d078997
fix(connectors): make every connector schedulable with one sync row p…
RobertLD Oct 7, 2026
01fd823
Merge branch 'worktree-agent-a4eabd1efc51d2598' into fix/audit-defects
RobertLD Oct 7, 2026
165e495
fix(embeddings): resolve model dimensions and track the model that bu…
RobertLD Oct 7, 2026
99b26c1
Merge branch 'worktree-agent-a08a04b028d6f881d' into fix/audit-defects
RobertLD Oct 7, 2026
9c26370
fix(mcp): make connector syncs cancellable and stop requiring secrets
RobertLD Oct 7, 2026
84eaefa
fix(embeddings): check the model at every vector-table open and expla…
RobertLD Oct 7, 2026
cefc0d3
Merge branch 'worktree-agent-acc3114859d287365' into fix/audit-defects
RobertLD Oct 7, 2026
7c0786c
feat(config)!: one zod schema for config keys, env vars, and secrets
RobertLD Oct 7, 2026
73548de
docs(config): document the config schema, secrets.json, auto LLM, and…
RobertLD Oct 7, 2026
80958a8
Merge branch 'worktree-agent-a38a4a27496773a8c' into feat/simplify-re…
RobertLD Oct 7, 2026
4f3b8ed
feat(errors): add NotFoundError base for every not-found error
RobertLD Oct 7, 2026
11a7824
refactor(core): move the task registry from mcp to core
RobertLD Oct 7, 2026
846ace8
refactor(core): shared helpers for the operation layer
RobertLD Oct 7, 2026
67d3641
feat(core): one ingest entry point and one default source-type rule
RobertLD Oct 7, 2026
6050cf4
feat(rag): answer() handles passthrough and LLM answers in one place
RobertLD Oct 7, 2026
04aff81
feat(core): bootstrap() opens config, database, provider and vector t…
RobertLD Oct 7, 2026
489ed79
feat(connectors): connector registry for sync, disconnect and listing
RobertLD Oct 7, 2026
faeb0ff
feat(core): operation layer with one schema per action
RobertLD Oct 7, 2026
32b063a
fix(core): resolve the LLM per surface in operations and reuse the ra…
RobertLD Oct 7, 2026
c20f243
docs(migration): list Library API renames and not-found error changes
RobertLD Oct 7, 2026
64a590f
Merge branch 'worktree-agent-a538d50c69d6a0884' into feat/simplify-re…
RobertLD Oct 7, 2026
afb0a65
feat(core): graph operation for the knowledge graph view
RobertLD Oct 7, 2026
18421aa
feat(api)!: generate REST routes and OpenAPI from operations
RobertLD Oct 7, 2026
172a2b1
feat(mcp)!: generate MCP tools from operations (11 core + admin toolset)
RobertLD Oct 7, 2026
fc07fbf
feat(core): custom chunker hook for add and shared ask input parsing
RobertLD Oct 7, 2026
2bb894e
chore(api): temporary compile fixes for the SDK export change
RobertLD Oct 7, 2026
b8690be
feat(sdk)!: LibScope on the operation layer; root exports shrink; lit…
RobertLD Oct 7, 2026
0d72be2
docs(mcp): document the 11 core tools, admin toolset and MCP migration
RobertLD Oct 7, 2026
04a5cc1
docs(api): REST reference, dashboard guide and REST migration notes f…
RobertLD Oct 7, 2026
05bf1d8
Merge branch 'worktree-agent-a4d06e389559473d0' into feat/simplify-re…
RobertLD Oct 7, 2026
8f6d0ef
Merge branch 'worktree-agent-a96ebaf4219ccf7ee' into feat/simplify-re…
RobertLD Oct 7, 2026
cbacaf8
feat(core): diversity on search and systemPrompt on ask
RobertLD Oct 7, 2026
3dabd6a
docs: LibScope SDK and libscope/lite for 2.0; Library API migration
RobertLD Oct 7, 2026
15d8185
feat(core): generic pieces for the CLI redesign
RobertLD Oct 7, 2026
46cc802
feat(cli)!: one command per task over the operation layer
RobertLD Oct 7, 2026
fc854f1
Merge branch 'worktree-agent-a2bebed4d54217521' into feat/simplify-re…
RobertLD Oct 7, 2026
61215c4
docs(cli): reference, getting started and migration table for the 2.0…
RobertLD Oct 7, 2026
cfb8b6d
Merge branch 'worktree-agent-afb5f823776d715f8' into feat/simplify-re…
RobertLD Oct 7, 2026
3de35d7
feat(config)!: mcp.toolsets config key replaces the raw LIBSCOPE_MCP_…
RobertLD Oct 7, 2026
26fcf2a
fix(operations): validate add and sync before a background task starts
RobertLD Oct 7, 2026
7882db7
fix(searches)!: store saved search filters under the search operation…
RobertLD Oct 7, 2026
f1f8fe3
feat(sdk)!: Python and Go clients use the 2.0 REST routes and backgro…
RobertLD Oct 7, 2026
26396b2
feat(packs)!: one pack registry system (git registries) over operations
RobertLD Oct 7, 2026
7e700fd
docs(packs): one registry system; migration table for packs and regis…
RobertLD Oct 7, 2026
60b00b8
fix(docker)!: run the REST API with valid 2.0 commands and keep data …
RobertLD Oct 7, 2026
2470fbc
Merge branch 'worktree-agent-a16f2be2376e01310' into feat/simplify-re…
RobertLD Oct 7, 2026
e88456b
docs(migration): list-packs takes a registry name, not registryUrl
RobertLD Oct 7, 2026
0b66297
Merge branch 'worktree-agent-a53570696a537980a' into feat/simplify-re…
RobertLD Oct 7, 2026
c9a6d9f
docs: generate the CLI, MCP, config and REST references from code
RobertLD Oct 7, 2026
b7bc1d2
docs(reference): fix hand-written parts around the generated blocks
RobertLD Oct 7, 2026
092eb5a
docs(migration): verify the 2.0 guide against the code and link its s…
RobertLD Oct 7, 2026
a248043
docs(claude): describe the 2.0 structure, config and generated docs
RobertLD Oct 7, 2026
f391c10
docs: bring the README, guides and agent notes in line with 2.0
RobertLD Oct 7, 2026
7b7fb2a
Merge branch 'worktree-agent-a3ceb4d3f234738de' into feat/simplify-re…
RobertLD Oct 7, 2026
a2c7e61
fix(core): a custom chunker can index files that have no parser
RobertLD Oct 7, 2026
56366d3
refactor(core): remove unused batch import and batch search modules
RobertLD Oct 7, 2026
3f0ec43
fix: correct stale command names in messages; remove the unreachable …
RobertLD Oct 7, 2026
5293a2c
fix(core): decode HTML character references in page titles
RobertLD Oct 8, 2026
cdd574b
fix(connectors): docs disconnect deletes only the pages the connectio…
RobertLD Oct 8, 2026
a39bd93
fix(lite): load the TypeScript grammar from tree-sitter-typescript's …
RobertLD Oct 8, 2026
e77ea84
fix(search): leave function words out of the keyword OR fallback
RobertLD Oct 8, 2026
6252880
fix(registry): publish --submit pushes the feature branch and restore…
RobertLD Oct 8, 2026
7330c56
Merge branch 'worktree-agent-a8c236278d19af209' into feat/simplify-re…
RobertLD Oct 8, 2026
b0c06ed
fix(registry): create registries on main and push new branches with -…
RobertLD Oct 8, 2026
b650ed1
fix(ingest): decode character references in page titles
RobertLD Oct 8, 2026
7055a12
docs: fix examples that fail when run as written
RobertLD Oct 8, 2026
0d7790e
Merge branch 'worktree-agent-a835b3b6cfc97fe98' into feat/simplify-re…
RobertLD Oct 8, 2026
2291602
test: use specific matchers, parameterize repeated cases, assert in s…
RobertLD Oct 8, 2026
5d27c7e
Merge branch 'worktree-agent-a1317d16b8ec63066' into feat/simplify-re…
RobertLD Oct 8, 2026
4767bee
ci: install npm packages with --ignore-scripts and rebuild only nativ…
RobertLD Oct 8, 2026
e76a943
refactor(scripts): split gen-docs main into per-file helpers
RobertLD Oct 8, 2026
8ca1700
refactor(sdk/go): use a constant for the documents path
RobertLD Oct 8, 2026
890dbc4
refactor(sdk/python): let callers bound the async wait_for_task
RobertLD Oct 8, 2026
82b23f1
Merge branch 'worktree-agent-ae999422dca7cf4c2' into feat/simplify-re…
RobertLD Oct 8, 2026
fcf62a6
refactor: fix SonarCloud issues in src
RobertLD Oct 8, 2026
b5b2ddd
test: cover the refactored helpers, scanners and edge cases
RobertLD Oct 8, 2026
00828d1
Merge branch 'worktree-agent-af58828b7adc54ee5' into feat/simplify-re…
RobertLD Oct 8, 2026
f9357f9
refactor: fix the last SonarCloud issues
RobertLD Oct 8, 2026
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
3 changes: 1 addition & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ dist
*.md
tests
coverage
sdk-python
sdk-go
sdk
.github
36 changes: 30 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
# LibScope Environment Variables
# Copy this file to .env and fill in your values.
# LibScope environment variables
# LibScope does not load .env files. Export these in your shell, or put them in
# the "env" block of your MCP client config. This file is a reference only.
# Every config key has a variable LIBSCOPE_<SECTION>_<FIELD>; see
# docs/reference/configuration.md for the full list.

# Embedding provider: "local" | "ollama" | "openai" (default: "local")
LIBSCOPE_EMBEDDING_PROVIDER=local

# Ollama settings (required when provider is "ollama")
LIBSCOPE_OLLAMA_URL=http://localhost:11434
LIBSCOPE_OLLAMA_MODEL=nomic-embed-text
# Embedding model and server URL (the local provider ignores both)
# LIBSCOPE_EMBEDDING_MODEL=nomic-embed-text
# LIBSCOPE_EMBEDDING_URL=http://localhost:11434

# OpenAI settings (required when provider is "openai")
# OpenAI key (used for embeddings and for the LLM).
# Precedence: LIBSCOPE_OPENAI_API_KEY > OPENAI_API_KEY > ~/.libscope/secrets.json.
LIBSCOPE_OPENAI_API_KEY=

# LLM for `ask`: "auto" (default) | "openai" | "anthropic" | "ollama" | "passthrough"
# LIBSCOPE_LLM_PROVIDER=auto
# LIBSCOPE_LLM_MODEL=
# LIBSCOPE_LLM_URL=

# Anthropic key. Precedence: LIBSCOPE_ANTHROPIC_API_KEY > ANTHROPIC_API_KEY > ~/.libscope/secrets.json.
# LIBSCOPE_ANTHROPIC_API_KEY=

# Fetching from private networks and self-signed TLS certificates (default: false)
# LIBSCOPE_INDEXING_ALLOW_PRIVATE_URLS=false
# LIBSCOPE_INDEXING_ALLOW_SELF_SIGNED_CERTS=false

# MCP server: optional toolsets ("admin" adds sync, install-pack, list-packs, reindex-documents)
# LIBSCOPE_MCP_TOOLSETS=admin

# Not config keys: active workspace, REST API key, key that encrypts stored webhook secrets
# LIBSCOPE_WORKSPACE=default
# LIBSCOPE_API_KEY=
# LIBSCOPE_SECRET_KEY=
14 changes: 11 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ jobs:
with:
node-version: 22
cache: npm
- run: npm ci
# Lint, format and typecheck load no native addon.
- run: npm ci --ignore-scripts
- run: npm run lint
- run: npm run format:check
- run: npm run typecheck
Expand All @@ -36,7 +37,10 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm ci --ignore-scripts
# Build only the native addons the tests load: better-sqlite3, and sharp
# (@xenova/transformers loads it in the neural retrieval-quality suite).
- run: npm rebuild better-sqlite3 sharp
- run: npm run test:coverage
- name: Upload coverage
if: matrix.node-version == 22
Expand Down Expand Up @@ -65,10 +69,14 @@ jobs:
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm ci --ignore-scripts
# docs:check opens an in-memory better-sqlite3 database.
- run: npm rebuild better-sqlite3
- run: npm run build
- name: Verify dist output
run: |
test -f dist/mcp/server.js
test -f dist/cli/index.js
test -f dist/core/index.js
- name: Check generated docs (run `npm run docs:gen` to update)
run: npm run docs:check
3 changes: 2 additions & 1 deletion .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ jobs:
node-version: 22
cache: npm
registry-url: "https://registry.npmjs.org"
- run: npm ci
# tsc and npm publish load no native addon.
- run: npm ci --ignore-scripts
- run: npm run build
- run: npm publish --provenance --access public
env:
Expand Down
113 changes: 73 additions & 40 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# libscope — Agent Guidelines

AI-powered knowledge base with MCP integration. TypeScript, Node.js >=20, CommonJS (ES2022 target).
AI-powered knowledge base with MCP integration. TypeScript, Node.js >=20, ES modules (`"type": "module"`, NodeNext, ES2022 target).

## Build & Test

Expand All @@ -13,9 +13,13 @@ npm run format # Auto-format
npm test # Run all tests via vitest
npm run test:coverage # Coverage thresholds: statements 75%, branches 74%, functions 75%, lines 75%
npm run build # tsc — outputs to dist/
npm run docs:gen # After build: rewrite the generated blocks in docs/reference/*.md
npm run docs:check # After build: exit 1 if a generated block is out of date (CI runs this)
```

CI runs on Node 20 and 22. CI checks: lint, format:check, typecheck, test:coverage, build. Build verifies `dist/mcp/server.js`, `dist/cli/index.js`, `dist/core/index.js` exist.
CI runs on Node 20 and 22. CI checks: lint, format:check, typecheck, test:coverage, build, docs:check. Build verifies `dist/mcp/server.js`, `dist/cli/index.js`, `dist/core/index.js` exist.

When you change a CLI command or option, an operation's input schema or summary, an MCP tool, a REST route or a config key, run `npm run build && npm run docs:gen` and commit the changed `docs/reference/*.md`. The generator is `scripts/gen-docs.mjs`; do not edit text between `<!-- generated:start ... -->` and `<!-- generated:end ... -->` by hand.

**Before every push, run this exact sequence locally:**
```bash
Expand Down Expand Up @@ -67,38 +71,66 @@ When delegating to subagents for mechanical fixes:

## Project Structure

Every feature is one **operation** in `src/core/operations/`. The CLI, MCP server, REST API and SDK are thin adapters over the operations: they parse input, call `runOperation(op, ctx, input)` (or `startOperationTask` for long-running operations), and format the result. Put logic in an operation or a core module, never in a surface.

```
src/
├── cli/ # Commander.js CLI
│ ├── index.ts # Main entry (#!/usr/bin/env node)
│ └── commands/ # Each file exports registerCommands(program)
├── mcp/ # MCP server
│ ├── server.ts # MCP entry point
│ └── tools/ # Each file exports registerTools(server, db, provider)
├── lite/ # libscope/lite — embeddable semantic search (no CLI/MCP/connectors)
│ ├── index.ts # Public entrypoint — exports LibScopeLite + types
│ ├── core.ts # LibScopeLite class (index, search, getContext, ask, rate)
│ ├── types.ts # LiteOptions, LiteDoc, LiteSearchResult, etc.
│ ├── normalize.ts # Raw input → markdown (dispatches to core/parsers/)
│ └── chunker-treesitter.ts # Optional tree-sitter code chunker (TS/JS/Python)
├── core/ # Business logic (documents, search, indexing, packs, topics, etc.)
│ └── parsers/ # File format parsers (markdown, pdf, docx, html, epub, pptx, csv, yaml, json)
├── api/ # REST API server (routes, middleware, openapi spec)
├── web/ # Web UI / dashboard
├── db/ # SQLite via better-sqlite3 (schema, migrations, connection)
├── providers/ # Embedding providers (local/xenova, ollama, openai)
├── registry/ # Git-backed pack registries (config, git, sync, publish, search, checksum)
├── connectors/ # Third-party syncs (notion, slack, confluence, onenote, obsidian)
├── config.ts # Config loading: env vars > project .libscope.json > user ~/.libscope/config.json > defaults
├── errors.ts # Error hierarchy
├── logger.ts # Pino logger
└── LibScope.ts # Main public API class
├── core/
│ ├── operations/ # The operation layer: one file per group (documents, search, links, graph, tags,
│ │ # topics, searches, packs, registries, connectors, admin, analytics, webhooks, tasks)
│ │ ├── types.ts # defineOperation, runOperation, startOperationTask, createOperationContext, ListResult
│ │ ├── schemas.ts # Shared zod field schemas (documentId, topic, sourceType, limit, tags, ...)
│ │ └── index.ts # OPERATIONS (every operation, in surface order), getOperation(name)
│ ├── bootstrap.ts # One startup for every surface: config -> db path -> migrate -> provider -> vector table
│ ├── ingest.ts # add: content, file, directory, URL (+ spider) or repository
│ ├── tasks.ts # Background task registry (AbortSignal, progress, 1 h retention)
│ ├── overview.ts # Counts, topics, packs, index model, health
│ ├── document-view.ts # get-document view (paged content, tags, links, ratings)
│ ├── rag.ts # answer() for ask (LLM or passthrough)
│ ├── index.ts # Package root exports: LibScope class, option/result types, errors
│ ├── parsers/ # File format parsers (markdown, pdf, docx, html, epub, pptx, csv, yaml, json, text)
│ └── ... # Business logic used by operations (documents, search, indexing, packs, topics, ...)
├── cli/
│ ├── index.ts # Program, global options (--json, --verbose, --log-level, --workspace), error handler; exports `program`
│ └── commands/ # One file per command group; each exports register(program)
├── mcp/
│ ├── server.ts # createMcpServer(): tools generated from operations (11 core + admin toolset); runStdioServer()
│ ├── format.ts # Compact text output of each tool
│ ├── errors.ts # withErrorHandling(), errorResponse()
│ └── main.ts # stdio entry point (npm run serve)
├── api/
│ ├── routes.ts # API_ROUTES: one route per operation with `http`, plus /openapi.json and /api/v1/health
│ ├── adapter.ts # HTTP input -> operation input; 202 + task for long-running operations; error -> status
│ ├── openapi.ts # buildOpenApiSpec(API_ROUTES) from the operation schemas
│ ├── middleware.ts
│ └── server.ts # startApiServer({ db, provider, config }, options)
├── web/ # Dashboard server (server.ts) and page (dashboard.ts: do not edit)
├── lite/ # libscope/lite: createLite() preset of LibScope, createCodeChunker(), TreeSitterChunker, normalizeRawInput()
├── db/ # SQLite (schema.ts migrations, connection.ts, index-meta.ts embedding model of the index)
├── providers/ # Embedding providers (local/xenova, ollama, openai)
├── registry/ # Git-backed pack registries (config, git, sync, publish, search, resolve, checksum)
├── connectors/ # notion, slack, confluence, onenote, obsidian, docs; registry.ts (types, saved connections, sync)
├── config-schema.ts # The zod config schema: keys, defaults, env var names, docs table (getConfigKeyTable)
├── config.ts # loadConfig(), config get/set/unset, secrets.json
├── errors.ts # Error hierarchy
├── logger.ts # Pino logger (stderr)
└── LibScope.ts # SDK class: add/search/ask/askStream/overview + namespaces bound to operations
scripts/gen-docs.mjs # Fills the generated blocks in docs/reference/*.md from dist/
tests/
├── unit/ # Fast, mocked — test modules in isolation
├── integration/ # Real SQLite DB, full workflows
└── fixtures/ # test-db.ts, mock-provider.ts, helpers.ts
├── unit/ # Fast, mocked — test modules in isolation (operations: tests/unit/operations/)
├── integration/ # Real SQLite DB, full workflows
└── fixtures/ # test-db.ts, mock-provider.ts, helpers.ts
```

### Adding or changing a feature

1. Add or change the operation in `src/core/operations/<group>.ts` with `defineOperation({ name, group, summary, input, annotations, http, handler })`. Every input field has `.describe()`; defaults live in the schema only. Add it to the group's exported list (it then appears in `OPERATIONS`).
2. REST: setting `http: { method, path }` creates the route and its OpenAPI entry. `annotations.longRunning` makes the route answer `202` with a task.
3. MCP: tools are registered in `src/mcp/server.ts` (`registerCoreTools` / `registerAdminTools`) with a formatter from `format.ts`. Not every operation is a tool: saved searches, webhooks, analytics and registries are CLI/REST/SDK only.
4. CLI: add or change the command in `src/cli/commands/<group>.ts`; it calls the operation and prints the result.
5. SDK: add the operation to its namespace in `NAMESPACES` in `src/LibScope.ts`.
6. Run `npm run build && npm run docs:gen` and commit the updated references. List removed or renamed names in `docs/migration-v2.md`.

## Error Handling

All custom errors extend `LibScopeError` with a `code` property and optional `cause`:
Expand All @@ -107,22 +139,23 @@ All custom errors extend `LibScopeError` with a `code` property and optional `ca
LibScopeError
├── DatabaseError
├── EmbeddingError
├── ValidationError
├── FetchError
├── ValidationError (REST 400)
├── FetchError (REST 502)
├── ConfigError
├── DocumentNotFoundError
├── ChunkNotFoundError
└── TopicNotFoundError
└── NotFoundError (REST 404; code names the resource, e.g. LINK_NOT_FOUND)
├── DocumentNotFoundError
├── ChunkNotFoundError
└── TopicNotFoundError
```

Always use the appropriate error subclass. MCP tool handlers must be wrapped with `withErrorHandling()` from `src/mcp/errors.ts`.
Always use the appropriate error subclass. MCP tool handlers are wrapped with `withErrorHandling()` from `src/mcp/errors.ts` (`registerOperationTool` does this). The CLI prints every error once in `src/cli/errors.ts` (`✗ message` and a hint).

## Database

- **Engine:** better-sqlite3 + sqlite-vec for vector search
- **Schema version:** 17 (migrations in `src/db/schema.ts`)
- **Schema version:** 19 (migrations in `src/db/schema.ts`)
- **Adding migrations:** Increment `SCHEMA_VERSION`, add entry to `MIGRATIONS` object with the new version number as key
- **Key tables:** documents, chunks, chunks_fts (FTS5), chunk_embeddings (vector), topics, ratings, schema_version
- **Key tables:** documents, chunks, chunks_fts (FTS5), chunk_embeddings (vector), index_meta (embedding model of the index), topics, tags, ratings, document_links, saved_searches, webhooks, packs, schema_version. `connector_configs` is unused.

## Testing Patterns

Expand Down Expand Up @@ -159,7 +192,7 @@ packs/<pack-name>/
```

- Registry names: `/^[a-zA-Z0-9_-]+$/`, 2-64 chars
- Git URLs: https://, ssh://, or git@host:path (no embedded credentials)
- Registry URLs: https://, ssh://, SCP-style SSH (user@host:path) or file:/// (no embedded credentials)
- Path segment validation: reject `..`, `/`, `\`, null bytes, non-alphanumeric (except `._-`)

## Logging
Expand All @@ -168,6 +201,6 @@ Use `getLogger()` from `src/logger.ts` (pino). Create child loggers with `create

## Configuration

`loadConfig()` merges with precedence: env vars > project `.libscope.json` > user `~/.libscope/config.json` > defaults. 30-second cache TTL.
`src/config-schema.ts` is the one zod schema for every config key: defaults, validation, `config get/set/unset`, env var names and the docs table. `loadConfig()` merges with precedence: env vars > project `.libscope.json` > user `~/.libscope/config.json` > defaults. API keys (`openai.apiKey`, `anthropic.apiKey`) are read only from env vars and `~/.libscope/secrets.json`. 30-second cache TTL.

Key env vars: `LIBSCOPE_EMBEDDING_PROVIDER` (local|ollama|openai), `LIBSCOPE_LLM_PROVIDER` (openai|ollama|anthropic|passthrough), `LIBSCOPE_OPENAI_API_KEY`, `LIBSCOPE_ANTHROPIC_API_KEY`, `LIBSCOPE_OLLAMA_URL`, `LIBSCOPE_OLLAMA_MODEL`.
Every key `section.field` has the env var `LIBSCOPE_<SECTION>_<FIELD>`. Key env vars: `LIBSCOPE_EMBEDDING_PROVIDER` (local|ollama|openai), `LIBSCOPE_EMBEDDING_MODEL`, `LIBSCOPE_EMBEDDING_URL`, `LIBSCOPE_LLM_PROVIDER` (auto|openai|anthropic|ollama|passthrough; default auto), `LIBSCOPE_LLM_MODEL`, `LIBSCOPE_LLM_URL`, `LIBSCOPE_OPENAI_API_KEY` (or `OPENAI_API_KEY`), `LIBSCOPE_ANTHROPIC_API_KEY` (or `ANTHROPIC_API_KEY`), `LIBSCOPE_MCP_TOOLSETS` (admin|all). Not config keys: `LIBSCOPE_WORKSPACE`, `LIBSCOPE_API_KEY` (REST auth), `LIBSCOPE_SECRET_KEY` (webhook secrets), `LIBSCOPE_VERBOSE`, `LIBSCOPE_GIT_TIMEOUT_MS`. Full list: `docs/reference/configuration.md`.
Loading
Loading