Command-Line Interface
The LocalVectorDB CLI provides comprehensive tools for database management, document operations, and server administration.
Exit Codes
Commands exit 0 on success and a non-zero code on failure. The semantic
codes deliberately skip 2, which Click reserves for its own usage errors
(unknown option, bad argument, missing value), so a configuration problem can
never be confused with a usage mistake.
Code |
Meaning |
|---|---|
|
Success |
|
Generic runtime error (operation failed, not found, invalid input) |
|
Usage error — emitted by Click for unknown options, bad arguments, or missing values (not raised by the commands themselves) |
|
Ollama check failed ( |
|
Permission error (e.g. filesystem permission denied writing a config file or deleting a database) |
|
Configuration error (config file missing, unreadable, invalid, or a bad
|
Installation
The CLI is included with the server installation:
pip install "localvectordb[server]"
# Verify installation
lvdb --help
Server Management
Starting the Server
# Basic server start
lvdb serve
# Custom configuration (--config is a global option: it goes BEFORE the subcommand)
lvdb --config production.toml serve --host 0.0.0.0 --port 8080
# Development mode
lvdb serve --debug --log-level DEBUG
# Specific database folder (--db-folder is also a global option)
lvdb --db-folder /data/vector_databases serve
# Disable Ollama check
lvdb serve --disable-ollama-check
Options:
--host, -H: Interface to bind to (default: 127.0.0.1)--port, -p: Port to bind to (default: 8000; falls back toserver.portfrom config)--debug: Enable debug mode--log-level, -l: Set logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)--disable-ollama-check, -x: Skip Ollama availability check
Note
--config, -c, --db-folder, -d, --verbose, -v and --quiet, -q are
global options on the top-level lvdb group, not on serve. They must be
given before the subcommand, e.g. lvdb --config production.toml serve or
lvdb --verbose db mydb add file.txt. (-h is reserved for --help; the host
short flag is -H.)
Global options (given before the subcommand):
--config, -c: Path to config file (env:LVDB_SERVER_CONFIG)--db-folder, -d: Directory containing vector databases (env:LVDB_DATABASE_ROOT_DIR)--verbose, -v: Enable verbose (DEBUG) logging--quiet, -q: Only log errors (suppress warnings/info)--version, -V: Print the installedlocalvectordbversion
Configuration Management
For a complete overview of the configuration settings, see the Configuration Parameters Documentation.
Initialize Configuration
# Create default TOML configuration
lvdb config init
# Create with predefined schema
lvdb config init --schema research_papers --output research.toml
View Configuration
# Show current configuration
lvdb config show
# Show specific section
lvdb config show --section database
# Show in different format
lvdb config show --format json
# Show from specific file (--config is global; it precedes the subcommand)
lvdb --config /path/to/config.toml config show
Example Output:
[database]
root_dir = "./.lvdb"
timeout = 300
connection_pool_size = 10
enable_gpu = false
enable_fts = true
chunk_size = 500
chunk_overlap = 1
chunking_method = "lines"
[embedding]
provider = "ollama"
model = "nomic-embed-text"
batch_size = 64
timeout = 30
max_retries = 3
[server]
host = "127.0.0.1"
port = 8000
log_level = "INFO"
log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
max_request_size = 104857600
[server.security]
require_api_key = false
api_key_header = "Authorization"
auto_prune_expired_keys = false
key_audit_logging = true
auth_log_level = "INFO"
warn_expiring_days = 7
cors_enabled = true
cors_allowed_origins = "*"
cors_allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
cors_allowed_headers = ["Content-Type", "Authorization"]
cors_max_age = 86400
Get Configuration Values
Get individual configuration values using dot notation:
# Get basic configuration values
lvdb config get server.host
lvdb config get server.port
lvdb config get database.chunk_size
lvdb config get embedding.model
# Get security settings
lvdb config get server.security.require_api_key
lvdb config get server.security.cors_enabled
lvdb config get server.security.cors_allowed_origins
# Get metadata schema fields
lvdb config get database.metadata_schema.title
lvdb config get database.metadata_schema.author
# Different output formats
lvdb config get server.port --format raw # Just the value
lvdb config get server.port --format json # JSON format
lvdb config get server.port --format pretty # Formatted (default)
Options:
--format, -f: Output format (raw, json, pretty)
Example Output:
$ lvdb config get server.security.require_api_key
Configuration: server.security.require_api_key
===============================================
false
$ lvdb config get server.security.cors_allowed_origins --format json
["*"]
$ lvdb config get database.chunk_size --format raw
500
Set Configuration Values
Set configuration values using dot notation with intelligent type conversion:
# Set basic values
lvdb config set server.port 8080
lvdb config set server.host "0.0.0.0"
lvdb config set database.chunk_size 1000
# Set boolean values
lvdb config set server.security.require_api_key true
lvdb config set database.enable_fts false
# Set list values (JSON format)
lvdb config set server.security.cors_allowed_origins '["http://localhost:3000", "https://app.example.com"]'
# Set list values (comma-separated)
lvdb config set server.security.cors_allowed_methods "GET,POST,PUT,DELETE"
# Set null values
lvdb config set server.security.key_database_path null
# Set metadata schema fields (JSON format)
lvdb config set database.metadata_schema.category '{"type": "text", "indexed": true, "required": false}'
# Preview changes without saving
lvdb config set server.port 9000 --dry-run
# Skip confirmation prompt
lvdb config set embedding.model "all-minilm-l6-v2" --force
Options:
--dry-run, -n: Show what would be changed without saving--force, -y: Skip confirmation prompt
Type Conversion:
The set command automatically converts string inputs to the appropriate type:
Booleans:
true,false,yes,no,1,0,on,offIntegers:
8080,500,-1Floats:
0.8,3.14Lists: JSON format
["item1", "item2"]or comma-separateditem1,item2Objects: JSON format
{"key": "value"}Null values:
null,none, or empty string
Example Session:
$ lvdb config set server.security.require_api_key true
Configuration Change:
=====================
Key: server.security.require_api_key
Old value: false
New value: true
Apply this change? [y/N]: y
✓ Configuration updated and saved to server-cfg.toml
$ lvdb config set server.security.cors_allowed_origins '["http://localhost:3000"]' --dry-run
Configuration Change:
=====================
Key: server.security.cors_allowed_origins
Old value: ["*"]
New value: ["http://localhost:3000"]
[DRY RUN] No changes made.
Common Configuration Tasks:
# Enable API key authentication
lvdb config set server.security.require_api_key true
# Change server binding
lvdb config set server.host "0.0.0.0"
lvdb config set server.port 8080
# Configure CORS for web applications
lvdb config set server.security.cors_allowed_origins '["http://localhost:3000", "https://app.company.com"]'
# Adjust chunking parameters
lvdb config set database.chunk_size 750
lvdb config set database.chunk_overlap 2
# Change embedding model
lvdb config set embedding.model "all-minilm-l6-v2"
lvdb config set embedding.provider "openai"
# Enable GPU acceleration
lvdb config set database.enable_gpu true
# Configure logging
lvdb config set server.log_level "DEBUG"
Dot Notation Reference:
Configuration values can be accessed using dot notation:
Database Settings (database.*):
database.root_dir- Database storage directorydatabase.chunk_size- Maximum tokens per chunkdatabase.chunk_overlap- Overlap between chunksdatabase.chunking_method- Chunking strategydatabase.enable_gpu- GPU accelerationdatabase.enable_fts- Full-text searchdatabase.connection_pool_size- Connection pool sizedatabase.timeout- Database timeout
Embedding Settings (embedding.*):
embedding.provider- Provider (ollama, openai)embedding.model- Model nameembedding.base_url- Provider base URLembedding.api_key- API key for providersembedding.batch_size- Batch processing sizeembedding.timeout- Request timeoutembedding.max_retries- Maximum retry attempts
Server Settings (server.*):
server.host- Server host addressserver.port- Server portserver.log_level- Logging levelserver.log_format- Log message formatserver.max_request_size- Maximum request size
Security Settings (server.security.*):
server.security.require_api_key- Enable API key authserver.security.api_key_header- Auth header nameserver.security.key_database_path- API key database pathserver.security.auto_prune_expired_keys- Auto cleanupserver.security.key_audit_logging- Audit key usageserver.security.cors_enabled- Enable CORSserver.security.cors_allowed_origins- Allowed originsserver.security.cors_allowed_methods- Allowed methodsserver.security.cors_allowed_headers- Allowed headers
Metadata Schema (database.metadata_schema.*):
database.metadata_schema.<field_name>- Individual schema fields
Example Metadata Schema Configuration:
# Add a new metadata field
lvdb config set database.metadata_schema.priority '{"type": "integer", "indexed": true, "default_value": 1}'
# Add a simple text field
lvdb config set database.metadata_schema.department '{"type": "text", "indexed": true}'
# Add a JSON field for tags
lvdb config set database.metadata_schema.tags '{"type": "json"}'
Security Configuration Example:
# Complete security setup
lvdb config set server.security.require_api_key true
lvdb config set server.security.cors_enabled true
lvdb config set server.security.cors_allowed_origins '["https://app.company.com"]'
lvdb config set server.security.key_audit_logging true
lvdb config set server.security.auto_prune_expired_keys true
# Verify security settings
lvdb config get server.security.require_api_key
lvdb config get server.security.cors_allowed_origins
Authentication and API Key Management
The LocalVectorDB CLI provides comprehensive API key management with permission-based access control for secure server access.
Permission Levels
API keys support two permission levels:
read_only: Grants access to query, search, and read operations only. Cannot create, update, or delete any resources.
read_write: Full access to all operations including database creation, document management, and administrative functions.
API keys are stored in {root_dir}/api_keys.db by default. To change the location of this file, set the
configuration setting key_database_path = "path/to/your/api_keys.db" in the [server.security] section.
Check Authentication Status
# Show current authentication configuration
lvdb auth status
# Show in JSON format
lvdb auth status --format json
Example Output:
Authentication Status
Configuration file: /home/user/server-cfg.toml
API Authentication: Enabled
Database-managed Keys:
Status: Available
Total keys: 5
Active keys: 4
Expired keys: 1
Expiring soon (7 days): 1
Recently used (24h): 2
⚠️ 1 key(s) expiring within 7 days
Create API Keys
API keys support permission levels for fine-grained access control:
read_only: Can query and search, but cannot create, update, or delete resources
read_write: Full access to all operations (default)
# Create a basic read-write API key (default)
lvdb auth create-key
# Create a read-only key for monitoring/analytics
lvdb auth create-key --description "Monitoring Dashboard" --permission-level read_only
# Create a read-write key with expiration
lvdb auth create-key --description "Admin Access" --permission-level read_write --expires-days 30
# Create a read-only key for public API
lvdb auth create-key --description "Public Search API" \
--permission-level read_only \
--expires-days 365 \
--created-by "api-team"
# JSON output for scripting
lvdb auth create-key --description "Script Access" --permission-level read_only --format json
# Key-only output for automation
lvdb auth create-key --permission-level read_write --format key-only
Options:
--description, -d: Human-readable description of the key’s purpose--permission-level, -p: Permission level (read_only, read_write) - defaults to read_write--expires-days: Number of days until key expires (omit for no expiration)--created-by: Identifier of who is creating the key--format, -f: Output format (table, json, key-only)
Example Output:
✓ API Key Created Successfully
Key Details:
Key ID: key_20241201_abc123
Description: Production API Access
Permission Level: read_write
Created: 2024-12-01 10:30:00 UTC
Expires: Never
API Key (save this now - it won't be shown again):
lvdb_XyZ9k2mN7qP4wR8tL3vB5nM9kJ7hF2dS6xW1qE4yT8rL9pN3mK5
⚠️ Store this key securely - it cannot be retrieved again!
List API Keys
# List all API keys
lvdb auth list-keys
# List only active keys
lvdb auth list-keys --active-only
# Exclude expired keys
lvdb auth list-keys --no-expired
# Show key management statistics
lvdb auth list-keys --show-stats
# JSON output
lvdb auth list-keys --format json
Example Output:
Key Management Statistics:
Total keys: 5
Active keys: 4
Expired keys: 1
Expiring soon (7 days): 1
Recently used (24h): 2
API Keys:
ID Description Permission Status Created Expires Last Used
-----------------------------------------------------------------------------------------------------------------------------------
key_20241201_abc123 Production API Access read_write ACTIVE 2024-12-01 Never 2024-12-01
key_20241125_def456 CI/CD Pipeline read_write ACTIVE 2024-11-25 2024-12-25 Never
key_20241120_ghi789 Monitoring Dashboard read_only ACTIVE 2024-11-20 Never 2024-11-26
key_20241115_jkl012 Development Access read_write EXPIRED 2024-11-15 2024-11-22 2024-11-21
Get Key Information
# Show detailed key information
lvdb auth key-info key_20241201_abc123
# JSON output
lvdb auth key-info key_20241201_abc123 --format json
Example Output:
API Key Information: key_20241201_abc123
Basic Information:
ID: key_20241201_abc123
Description: Production API Access
Permission Level: read_write
Created by: admin@company.com
Status:
Status: ACTIVE
Dates:
Created: 2024-12-01 10:30:00 UTC
Expires: Never
Last used: 2024-12-01 15:45:00 UTC
Revoke API Keys
# Revoke a key (with confirmation)
lvdb auth revoke-key key_20241201_abc123
# Force revoke without confirmation
lvdb auth revoke-key key_20241201_abc123 --confirm
Example Output:
Key Details:
ID: key_20241201_abc123
Description: Production API Access
Created: 2024-12-01 10:30:00 UTC
Are you sure you want to revoke key 'key_20241201_abc123'? [y/N]: y
✓ Key 'key_20241201_abc123' has been revoked.
Rotate API Keys
# Rotate a key (creates new, revokes old)
lvdb auth rotate-key key_20241201_abc123
# JSON output for automation
lvdb auth rotate-key key_20241201_abc123 --format json
# Key-only output
lvdb auth rotate-key key_20241201_abc123 --format key-only
Example Output:
✓ API Key Rotated Successfully
Original Key:
ID: key_20241201_abc123 (now revoked)
New Key Details:
Key ID: key_20241201_xyz789
Description: Rotated from key_20241201_abc123: Production API Access
Created: 2024-12-01 16:00:00 UTC
Expires: Never
New API Key (save this now):
lvdb_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4Y5z6
⚠️ Update your applications with the new key!
Clean Up Expired Keys
# Preview what would be cleaned up
lvdb auth prune-expired --dry-run
# Soft delete (deactivate) expired keys
lvdb auth prune-expired
# Hard delete (permanently remove) expired keys
lvdb auth prune-expired --hard-delete
# Skip confirmation
lvdb auth prune-expired --confirm
Example Output:
Found 2 expired key(s):
key_20241120_ghi789: Temporary Access (expired 4 days ago)
key_20241110_mno345: Test Key (expired 21 days ago)
Are you sure you want to deactivate these 2 expired keys? [y/N]: y
✓ 2 expired key(s) deactivated.
Options:
--soft-delete/--hard-delete: Deactivate vs permanently remove (default: soft-delete)--dry-run, -n: Show what would be pruned without doing it--confirm, -y: Skip confirmation prompt
API Key Usage in Applications
Once you have created an API key, use it in your applications:
cURL Example:
# Using the API key in requests
curl -H "Authorization: Bearer lvdb_XyZ9k2mN7qP4wR8tL3vB5nM9kJ7hF2dS6xW1qE4yT8rL9pN3mK5" \
-H "Content-Type: application/json" \
-X POST http://localhost:8000/api/v1/databases/my_database/query \
-d '{"query": "machine learning", "search_type": "vector", "k": 5}'
Python Example:
import requests
headers = {
"Authorization": "Bearer lvdb_XyZ9k2mN7qP4wR8tL3vB5nM9kJ7hF2dS6xW1qE4yT8rL9pN3mK5",
"Content-Type": "application/json"
}
response = requests.post(
"http://localhost:8000/api/v1/databases/my_database/query",
headers=headers,
json={"query": "neural networks", "search_type": "vector", "k": 10}
)
Environment Variable:
# Set as environment variable
export LVDB_API_KEY="lvdb_XyZ9k2mN7qP4wR8tL3vB5nM9kJ7hF2dS6xW1qE4yT8rL9pN3mK5"
# Use in application
curl -H "Authorization: Bearer $LVDB_API_KEY" \
-X GET http://localhost:8000/api/v1/databases/my_database/info
Security Best Practices
Key Management:
Rotate keys regularly: Use
lvdb auth rotate-keyfor regular key rotationSet expiration dates: Use
--expires-daysfor temporary accessUse descriptive names: Always provide meaningful descriptions
Monitor usage: Regularly check
lvdb auth list-keys --show-statsClean up expired keys: Use
lvdb auth prune-expiredto maintain hygiene
Key Storage:
Store keys securely (password managers, secrets management systems)
Never commit keys to version control
Use environment variables for applications
Rotate immediately if a key is compromised
Access Control:
Create separate keys for different applications/users
Use short-lived keys for temporary access
Revoke keys immediately when no longer needed
Monitor the “Last Used” column to identify unused keys
Example Security Workflow:
# Weekly security routine
# 1. Check for keys expiring soon
lvdb auth list-keys --show-stats
# 2. Clean up expired keys
lvdb auth prune-expired --dry-run
lvdb auth prune-expired
# 3. Rotate long-lived keys (quarterly)
lvdb auth rotate-key old_production_key
# 4. Check for unused keys
lvdb auth list-keys | grep "Never" | awk '{print $1}'
# 5. Review key descriptions and purposes
lvdb auth list-keys
Database Operations
List Databases
# List all databases
lvdb list
# List with details
lvdb list --details
# Specify database folder (--db-folder is a global option, before the subcommand)
lvdb --db-folder /path/to/databases list
Options:
--details: Show document/chunk count, model, and chunk method for each database
The database folder and config file are selected with the global options
--db-folder, -d and --config, -c (given before list), e.g.
lvdb --config server.toml list --details.
Example Output:
lvdb list --details
Databases in /home/user/.lvdb
Name Documents Chunks Model Method
====================================================================================
research_papers 1250 8500 nomic-embed-text sentences
customer_support 845 3200 all-minilm sentences
code_documentation 324 2100 nomic-embed-text code-blocks
Create Database
# Basic database creation
lvdb create my_database
# With custom configuration
lvdb create research_db \
--embedding-model nomic-embed-text \
--chunk-size 600 \
--chunking-method sections \
--metadata-schema research_papers
# With specific provider
lvdb create openai_db \
--embedding-provider openai \
--embedding-model text-embedding-3-small
Options:
--embedding-model: Embedding model to use--embedding-provider: Provider (ollama, openai)--chunk-size: Maximum tokens per chunk--chunking-method: Chunking strategy. One ofsentences,tokens,characters,words,lines,sections--chunk-overlap: Overlap between chunks--metadata-schema: Predefined schema (documents, research_papers, etc.)
Delete Database
# Delete database (with confirmation)
lvdb delete old_database
# Force delete without confirmation
lvdb delete old_database --confirm
Rename Database
# Rename a database
lvdb rename old_database new_database
rename OLD NEW moves the database’s on-disk files rather than rewriting anything
internally: the SQLite database (old.sqlite and its -wal/-shm companions),
the FAISS index (old.faiss), and any hierarchical sidecar indexes
(old_sections.faiss, old_documents.faiss) are renamed to the new prefix.
The command aborts if OLD does not exist or if a database named NEW already exists.
Database-Specific Operations
All database-specific operations use the lvdb db <database_name> prefix.
Database Information
# Show database info
lvdb db research_papers info
# Show detailed statistics
lvdb db research_papers stats
Example Output:
Database Info
-------------
Database: research_papers
Path: /home/user/.lvdb
Embedding model: nomic-embed-text
Embedding provider: ollama
Chunk size: 500
Chunking method: sentences
FTS search available: True
Total Documents: 1250
Total Chunks: 8500
Metadata fields: 4
Document Management
Add Documents
# Add single file
lvdb db my_database add document.txt
# Add multiple files
lvdb db my_database add file1.txt file2.txt
# Or with globs
lvdb db my_database add *.txt
# Add with metadata
lvdb db my_database add paper.txt --metadata '{"title": "Research Paper", "author": "Dr. Smith"}'
# Add from stdin
cat document.txt | lvdb db my_database add -
# Add with custom IDs
lvdb db my_database add file1.txt file2.txt --id "doc_1,doc_2"
Note
Rich document formats (PDF, DOCX, HTML, CSV, XLSX, …) are automatically
extracted to Markdown; plain text, Markdown, and source files are read
directly as UTF-8. Use --extract/--no-extract to force or disable
extraction. See File Extraction System.
Note
Unless --id is given, documents added from files use the filename
without extension as their id (matching db.upsert_from_file(...)), so
adding the same file again updates the existing document. Text and stdin
input gets an auto-generated id.
Get Documents
# Get document by ID
lvdb db my_database get doc_1
# Get with metadata
lvdb db my_database get doc_1 --metadata
# Pretty formatted output
lvdb db my_database get doc_1 --pretty
# Save to file
lvdb db my_database get doc_1 --output retrieved_doc.txt
# JSON output
lvdb db my_database get doc_1 --format json
By default get returns the whole document. The following flags return a
part of the document instead and are mutually exclusive (only one may be
given per invocation). They compose with --format, -f, --pretty,
--metadata and --output.
# A single chunk (0-based index) or an inclusive chunk range, as indexed
lvdb db my_database get doc_1 --chunk 3
lvdb db my_database get doc_1 --chunk 2:5
# A character slice (0-based, end-exclusive — like Python's content[M:N])
lvdb db my_database get doc_1 --range 0:200
# A line range (1-based, inclusive)
lvdb db my_database get doc_1 --lines 10:20
# A section by its Markdown heading (case-insensitive)
lvdb db my_database get doc_1 --section "Installation"
# The document's section outline (headings, levels, start lines)
lvdb db my_database get doc_1 --outline
Selection options:
--chunk M[:N]: Return the persisted chunk at 0-based indexM(as it was stored at ingest), or the inclusive rangeM:N. Open-ended formsM:/:N/:are accepted. In--format, -fmode each chunk is emitted with itsindex,contentand fullposition.--range M:N: Return the character slicecontent[M:N](0-based, end-exclusive). Open-ended forms are accepted.--lines M:N: Return linesMthroughN(1-based, inclusive). Open-ended forms are accepted.--section NAME: Return the body of the section whose Markdown heading matchesNAME(case-insensitive). Sections are detected on the fly from the document content (code-fence aware), so this works regardless of whether hierarchical embeddings were enabled at ingest. If no heading matches, the available headings are listed.--outline: Print the document’s section outline as an indented tree (or a JSON list of{index, heading, level, start_line, end_line}with--format, -f).
Update Documents
# Update content from file
lvdb db my_database update doc_1 new_content.txt
# Update from stdin
echo "New content" | lvdb db my_database update doc_1 -
# Update metadata only
lvdb db my_database update doc_1 --metadata '{"status": "revised"}'
Patch Documents (in-place edit)
Edit a document without re-sending its whole content. --find must match
exactly --count times (default 1) or the patch fails; --append and
--prepend cover the no-anchor cases. Combine ops as long as they touch
disjoint spans.
# Exact find/replace
lvdb db my_database patch doc_1 --find "brown" --replace "red"
# Replace all N occurrences (fails unless exactly N match)
lvdb db my_database patch doc_1 --find "TODO" --replace "DONE" --count 3
# Append / prepend
lvdb db my_database patch doc_1 --append " (revised)"
lvdb db my_database patch doc_1 --prepend "DRAFT: "
# Optimistic concurrency: fail if the document changed since you read it
lvdb db my_database patch doc_1 --find "v1" --replace "v2" --expect-hash 9f2b...
Delete Documents
# Delete document
lvdb db my_database delete doc_1
List Documents
# List document IDs
lvdb db my_database list
# List with pagination
lvdb db my_database list --limit 20 --offset 40
# Save to file
lvdb db my_database list --output doc_ids.txt
# JSON format
lvdb db my_database list --format json
Search Operations
# Basic vector search
lvdb db my_database search "machine learning"
# Keyword search
lvdb db my_database search "neural networks" --search-type keyword
# Hybrid search
lvdb db my_database search "AI algorithms" --search-type hybrid --vector-weight 0.8
# Limit results
lvdb db my_database search "deep learning" --limit 3
# Return chunks instead of documents
lvdb db my_database search "optimization" --return-type chunks
# Return matching chunks with surrounding context (2 neighbouring chunks each side)
lvdb db my_database search "optimization" --return-type context --context-window 2
# Size the context by a token budget instead of a chunk count, hard-truncating to fit
lvdb db my_database search "optimization" \
--return-type enriched --context-unit tokens --context-window 400 --context-truncate
# Search with metadata filter
lvdb db my_database search "research" --metadata-filter '{"journal": "Science"}'
# Minimum score threshold
lvdb db my_database search "neural" --score-threshold 0.8
# Pretty output
lvdb db my_database search "machine learning" --pretty
# Save results
lvdb db my_database search "AI" --output search_results.txt
# JSON output
lvdb db my_database search "algorithms" --format json --metadata
Options:
--limit, -n: Maximum number of results (default: 5)--search-type, -t: Search method (vector,keyword,hybrid) - defaults tovector--return-type, -r: What to return (documents,chunks,context,enriched,sections) - defaults todocuments--search-level: Which index to search (chunks,sections,documents) - defaults tochunks--score-threshold: Minimum score threshold (default: 0.0)--vector-weight: Weight for the vector component in hybrid search (default: 0.5)--context-window: Context size for--return-type context/enriched, measured in--context-unit(default: 2)--context-unit: Unit for--context-window(chunks,tokens,words,characters) - defaults tochunks--context-truncate: Hard-truncate assembled context to exactly the budget (non-chunk--context-unitonly)--metadata-filter: Metadata filter in JSON format--metadata/--no-metadata: Include metadata in output--pretty, -p: Human-readable, titled output--format, -f: Output format (tableorjson, defaulttable);-jis a shortcut for--format json--output, -o: Write results to a file instead of stdout
Context Results:
Use --return-type context or --return-type enriched to return matching chunks
together with their neighbouring chunks. --context-window sets how much context to
include, interpreted according to --context-unit: a count of neighbouring chunks
(the default), or a tokens/words/characters budget. When a token/word/character
budget is used, --context-truncate trims the assembled context to exactly that budget.
Hierarchical Search:
# Search the section-level index and return whole sections
lvdb db my_database search "training loop" --search-level sections --return-type sections
# Search the document-level index
lvdb db my_database search "training loop" --search-level documents
The --search-level sections/documents options and the sections value for
--return-type require a database created with hierarchical_embeddings=True. On a
standard (chunk-only) database, only --search-level chunks is available. See
Hierarchical Embeddings for details on hierarchical embeddings.
Example Search Output:
Vector Search Results for `machine learning`: 3 Results
=========================================================
1. Document: doc_123 (Score: 0.8924)
----------------------------------------
Machine learning algorithms have revolutionized the field of artificial intelligence.
Recent advances in deep learning have enabled breakthroughs in computer vision,
natural language processing, and reinforcement learning...
~~~~~
Metadata: {
"title": "ML Advances",
"author": "Dr. Smith",
"journal": "AI Quarterly"
}
-----
2. Document: doc_456 (Score: 0.8456)
----------------------------------------
The application of machine learning techniques to real-world problems requires
careful consideration of data quality, model selection, and evaluation metrics...
Schema Management
The LocalVectorDB CLI provides comprehensive metadata schema management capabilities, allowing you to view, update, and evolve database schemas with optional column remapping to rename existing columns while preserving data.
View Current Schema
# Display current schema (pretty format)
lvdb db my_database schema show
# Table format for overview
lvdb db my_database schema show --format table
# JSON format for programmatic use
lvdb db my_database schema show --format json
# Save schema to file
lvdb db my_database schema show --format json --output current_schema.json
Options:
--format, -f: Output format (pretty, json, table)--output, -o: Output to file instead of stdout
Example Output (Table Format):
+------------------+----------+---------+----------+---------------+
| Field Name | Type | Indexed | Required | Default Value |
+------------------+----------+---------+----------+---------------+
| title | TEXT | ✓ | ✓ | None |
| author | TEXT | ✓ | ✗ | Unknown |
| publication_year | INTEGER | ✓ | ✗ | None |
| tags | JSON | ✗ | ✗ | [] |
+------------------+----------+---------+----------+---------------+
Update Schema
Update database metadata schema from files or JSON strings, with optional column remapping for renaming existing columns:
# Update schema from JSON file
lvdb db my_database schema update --schema new_schema.json
# Update with column remapping
lvdb db my_database schema update \
--schema new_schema.json \
--mapping '{"old_author": "author", "pub_year": "publication_year"}'
# Update from JSON string
lvdb db my_database schema update \
--schema '{"title": "text", "author": "text", "year": "integer"}'
# Dry run to preview changes
lvdb db my_database schema update --schema new_schema.json --dry-run
# Skip confirmation prompts
lvdb db my_database schema update --schema new_schema.json --force
# Verbose output with detailed progress
lvdb db my_database schema update --schema new_schema.json --verbose
# Column mapping from file
lvdb db my_database schema update \
--schema new_schema.json \
--mapping column_mappings.json
Options:
--schema, -s: JSON string or path to JSON file containing new schema definition--mapping: Column mapping as JSON string or path to JSON file (old_name: new_name)--drop-columns, --drop: Actually drop removed columns (WARNING: data loss)--dry-run, --dry: Show what would be changed without making changes--force: Skip confirmation prompts--verbose, -v: Show detailed output
Schema File Format:
{
"title": {
"type": "text",
"indexed": true,
"required": true
},
"author": {
"type": "text",
"indexed": true,
"required": false,
"default_value": "Unknown"
},
"tags": {
"type": "json",
"indexed": false,
"required": false,
"default_value": []
},
"rating": {
"type": "real",
"indexed": true,
"required": false,
"default_value": 0.0
}
}
Column Mapping Format:
{
"old_column_name": "new_column_name",
"author_name": "author",
"pub_year": "publication_year",
"rating_text": "rating"
}
Example Update Session:
$ lvdb db papers schema update --schema new_schema.json --mapping '{"old_author": "author"}'
Planned Changes:
New fields: author, genre, rating
Removed fields: category
Column remapping:
old_author → author
Proceed with schema update? [y/N]: y
Applying schema update...
Schema Update Complete!
Added fields: author, genre, rating
Remapped columns:
old_author → author (150 rows transferred)
Populated defaults:
genre: 150 rows updated
rating: 150 rows updated
Supported Field Types:
text: String valuesinteger: Whole numbersreal: Floating-point numbersboolean: True/false valuesdate: Date strings (ISO format)json: JSON objects and arrays
Type Conversion During Remapping:
The system supports safe type conversions during column remapping:
TEXT→ Any type (SQLite handles conversion)INTEGER→REAL(safe numeric widening)BOOLEAN→INTEGER/REAL(True=1, False=0)JSON→TEXT(already stored as text)
Export Schema
Export current metadata schema to a file for backup or editing:
# Export to JSON file
lvdb db my_database schema export --output current_schema.json
# Export with sample data for reference
lvdb db my_database schema export --output schema_with_samples.json --include-data
# Export to TOML format (requires: pip install toml)
lvdb db my_database schema export --output schema.toml --format toml
Options:
--output, -o: Output file path (required)--format, -f: Output format (json, toml)--include-data, --with-data: Include sample data for each field type
Example Output:
$ lvdb db papers schema export --output backup_schema.json
Schema exported to backup_schema.json
Fields exported: 4
Common Schema Evolution Patterns
Simple Column Renaming:
# Rename columns while preserving data
lvdb db my_database schema update \
--schema '{"title": "text", "author": "text", "year": "integer"}' \
--mapping '{"doc_title": "title", "author_name": "author", "pub_year": "year"}'
Adding New Fields with Defaults:
# Add new fields with default values
lvdb db my_database schema update \
--schema new_schema.json
# Where new_schema.json contains:
# {
# "title": "text",
# "author": "text",
# "category": {"type": "text", "default_value": "general"},
# "tags": {"type": "json", "default_value": []},
# "rating": {"type": "real", "default_value": 0.0}
# }
Type Conversion During Migration:
# Convert text fields to appropriate types
lvdb db my_database schema update \
--schema converted_schema.json \
--mapping '{"rating_text": "rating", "is_published": "published_flag"}'
# This converts:
# rating_text (TEXT) → rating (REAL)
# is_published (TEXT) → published_flag (BOOLEAN)
Safe Schema Evolution Workflow:
# 1. Backup current schema
lvdb db my_database schema export --output backup_$(date +%Y%m%d).json
# 2. Test changes with dry run
lvdb db my_database schema update --schema new_schema.json --mapping mappings.json --dry-run
# 3. Apply changes if satisfied
lvdb db my_database schema update --schema new_schema.json --mapping mappings.json --verbose
# 4. Verify results
lvdb db my_database schema show --format table
lvdb db my_database search "test query" --limit 3
Best Practices
Planning Schema Changes:
# Always export current schema before major changes
lvdb db my_database schema export --output backup_schema.json
# Use dry-run to preview all changes
lvdb db my_database schema update --schema new_schema.json --dry-run
# Test on a copy of your database first
cp -r my_database my_database_test
lvdb db my_database_test schema update --schema new_schema.json
Column Mapping Guidelines:
Plan mappings carefully and test with sample data
Use descriptive column names that follow consistent conventions
Consider type compatibility when mapping between different field types
Document schema changes for team collaboration
Error Recovery:
# If something goes wrong, restore from backup
lvdb db my_database schema update --schema backup_schema.json --force
# Check for data integrity after major changes
lvdb db my_database stats
lvdb db my_database search "test query"
Production Considerations:
Always backup schema before production changes
Use staged deployments (dev → staging → production)
Monitor application logs after schema updates
Have rollback procedures ready
Test with representative data volumes
Example Production Workflow:
#!/bin/bash
# Production schema update script
DB_NAME="production_database"
SCHEMA_FILE="new_schema_v2.json"
MAPPING_FILE="v1_to_v2_mappings.json"
# 1. Backup current schema
echo "Creating backup..."
lvdb db $DB_NAME schema export --output "backup_$(date +%Y%m%d_%H%M%S).json"
# 2. Validate changes on test database
echo "Testing on copy..."
cp -r $DB_NAME "${DB_NAME}_test"
lvdb db "${DB_NAME}_test" schema update --schema $SCHEMA_FILE --mapping $MAPPING_FILE
if [ $? -ne 0 ]; then
echo "Schema update failed on test database. Aborting."
rm -rf "${DB_NAME}_test"
exit 1
fi
# 3. Test search functionality on copy
echo "Testing search functionality..."
lvdb db "${DB_NAME}_test" search "test query" --limit 5 > /dev/null
if [ $? -ne 0 ]; then
echo "Search test failed. Aborting."
rm -rf "${DB_NAME}_test"
exit 1
fi
# 4. Apply to production
echo "Applying to production..."
lvdb db $DB_NAME schema update --schema $SCHEMA_FILE --mapping $MAPPING_FILE --force
# 5. Verify production update
echo "Verifying production update..."
lvdb db $DB_NAME schema show --format table
lvdb db $DB_NAME stats
# 6. Cleanup
rm -rf "${DB_NAME}_test"
echo "Schema update completed successfully!"
This schema management system provides a safe, powerful way to evolve your database structure while preserving data integrity and maintaining application compatibility.
Interactive Shell
Start an interactive shell for comprehensive database operations, including document management and schema evolution:
lvdb db my_database shell
The interactive shell provides a REPL (Read-Eval-Print Loop) environment for performing multiple operations without repeatedly connecting to the database. It includes full schema management capabilities alongside traditional document operations.
Shell Startup:
$ lvdb db research_papers shell
Connected to database: research_papers
Documents: 1250, Chunks: 8500
Type 'help' for available commands, 'exit' to quit
research_papers>
Available Commands
Document Operations:
search "<query>" [limit] [type] - Search for documents
get <id> - Get document by ID
add <file or glob> - Add file(s) to database
delete <id> - Delete document by ID
list [limit] [offset] - List document IDs
count - Show document count
stats - Show database statistics
info - Show database information
Schema Management:
schema show [format] - Show current schema (pretty|json|table)
schema update <file> - Update schema from JSON file
schema update-str <json> - Update schema from JSON string
schema export <file> - Export current schema to file
schema map <old> <new> - Add column mapping for next update
schema map-clear - Clear column mappings
schema map-show - Show current column mappings
General Commands:
clear - Clear the console
help - Show this help
exit/quit - Exit shell
Document Operations Examples
Search Operations:
research_papers> search "neural networks" 3 vector
Found 3 results:
========================================
1. Document: paper_001 (Score: 0.8745)
----------------------------------------
Neural networks are computational models inspired by biological neural networks...
2. Document: paper_127 (Score: 0.8234)
----------------------------------------
Deep learning approaches to natural language processing...
3. Document: paper_089 (Score: 0.7892)
----------------------------------------
Reinforcement learning in autonomous systems...
research_papers> search "machine learning" 5 hybrid
Hybrid search for `machine learning`...
Found 5 results combining vector and keyword search...
Document Management:
research_papers> add new_papers/*.md
Found 3 files. Adding to database...
Successfully added 3 documents
Created IDs: paper_1251, paper_1252, paper_1253
research_papers> get paper_001
Document: paper_001
----------------------------------------
Neural networks are computational models inspired by biological neural networks...
research_papers> delete paper_old_001
Delete document 'paper_old_001'? [y/N]: y
Successfully deleted document: paper_old_001
research_papers> list 5 10
paper_011
paper_012
paper_013
paper_014
paper_015
research_papers> count
Total documents: 1253
Database Information:
research_papers> stats
Database Statistics:
Documents: 1253, Chunks: 8521, Avg chunks/doc: 6.80
Embedding model: nomic-embed-text
Provider: ollama
Chunk size: 500, Overlap: 50
FTS enabled: True
research_papers> info
Database Info
-------------
Database: research_papers
Embedding model: nomic-embed-text
Total Documents: 1253
Total Chunks: 8521
Schema fields: 6
Schema Management Examples
View Current Schema:
research_papers> schema show table
+------------------+----------+---------+----------+---------------+
| Field Name | Type | Indexed | Required | Default Value |
+------------------+----------+---------+----------+---------------+
| title | TEXT | ✓ | ✓ | None |
| authors | JSON | ✗ | ✗ | [] |
| journal | TEXT | ✓ | ✗ | None |
| publication_year | INTEGER | ✓ | ✗ | None |
| keywords | JSON | ✗ | ✗ | [] |
| citation_count | INTEGER | ✓ | ✗ | 0 |
+------------------+----------+---------+----------+---------------+
research_papers> schema show json
{
"title": {
"type": "text",
"indexed": true,
"required": true,
"default_value": null
},
"authors": {
"type": "json",
"indexed": false,
"required": false,
"default_value": []
}
}
Schema Export and Backup:
research_papers> schema export backup_schema.json
Schema exported to backup_schema.json
Fields exported: 6
research_papers> schema export schema_$(date +%Y%m%d).json
Schema exported to schema_20241201.json
Fields exported: 6
Column Mapping and Schema Updates:
research_papers> schema map paper_title title
Added column mapping: paper_title → title
research_papers> schema map author_list authors
Added column mapping: author_list → authors
research_papers> schema map pub_year publication_year
Added column mapping: pub_year → publication_year
research_papers> schema map-show
Current column mappings:
paper_title → title
author_list → authors
pub_year → publication_year
research_papers> schema update new_research_schema.json
Planned Changes:
New fields: keywords, citation_count, impact_factor
Removed fields: old_category
Column remapping:
paper_title → title
author_list → authors
pub_year → publication_year
Proceed with schema update? [y/N]: y
Applying schema update...
Schema Update Complete!
Added fields: keywords, citation_count, impact_factor
Remapped columns:
paper_title → title (1253 rows transferred)
author_list → authors (1253 rows transferred)
pub_year → publication_year (1253 rows transferred)
Populated defaults:
keywords: 1253 rows updated
citation_count: 1253 rows updated
Quick Schema Updates:
research_papers> schema update-str '{"title": "text", "author": "text", "tags": {"type": "json", "default_value": []}}'
Apply schema update? [y/N]: y
Schema updated successfully!
research_papers> schema map-clear
Column mappings cleared
Complete Workflow Examples
Research Paper Database Migration:
papers> # Starting with legacy schema
papers> schema show table
+---------------+----------+---------+----------+---------------+
| Field Name | Type | Indexed | Required | Default Value |
+---------------+----------+---------+----------+---------------+
| paper_title | TEXT | ✓ | ✓ | None |
| author_names | TEXT | ✗ | ✗ | None |
| journal_name | TEXT | ✓ | ✗ | None |
| year_pub | INTEGER | ✓ | ✗ | None |
+---------------+----------+---------+----------+---------------+
papers> # Export backup before changes
papers> schema export legacy_backup.json
Schema exported to legacy_backup.json
Fields exported: 4
papers> # Set up column mappings for modernization
papers> schema map paper_title title
Added column mapping: paper_title → title
papers> schema map author_names authors
Added column mapping: author_names → authors
papers> schema map journal_name journal
Added column mapping: journal_name → journal
papers> schema map year_pub publication_year
Added column mapping: year_pub → publication_year
papers> # Review planned mappings
papers> schema map-show
Current column mappings:
paper_title → title
author_names → authors
journal_name → journal
year_pub → publication_year
papers> # Apply modern research schema
papers> schema update modern_research_schema.json
Planned Changes:
New fields: title, authors, journal, publication_year, keywords, doi, abstract
Removed fields: (none - all mapped)
Column remapping:
paper_title → title
author_names → authors
journal_name → journal
year_pub → publication_year
Proceed with schema update? [y/N]: y
Applying schema update...
Schema Update Complete!
Added fields: title, authors, journal, publication_year, keywords, doi, abstract
Remapped columns:
paper_title → title (892 rows transferred)
author_names → authors (892 rows transferred)
journal_name → journal (856 rows transferred)
year_pub → publication_year (892 rows transferred)
Populated defaults:
keywords: 892 rows updated
doi: 892 rows updated
abstract: 892 rows updated
papers> # Verify the migration worked
papers> schema show table
+------------------+----------+---------+----------+---------------+
| Field Name | Type | Indexed | Required | Default Value |
+------------------+----------+---------+----------+---------------+
| title | TEXT | ✓ | ✓ | None |
| authors | JSON | ✗ | ✗ | [] |
| journal | TEXT | ✓ | ✗ | None |
| publication_year | INTEGER | ✓ | ✗ | None |
| keywords | JSON | ✗ | ✗ | [] |
| doi | TEXT | ✓ | ✗ | None |
| abstract | TEXT | ✓ | ✗ | None |
+------------------+----------+---------+----------+---------------+
papers> # Test search with new schema
papers> search "machine learning" 3
Found 3 results:
========================================
1. Document: paper_045 (Score: 0.9123)
----------------------------------------
Machine learning techniques for automated research discovery...
papers> # Test document retrieval
papers> get paper_045
Document: paper_045
----------------------------------------
Machine learning techniques for automated research discovery...
Metadata:
{
"title": "ML for Research Discovery",
"authors": ["Chen, L.", "Rodriguez, M."],
"journal": "Nature Machine Intelligence",
"publication_year": 2023,
"keywords": ["machine learning", "research", "automation"],
"doi": "10.1038/s42256-023-00123-4",
"abstract": null
}
papers> # Schema migration successful!
papers> count
Total documents: 892
Development and Testing Workflow:
dev_db> # Quick schema prototyping
dev_db> schema update-str '{"name": "text", "category": "text", "priority": {"type": "integer", "default_value": 1}}'
Apply schema update? [y/N]: y
Schema updated successfully!
dev_db> # Add test data
dev_db> add test_documents/*.txt
Successfully added 5 documents
dev_db> # Test search functionality
dev_db> search "test query" 3
Found 3 results...
dev_db> # Export schema for production use
dev_db> schema export production_ready_schema.json
Schema exported to production_ready_schema.json
Fields exported: 3
dev_db> # Clear screen and continue working
dev_db> clear
dev_db> # Final verification
dev_db> stats
Database Statistics:
Documents: 5, Chunks: 23, Avg chunks/doc: 4.60
Shell vs CLI Command Comparison
Interactive Shell Advantages:
Persistent Connection: No reconnection overhead between commands
Command History: Easy to repeat and modify previous commands
Context Awareness: Schema mappings persist across commands
Real-time Feedback: Immediate results and error handling
Workflow Continuity: Schema updates → test search → verify data
When to Use Shell vs CLI:
Use Interactive Shell for:
# Data exploration and analysis
lvdb db research shell
# > search "topic A" 10
# > search "topic B" 10
# > search "topic C" 10
# Schema development and testing
# > schema show
# > schema update-str '{"test": "text"}'
# > add test.txt
# > search "test"
# Complex migrations
# > schema export backup.json
# > schema map old new
# > schema update new.json
# > search "verify"
Use CLI Commands for:
# Scripting and automation
lvdb db prod search "query" --format json > results.json
# One-time operations
lvdb db prod add important_doc.txt
# Production deployments
lvdb db prod schema update --schema prod_schema.json --force
This enhanced interactive shell provides a powerful environment for both day-to-day database operations and complex schema evolution tasks, making it easy to iterate, test, and deploy changes safely.
Standalone Chunking
lvdb chunk runs LocalVectorDB’s position-aware chunkers on their own — no database,
embedding provider, or configuration required. It reads text from files, globs, direct
arguments, or - (stdin), chunks each input, and writes one JSON object per chunk
(JSONL) to stdout or --output. This is handy for inspecting how a document will be
split before ingesting it, or for feeding chunks to another tool.
# Chunk a Markdown file to stdout (JSONL)
lvdb chunk notes.md
# Chunk a PDF (extracted to Markdown first), 300 tokens per chunk
lvdb chunk report.pdf --method sentences --max-tokens 300
# Chunk every Markdown file matching a glob into a file
lvdb chunk "docs/*.md" --method paragraphs -o chunks.jsonl
# Chunk text from stdin with word chunks and a 20-token overlap
echo "some long text..." | lvdb chunk - --method words --overlap 20
Rich file formats (PDF, DOCX, HTML, …) are extracted to Markdown first, exactly as
lvdb db <name> add does. Use --extract/--no-extract to force or disable
extraction (the default is auto-detection per file).
Options:
--method, -M: Chunking strategy. One ofsentences,tokens,words,lines,characters,paragraphs,sections,code-blocks(default:sentences)--max-tokens, --chunk-size, -s: Maximum tokens per chunk (default: 500)--overlap: Token overlap between consecutive chunks; ignored by some strategies (default: 0)--output, -o: Write JSONL to this file instead of stdout--extract/--no-extract: Force or disable text extraction for file inputs (default: auto)
Output Format:
Each output line is a JSON object with content, index (position within its source),
tokens, and position (a dict with start, end, line, column,
end_line, end_column). When more than one input is chunked, each record also
includes a source key naming its file. A summary of how many chunks were written is
printed to stderr, so it does not pollute the JSONL on stdout.
$ echo "First sentence. Second sentence." | lvdb chunk - --method sentences
{"content": "First sentence.", "index": 0, "tokens": 2, "position": {"start": 0, "end": 15, "line": 1, "column": 0, "end_line": 1, "end_column": 15}}
{"content": "Second sentence.", "index": 1, "tokens": 2, "position": {"start": 16, "end": 32, "line": 1, "column": 16, "end_line": 1, "end_column": 32}}
Wrote 2 chunk(s) from 1 input(s)
Version
# Print the installed localvectordb version
lvdb version
# The top-level --version / -V flag prints the same value
lvdb --version
Advanced Usage Examples
Bulk Operations
# Add all markdown files in a directory tree
lvdb db papers add "documents/**/*.md"
# Add with structured metadata from JSON
lvdb db papers add papers.txt --metadata metadata.json --id ids.txt
# Search and save results for further processing
lvdb db papers search "deep learning" --format json --output dl_papers.json
# Batch process search results
for query in "neural networks" "machine learning" "computer vision"; do
lvdb db papers search "$query" --limit 10 --output "results_${query// /_}.txt"
done
Configuration and Deployment
# Create production configuration
lvdb config init --format toml --output production.toml
# Start production server (--config is global; it precedes the subcommand)
lvdb --config production.toml serve --host 0.0.0.0 --port 8080
# Create backup-friendly database (--db-folder is global; it precedes the subcommand)
lvdb --db-folder /backup/vector_dbs create backup_db
# Monitor database growth
watch 'lvdb list --details'
Pipeline Integration
#!/bin/bash
# Document processing pipeline
# Create database if not exists.
# NOTE: `lvdb create --metadata-schema` accepts: documents, research_papers,
# code_repository, customer_support. The file-oriented `files` schema
# (file_path, created_at, last_modified, file_size_bytes, ...) is only available
# via `lvdb config init --schema files`; create a config with it first if you need
# those fields, since metadata not present in the schema is ignored on insert.
lvdb create research_pipeline --embedding-model nomic-embed-text --metadata-schema documents
# Process incoming documents
find /incoming/documents -name "*.txt" -newer /tmp/last_processed | while IFS= read -r file; do
echo "Processing: $file"
# Extract file metadata using stat
last_modified=$(stat -c %Y "$file")
file_size_bytes=$(stat -c %s "$file")
created_at=$(stat -c %w "$file")
# If creation time is unavailable (returns '-'), use the last modification time
if [ "$created_at" = "-" ]; then
created_at="$last_modified"
fi
# Construct JSON metadata string
metadata=$(printf '{"file_path": "%s", "last_modified": "%s", "file_size_bytes": "%s", "created_at": "%s"}' \
"$file" "$last_modified" "$file_size_bytes" "$created_at")
# Add record using lvdb add command with metadata
lvdb db research_pipeline add "$file" --metadata "$metadata"
done
# Update timestamp
touch /tmp/last_processed
# Search and generate report
lvdb db research_pipeline search "quarterly report" --format json > quarterly_matches.json
Troubleshooting
Common Issues
Database not found:
# Check available databases
lvdb list
# Verify database folder
ls -la ~/.lvdb/
# Create database if missing
lvdb create missing_database
Ollama connection errors:
# Check Ollama status
ollama list
# Start Ollama if needed
ollama serve
# Test with different model
lvdb create test_db --embedding-model all-minilm
Permission errors:
# Check database folder permissions
ls -la ~/.lvdb/
# Fix permissions
chmod 755 ~/.lvdb/
chmod 644 ~/.lvdb/*.sqlite
Configuration issues:
# Validate configuration
lvdb config show
# Reset to defaults
mv server-cfg.toml server-cfg.toml.backup
lvdb config init
Debug Mode
# Run server in debug mode
lvdb serve --debug --log-level DEBUG
# Test with verbose output (--verbose is a global option, before the subcommand)
lvdb --verbose db test_database add test.txt
# Check server logs
tail -f server.log
Backup and Restore Operations
The LocalVectorDB CLI provides comprehensive backup and restore capabilities for database protection and disaster recovery.
Create Backups
# Create full backup
lvdb backup create my_database --type full
# Create incremental backup (requires the parent backup ID)
lvdb backup create my_database --type incremental --parent backup-abc123
# Create backup with compression
lvdb backup create my_database --type full --compression gzip
# Create backup with custom location
lvdb backup create my_database --type full --location /backups/localvectordb
# Create backup, skipping the FAISS index and integrity check
lvdb backup create my_database --type full --exclude-faiss --no-verify
Options:
--type, -t: Backup type (full, incremental; defaultfull)--parent, -p: Parent backup ID (required for incremental backups)--location, -l: Backup storage location (default./backups)--compression, -c: Compression algorithm (none, gzip, lzma, bzip2; defaultgzip)--no-verify: Skip backup integrity verification after creation--exclude-faiss: Exclude the FAISS index from the backup--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
List Backups
# List all backups
lvdb backup list
# List backups for specific database
lvdb backup list --database my_database
# Filter by backup type and limit the number shown
lvdb backup list --type full --limit 10
# Scan a specific backup location, in JSON format
lvdb backup list --location /backups/localvectordb --format json
Options:
--database, -d: Filter backups for a specific database--type, -t: Filter by backup type (full, incremental)--limit, -n: Limit the number of backups shown--location, -l: Backup storage location to scan (default./backups)--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
Example Output:
Backups for database: my_database
=====================================
ID Type Created Size Status Description
-----------------------------------------------------------------------------------------
backup_20241201_001 FULL 2024-12-01 10:30:00 125.4 MB VALID Pre-migration backup
backup_20241201_002 INCREMENTAL 2024-12-01 15:45:00 8.2 MB VALID After document updates
backup_20241202_001 FULL 2024-12-02 09:00:00 127.1 MB VALID Daily backup
Restore Backups
# Restore a backup to its original location (partial backup IDs are accepted)
lvdb backup restore abc12345
# Restore into a specific directory
lvdb backup restore backup_20241201_001 --to-location ./restored_database
# Overwrite existing files without confirmation
lvdb backup restore backup_20241201_001 --to-location ./restored --overwrite
# Restore from a specific backup store, JSON output
lvdb backup restore abc12345 --location /backups/localvectordb --format json
Options:
--to-location, -t: Directory to restore to (default: the backup’s original location)--overwrite: Overwrite existing files without confirmation--location, -l: Backup storage location to read from (default./backups)--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
The BACKUP_ID argument accepts a partial ID; the first matching backup file is used.
For incremental backups the full backup chain is located and applied automatically.
Verify Backups
# Verify a specific backup (partial backup IDs are accepted)
lvdb backup verify abc12345
# Verify a backup in a specific store, JSON output
lvdb backup verify backup_20241201_001 --location /backups/localvectordb --format json
Options:
--location, -l: Backup storage location to read from (default./backups)--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
Example Output:
Verifying backup: backup_20241201_001
=====================================
✓ Backup metadata valid
✓ File integrity checksums match
✓ Database schema valid
✓ FAISS index accessible
✓ SQLite database accessible
Backup verification: PASSED
Clean Up Backups
# Clean up backups older than 30 days (the default), keeping at least 3 full backups
lvdb backup cleanup
# Delete backups older than 7 days
lvdb backup cleanup --older-than 7
# Keep at least 5 full backups, previewing what would be deleted
lvdb backup cleanup --keep-full 5 --dry-run
# Clean up a specific backup store, JSON output
lvdb backup cleanup --location /backups/localvectordb --format json
Options:
--older-than: Delete backups older than N days (default30)--keep-full: Minimum number of full backups to keep (default3)--location, -l: Backup storage location (default./backups)--dry-run: Show what would be deleted without actually deleting--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
cleanup operates on all backups in the store (it takes no database argument) while
maintaining backup-chain integrity and keeping a minimum number of full backups.
Point-in-Time Recovery
# Restore database to a specific point in time (--to-location is required)
lvdb backup pitr "2024-12-01 14:30:00" --to-location ./pitr_restored
# ISO-8601 timestamp with a wider search tolerance, validating without restoring
lvdb backup pitr "2024-12-01T14:30:00Z" --to-location ./restored --tolerance 120 --dry-run
# Read from a specific backup store, JSON output
lvdb backup pitr "2024-12-01 14:30:00" --to-location ./restored --location /backups/localvectordb --format json
Options:
--to-location, -t: Directory to restore to (required)--tolerance: Tolerance in minutes for finding a recovery point (default60)--location, -l: Backup storage location (default./backups)--dry-run: Validate recovery without actually restoring--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
The TIMESTAMP argument accepts YYYY-MM-DD HH:MM:SS or ISO-8601 format. The database
name is read from the backup store, so it is not passed on the command line.
Example PITR Session:
$ lvdb backup pitr "2024-12-01 14:30:00" --to-location ./recovered
Point-in-Time Recovery
======================
Target time: 2024-12-01 14:30:00 UTC
Database: research_papers
Restore location: ./recovered
Recovery plan:
Base backup: backup_20241201_001 (2024-12-01 10:00:00)
Incremental backups: 2
- backup_20241201_inc_001 (2024-12-01 12:00:00)
- backup_20241201_inc_002 (2024-12-01 14:15:00)
Proceed with recovery? [y/N]: y
Restoring base backup...
Applying incremental backup 1...
Applying incremental backup 2...
Stopping at target time: 2024-12-01 14:30:00
✓ Point-in-time recovery completed successfully!
Database Migration and Schema Evolution
The LocalVectorDB CLI provides powerful migration capabilities for evolving database schemas and managing version upgrades.
Migration Status
# Check migration status for database
lvdb migrate status my_database
# Use a custom migrations directory
lvdb migrate status my_database --migrations-dir ./custom_migrations
# JSON output for automation
lvdb migrate status my_database --format json
Options:
--migrations-dir, -m: Directory containing migration files (default./migrations)--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
Example Output:
Migration Status: my_database
=============================
Current Version: 1.1.0
Target Version: 1.2.0
Pending Migrations: 2
Available Migrations:
---------------------
Version Status Description Created
---------------------------------------------------------------
1.1.1 PENDING Add citation_count field 2024-11-15
1.2.0 PENDING Add full-text search indices 2024-11-20
Migration Path:
1.1.0 → 1.1.1 → 1.2.0
Apply Migrations
# Apply all pending migrations (a backup is created first by default)
lvdb migrate apply my_database
# Apply migrations up to a specific version
lvdb migrate apply my_database --to-version 1.2.0
# Apply without creating a pre-migration backup
lvdb migrate apply my_database --no-backup
# Dry run to preview changes without a backup
lvdb migrate apply my_database --dry-run --no-backup
# Store the pre-migration backup in a custom location
lvdb migrate apply my_database --backup-location /backups/premigration
Options:
--to-version: Target version to migrate to (default: latest)--migrations-dir, -m: Directory containing migration files (default./migrations)--backup/--no-backup: Create a backup before migrating (default: enabled)--backup-location, -b: Backup storage location (default./backups)--dry-run: Validate migrations without applying them--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
Example Migration Session:
$ lvdb migrate apply research_papers --backup
Migration Plan: research_papers
===============================
Current Version: 1.1.0
Target Version: 1.2.0
Migrations to Apply:
1. v1.1.1: Add citation_count field
2. v1.2.0: Add full-text search indices
Creating backup before migration...
✓ Backup created: backup_20241201_premigration
Apply these migrations? [y/N]: y
Applying migration v1.1.1...
✓ Added citation_count field (default: 0)
✓ Updated 1,247 existing records
Applying migration v1.2.0...
✓ Created full-text search indices
✓ Rebuilt search index
✓ Migration completed successfully!
Database version: 1.1.0 → 1.2.0
Rollback Migrations
# Rollback to a specific version (both database name and target version are required)
lvdb migrate rollback my_database 1.1.0
# Rollback without creating a pre-rollback backup
lvdb migrate rollback my_database 1.0.0 --no-backup
# Validate a rollback without applying it
lvdb migrate rollback my_database 1.1.0 --dry-run
Options:
--migrations-dir, -m: Directory containing migration files (default./migrations)--backup/--no-backup: Create a backup before rolling back (default: enabled)--backup-location, -b: Backup storage location (default./backups)--dry-run: Validate the rollback without applying it--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
Both the DATABASE_NAME and TARGET_VERSION positional arguments are required.
Create Migration Templates
# Create a new migration template (the description is the positional argument)
lvdb migrate create "add priority field" --version 1.3.0
# Create a schema-change template
lvdb migrate create "add user fields" --version 1.3.1 --template schema
# Create a data-transformation template in a specific directory
lvdb migrate create "migrate old data format" --version 1.4.0 --template data --migrations-dir ./migrations
Options:
--version: Version number for the migration, e.g.1.2.0(required)--migrations-dir, -m: Directory to create the migration in (default./migrations)--template, -t: Template type —basic(default),schema, ordata--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
Example Generated Migration:
Migrations subclass Migration and describe schema
changes by returning a new_schema mapping from get_schema_changes() /
get_rollback_changes() (there are no up/down methods). The schema template
produces:
# Migration: add user fields
# Version: 1.3.1
# Created: 2024-12-01 10:30:00
from typing import Dict, Any
from localvectordb.migration import Migration
from localvectordb.core import MetadataField, MetadataFieldType
class Migration_1_3_1(Migration):
"""
add user fields
"""
version = "1.3.1"
description = "add user fields"
dependencies = [] # Add version dependencies here
def get_schema_changes(self) -> Dict[str, Any]:
"""Get schema changes to apply in forward migration."""
# Define the new complete metadata schema after this migration
new_schema = {
'user_id': MetadataField(
type=MetadataFieldType.TEXT,
indexed=True,
required=False,
default_value=None,
),
'priority': MetadataField(
type=MetadataFieldType.INTEGER,
indexed=True,
required=False,
default_value=0,
),
# Add existing fields that should remain...
}
return {
'new_schema': new_schema,
'column_mapping': {}, # Optional: rename columns {'old_name': 'new_name'}
'drop_columns': False, # Whether to drop unused columns
}
def get_rollback_changes(self) -> Dict[str, Any]:
"""Get schema changes to apply for rollback."""
rollback_schema = {
# Define schema without the changes from this migration
}
return {
'new_schema': rollback_schema,
'column_mapping': {},
'drop_columns': False,
}
List Migrations
# List all discovered migration files
lvdb migrate list
# Show each migration's dependencies, JSON output
lvdb migrate list --show-dependencies --format json
# List migrations from a custom directory
lvdb migrate list --migrations-dir ./custom_migrations
Options:
--migrations-dir, -m: Directory containing migration files (default./migrations)--show-dependencies, -d: Show migration dependencies--format, -f: Output format (table(default) orjson);-jis a shortcut for--format json
list scans the migrations directory itself, so it takes no database argument.
Example Output:
Available Migrations in migrations:
Version Description File Dependencies
-------------------------------------------------------------------------------------
1.1.1 Add citation_count field v1_1_1_add_citation.py -
1.2.0 Add full-text search indices v1_2_0_add_fts.py 1.1.1
1.3.0 Add priority field v1_3_0_add_priority.py 1.2.0
Total: 3 migration(s)
SQLite Performance Tuning
The lvdb tuning command group manages SQLite performance profiles and pragma
settings for individual databases. Unlike most commands, tuning does not require a
configuration file; point it at your databases with the global --db-folder, -d
option (given before the subcommand), e.g. lvdb --db-folder ./data tuning get mydb.
List Tuning Profiles
# List available SQLite tuning profiles with descriptions
lvdb tuning list
list takes no arguments or options.
Show Tuning Configuration
# Show the current tuning profile, overrides, and active pragmas for a database
lvdb --db-folder ./data tuning get my_database
# JSON output
lvdb --db-folder ./data tuning get my_database --format json
Options:
--format, -f: Output format (table(default),json)
Apply a Tuning Profile
# Apply a named profile to a database
lvdb --db-folder ./data tuning set my_database read_optimized
# Apply a profile with pragma overrides (repeat --override per pragma)
lvdb --db-folder ./data tuning set my_database balanced \
--override cache_size=-64000 --override mmap_size=268435456
# Apply without persisting the settings to the database
lvdb --db-folder ./data tuning set my_database read_optimized --no-persist
# Preview what would be applied without changing anything
lvdb --db-folder ./data tuning set my_database read_optimized --dry-run
Options:
--override, -o KEY=VALUE: Pragma override (may be given multiple times)--no-persist: Do not persist the settings to the database--dry-run: Show what would be applied without applying it
Set a Single Pragma
# Set a single pragma override, keeping the current profile
lvdb --db-folder ./data tuning set-pragma my_database cache_size -64000
Options:
--no-persist: Do not persist the setting to the database
set-pragma takes three positional arguments: DATABASE, PRAGMA_KEY and
PRAGMA_VALUE.
Auto-Tuning Recommendations
# Get a recommendation from an interactive workload interview
lvdb --db-folder ./data tuning auto my_database --interactive
# Get a recommendation from explicit workload parameters
lvdb --db-folder ./data tuning auto my_database \
--workload-type read_heavy --memory-constraint generous --durability normal
# Apply the recommended settings immediately, JSON output
lvdb --db-folder ./data tuning auto my_database --workload-type balanced --apply --format json
Options:
--interactive, -i: Run an interactive workload interview--workload-type: Workload type (read_heavy,write_heavy,balanced,batch_ingest,real_time) — skips the interview--memory-constraint: Memory availability (generous,moderate,limited)--durability: Data durability importance (critical,high,normal,low)--apply: Apply the recommended settings immediately--format, -f: Output format (table(default),json)
Database Maintenance
The lvdb maintenance command group runs SQLite maintenance operations on a database.
Like tuning, it does not require a configuration file; select the database directory
with the global --db-folder, -d option before the subcommand.
WAL Checkpoint
# Run a WAL checkpoint (default mode PASSIVE)
lvdb --db-folder ./data maintenance checkpoint my_database
# Run a TRUNCATE checkpoint
lvdb --db-folder ./data maintenance checkpoint my_database --mode TRUNCATE
Options:
--mode, -m: Checkpoint mode (PASSIVE(default),FULL,RESTART,TRUNCATE)
Optimize
# Run PRAGMA optimize on a database
lvdb --db-folder ./data maintenance optimize my_database
optimize takes only the DATABASE argument.
Vacuum
# Full VACUUM (prompts for confirmation; requires exclusive access)
lvdb --db-folder ./data maintenance vacuum my_database
# Skip the confirmation prompt
lvdb --db-folder ./data maintenance vacuum my_database --confirm
# Incremental vacuum, reclaiming a given number of pages
lvdb --db-folder ./data maintenance vacuum my_database --incremental --pages 5000
Options:
--incremental, -i: Run an incremental vacuum instead of a full VACUUM--pages: Pages to reclaim (incremental only; default2000)--confirm: Skip the confirmation prompt (full VACUUM only)
Analyze System Resources
# Analyze system RAM, CPU, and disk for tuning recommendations
lvdb maintenance analyze-system
# JSON output
lvdb maintenance analyze-system --format json
Options:
--format, -f: Output format (table(default),json)
analyze-system inspects the host machine and takes no database argument.
MCP Server Integration
The LocalVectorDB CLI provides Model Context Protocol (MCP) server capabilities for integration with AI assistants and tools.
Start MCP Server
# Start MCP server in read-only mode (default)
lvdb mcp serve
# Start in read-write mode
lvdb mcp serve --mode read-write
# Start with specific configuration
lvdb mcp serve --config /path/to/mcp-config.toml
# Start with custom database root
lvdb mcp serve --databases-root /data/vector_databases
# Start with database mapping
lvdb mcp serve --databases-map '{"papers": "/data/research", "docs": "http://remote-server:8000/docs"}'
# Start with debug logging
lvdb mcp serve --log-level DEBUG
Options:
--mode: Server mode (read-only, read-write)--config: Path to MCP configuration file (TOML format)--databases-root: Root directory for local databases--databases-map: JSON mapping of database names to paths/URLs--log-level: Logging level (DEBUG, INFO, WARNING, ERROR)
MCP Configuration File Example:
Server-level settings (including the read-only/read-write mode) live under
[mcp]. Databases are configured under [databases] with a root directory
and an optional [databases.map] table mapping database names to specific local
paths or remote URLs. Run lvdb mcp config-example to print a fully-commented
template. See MCP Server for the complete configuration reference.
# mcp-config.toml
[mcp]
mode = "read-write" # or "read-only" (read-only is a whole-server setting)
log_level = "INFO"
[databases]
# Root directory searched for local databases
root = "/data/databases"
# Optional: map specific names to local paths or remote URLs
[databases.map]
research = "/data/research_papers"
documentation = "/data/docs"
shared_knowledge = "http://knowledge-server:8000/shared"
Claude Desktop Integration:
To use with Claude Desktop, add this to your Claude Desktop configuration:
{
"mcpServers": {
"localvectordb": {
"command": "lvdb",
"args": ["mcp", "serve", "--mode", "read-write"],
"env": {
"LVDB_MCP_CONFIG": "/path/to/your/mcp-config.toml"
}
}
}
}
Available MCP Tools:
When running as an MCP server, LocalVectorDB provides these tools to AI assistants.
Read-only tools are available in every mode; write tools require --mode read-write.
See MCP Server for the full parameter reference.
Read-only tools:
list_databases: List available databasesget_database_info: Get database statistics and configurationquery_database: Search with vector, keyword, or hybrid searchfind_related_documents: Find documents related to a given document (nearest neighbours)filter_documents: Filter documents by metadata (with limit/offset)get_document: Retrieve a document by ID, or a portion of it (chunk/range/lines/section/outline)check_documents_exist: Check whether documents existget_metadata_schema: Get a database’s metadata schemaget_system_info: Get version, configuration, and enabled tools
Write tools (read-write mode only):
create_database: Create a new databasedelete_database: Delete a database and its dataupsert_documents: Insert or update documentsupdate_document: Update a document’s content and/or metadatapatch_document: Edit a document in place with find/replace (old_string/new_string)delete_document: Delete a document by IDupdate_metadata_schema: Add or modify metadata schema fields