semtools
App Listed
Semantic search and document parsing tools for the command line
- Downloads
- 541
- Dependents
- Not applicable
- Stars
- 1,882
- Forks
- 144
- Contributors
- 5
- Commits
- 173
- Latest release
- 3.0.1 ·
About
Semantic search and document parsing tools for the command line
A high-performance CLI tool for document processing and semantic search, built with Rust for speed and reliability.
semtools parse- Parse documents (PDF, DOCX, etc.) using, by default, the LlamaParse API into markdown formatsemtools search- Local semantic keyword search using multilingual embeddings with cosine similarity matching and per-line context matchingsemtools ask- AI agent with search and read tools for answering questions over document collections (defaults to OpenAI, but see the config section to learn more about connecting to any OpenAI-Compatible API)semtools workspace- Workspace management for accelerating search over large collections
NOTE: By default, parse uses LlamaParse as a backend. Get your API key today for free at https://cloud.llamaindex.ai. search and workspace remain local-only. ask requires an OpenAI API key.
Read the full README
Key Features
- Fast semantic search using model2vec embeddings from minishlab/potion-multilingual-128M
- Reliable document parsing with caching and error handling
- Unix-friendly design with proper stdin/stdout handling
- Configurable distance thresholds and returned chunk sizes
- Multi-format support for parsing documents (PDF, DOCX, PPTX, etc.)
- Concurrent processing for better parsing performance
- Workspace management for efficient document retrieval over large collections
Installation
Prerequisites:
- For the
parsesubcommand: LlamaIndex Cloud API key - For the
asksubcommand: OpenAI API key
Install:
You can install semtools via npm:
npm i -g @llamaindex/semtools
Or via cargo:
# install entire crate
cargo install semtools
# install only select features
cargo install semtools --no-default-features --features=parse
Note: Installing from npm builds the Rust binaries locally during install if a prebuilt binary is not available, which requires Rust and Cargo to be available in your environment. Install from rustup if needed: https://www.rust-lang.org/tools/install.
Quick Start
Basic Usage:
# Parse some files
semtools parse my_dir/*.pdf
# Search some (text-based) files
semtools search "some keywords" *.txt --max-distance 0.3 --n-lines 5
# Ask questions about your documents using an AI agent
semtools ask "What are the main findings?" papers/*.txt
# Combine parsing and search
semtools parse my_docs/*.pdf | xargs search "API endpoints"
# Ask a question to a set of files
semtools ask "Some question?" *.txt
# Combine parsing with the ask agent
semtools parse research_papers/*.pdf | xargs ask "Summarize the key methodologies"
# Ask based on stdin content
cat README.md | semtools ask "How do I install SemTools?"
Advanced Usage:
# Combine with grep for exact-match pre-filtering and distance thresholding
semtools parse *.pdf | xargs cat | grep -i "error" | semtools search "network error" --max-distance 0.3
# Pipeline with content search (note the 'xargs' on search to search files instead of stdin)
find . -name "*.md" | xargs semtools parse | xargs semtools search "installation"
# Combine with grep for filtering (grep could be before or after parse/search!)
semtools parse docs/*.pdf | xargs semtools search "API" | grep -A5 "authentication"
# Save search results from stdin search
semtools parse report.pdf | xargs cat | semtools search "summary" > results.txt
Using Workspaces:
# Create or select a workspace
# Workspaces are stored in ~/.semtools/workspaces/
semtools workspace use my-workspace
> Workspace 'my-workspace' configured.
> To activate it, run:
> export SEMTOOLS_WORKSPACE=my-workspace
>
> Or add this to your shell profile (.bashrc, .zshrc, etc.)
# Activate the workspace
export SEMTOOLS_WORKSPACE=my-workspace
# All search commands will now use the workspace for caching embeddings
# The initial command is used to initialize the workspace
semtools search "some keywords" ./some_large_dir/*.txt --n-lines 5 --top-k 10
# If documents change, they are automatically re-embedded and cached
echo "some new content" > ./some_large_dir/some_file.txt
semtools search "some keywords" ./some_large_dir/*.txt --n-lines 5 --top-k 10
# If documents are removed, you can run prune to clean up stale files
semtools workspace prune
# You can see the stats of a workspace at any time
semtools workspace status
> Active workspace: arxiv
> Root: /Users/loganmarkewich/.semtools/workspaces/arxiv
> Documents: 3000
> Index: Yes (IVF_PQ)
CLI Help
$ semtools parse --help
A CLI tool for parsing documents using various backends
Usage: semtools parse [OPTIONS] <FILES>...
Arguments:
<FILES>... Files to parse
Options:
-c, --config <CONFIG> Path to the config file. Defaults to ~/.semtools_config.json
-b, --backend <BACKEND> The backend type to use for parsing. Defaults to `llama-parse` [default: llama-parse]
-v, --verbose Verbose output while parsing
-h, --help Print help
$ semtools search --help
A CLI tool for fast semantic keyword search
Usage: semtools search [OPTIONS] <QUERY> [FILES]...
Arguments:
<QUERY> Query to search for (positional argument)
[FILES]... Files to search, optional if using stdin
Options:
-n, --n-lines <N_LINES> How many lines before/after to return as context [default: 3]
--top-k <TOP_K> The top-k files or texts to return (ignored if max_distance is set) [default: 3]
-m, --max-distance <MAX_DISTANCE> Return all results with distance below this threshold (0.0+)
-i, --ignore-case Perform case-insensitive search (default is false)
-j, --json Output results in JSON format
-h, --help Print help
$ semtools workspace --help
Manage semtools workspaces
Usage: semtools workspace [OPTIONS] <COMMAND>
Commands:
use Use or create a workspace (prints export command to run)
status Show active workspace and basic stats
prune Remove stale or missing files from store
help Print this message or the help of the given subcommand(s)
Options:
-j, --json Output results in JSON format
-h, --help Print help
$ semtools ask --help
A CLI tool for document-based question-answering
Usage: semtools ask [OPTIONS] <QUERY> [FILES]...
Arguments:
<QUERY> Query to prompt the agent with
[FILES]... Files to search, optional if using stdin
Options:
-c, --config <CONFIG> Path to the config file. Defaults to ~/.semtools_config.json
--api-key <API_KEY> OpenAI API key (overrides config file and env var)
--base-url <BASE_URL> OpenAI base URL (overrides config file)
-m, --model <MODEL> Model to use for the agent (overrides config file)
--api-mode <API_MODE> API mode to use: 'chat' or 'responses' (overrides config file)
-j, --json Output results in JSON or text format
-h, --help Print help
Configuration
SemTools uses a unified configuration file at ~/.semtools_config.json that contains settings for all CLI tools. You can also specify a custom config file path using the -c or --config flag on any command.
Unified Configuration File
Create a ~/.semtools_config.json file with settings for the tools you use. All sections are optional - if not specified, sensible defaults will be used. (They parse_kwargs section is passed directly to LlamaParse, see docs for available options.)
{
"parse": {
"api_key": "your_llama_cloud_api_key_here",
"num_ongoing_requests": 10,
"base_url": "https://api.cloud.llamaindex.ai",
"parse_kwargs": {
"tier": "agentic",
"version": "latest",
"disable_cache": false
},
"check_interval": 5,
"max_timeout": 3600,
"max_retries": 10,
"retry_delay_ms": 1000,
"backoff_multiplier": 2.0
},
"ask": {
"api_key": "your_openai_api_key_here",
"base_url": null,
"model": "gpt-4o-mini",
"max_iterations": 20,
"api_mode": "responses", // Can be responses or chat
}
}
Find out more about parsing configuration on the dedicated documentation page.
See example_semtools_config.json in the repository for a complete example.
Environment Variables
As an alternative or supplement to the config file, you can set API keys via environment variables:
# For parse tool
export LLAMA_CLOUD_API_KEY="your_llama_cloud_api_key_here"
# For ask tool
export OPENAI_API_KEY="your_openai_api_key_here"
Configuration Priority
Configuration values are resolved in the following priority order (highest to lowest):
- CLI arguments (e.g.,
--api-key,--model,--base-url) - Config file (
~/.semtools_config.jsonor custom path via-c) - Environment variables (
LLAMA_CLOUD_API_KEY,OPENAI_API_KEY) - Built-in defaults
This allows you to set common defaults in the config file while overriding them on a per-command basis when needed.
Subcommand-Specific Configuration
Parse Subcommand
The parse subcommand requires a LlamaParse API key. Get your free API key at https://cloud.llamaindex.ai.
Configuration options:
api_key: Your LlamaParse API keybase_url: API endpoint (default: "https://api.cloud.llamaindex.ai")num_ongoing_requests: Number of concurrent requests (default: 10)parse_kwargs: Additional parsing parameterscheck_interval,max_timeout,max_retries,retry_delay_ms,backoff_multiplier: Retry and timeout settings
Ask Subcommand
The ask subcommand requires an OpenAI API key for the agent's LLM.
Configuration options:
api_key: Your OpenAI API keybase_url: Custom OpenAI-compatible API endpoint (optional, for using other providers)model: LLM model to use (default: "gpt-4o-mini")max_iterations: Maximum agent loop iterations (default: 10)
You can also override these per-command:
semtools ask "What is this about?" docs/*.txt --model gpt-4o --api-key sk-...
Agent Use Case Examples
Future Work
- [ ] More parsing backends (something local-only would be great!)
- [ ] Improved search algorithms
- [x] Built-in agentic search
- [x] Persistence for speedups on repeat searches on the same files
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- LlamaIndex/LlamaParse for document parsing capabilities
- model2vec-rsfor fast embedding generation
- minishlab/potion-multilingual-128M for an amazing default static embedding model
- simsimd for efficient similarity computation
Compatibility
- Runs on
- GPU support unknown
What shows it
- no dependency or feature matches a backend row
- Native code
- Optional
- Binds native code: zstd-sys (feature workspace)
- Python bindings
- No Python binding crate found
- License
- MIT
Compare with similar projects
Order: strongest tier first, then most downloads, then name, with unmeasured values last. A library counts downloads over 30 days. An app counts binary downloads per release. An app with none counts its crate downloads over 30 days. ML Rust runs this catalogue, so its closest project always gets a row.
| Project | Downloads | Dependents | Stars | Latest release | Runs on (GPU) | Native code | License |
|---|---|---|---|---|---|---|---|
|
Semantic search and document parsing tools for the command line |
541 binary downloads per release | Not applicable | 1,882 | 3.0.1 | GPU support unknown | Binds native code: zstd-sys (feature workspace) | MIT |
|
meilisearch-sdk Featured
Rust wrapper for the Meilisearch API. Meilisearch is a powerful, fast, open-source, easy to use and deploy search engine. |
170,111 downloads over 30 days | 16 | 431 | 0.33.0 | GPU support unknown | No native code found | MIT |
|
splintr Listed
Tokenizer for Rust and Python: pure Rust by default, with 18 bundled vocabularies and four backends covering BPE, SentencePiece and WordPiece. Its output matches Hugging Face tokenizers id for id on 14 model families, including GPT-2, Qwen, Whisper, T5 and BERT. Python bindings |
8,204 downloads over 30 days | 7 | 63 | 0.22.2 | GPU support unknown | Binds native code: pcre2-sys (feature pcre2) | MIT |
|
Local first semantic and hybrid BM25 grep / search tool for use by AI and humans! |
1,775 binary downloads per release | Not applicable | 1,772 | 0.8.1 | GPU support unknown | Binds native code: tree-sitter, tree-sitter-language, openssl-sys (feature openssl), ort-sys (feature mixedbread) | Apache-2.0 OR MIT |
|
🔍 Tiny, full-text search engine for static websites built with Rust and Wasm |
147 binary downloads per release | Not applicable | 2,980 | Not measured | Not measured | Apache-2.0 | |
|
All-in-one platform for search, recommendations, RAG, and analytics offered via API |
9 binary downloads per release | Not applicable | 2,723 | Not measured | Not measured | MIT | |
|
A flexible, performant and reliable search database without the AI bullshit. |
0 binary downloads per release | Not applicable | 1,459 | Not measured | Not measured | MIT |
All projects in Text, embeddings and searchAll projects in Documents and OCR
Why ListedNo archive, New or Featured rule places it, so it is Listed.
What it lacks for Featured
- The check holds no value for Homebrew installs on request over 365 days, Repology repository families, Docker pull growth over 90 days. A gate that lacks its signal does not pass.
What else the check found
- The last activity is on 11 Mar 2026, 243 days ago. The rules expect an update within 365 days. Dormancy rule
- The oldest outside issue waits 417 days for a reply, past the limit of 270. No maintainer replied in 365 days. Rot signals rule
Not measured: Homebrew installs on request over 365 days, Repology repository families, Docker pull growth over 90 days.
Exact rules: Listed, Featured app. The check on applied thresholds version 9.
Every rule outcome, as the check records it
expected-interval: app: E = 365 daysdormancy: last activity 2026-03-11, 243 days ago, E = 365: activerot: oldest unanswered issue 417 days (limit 270), no maintainer reply in 365 daysfeatured: not featured: unknown homebrew_on_request_365d, repology_families, docker_pull_growth_90dlisted: listed: no archive, new or featured rule applies
Measurements and sources
Each signal row shows the raw value, its source and the fetch date. The Sources list gathers every distinct source on this page. Movement needs more history.
Sources6 sources
- Description: the crates.io description
- crates.io database dump, fetched
- GitHub releases, fetched
- GitHub repository, fetched
- crates.io package, fetched
- GitHub contributors, fetched
Adoption541 binary downloads per release4 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Active dependents | Not measured | Yes | ||
| New dependents (365 days) | Not measured | Yes | ||
| Peak active dependents | Not measured | Yes | ||
| Active dependents as a share of the peak | Not measured | Yes | ||
| Binary downloads per release | 541 | GitHub releases | Yes |
MaintenanceLatest human commit: 8 months ago4 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Latest human commit | 2026-03-11 | GitHub repository | Yes | |
| Latest release | 2026-03-11 | GitHub releases | Yes | |
| First release | 2025-08-26 | crates.io database dump | Yes | |
| Latest version | 3.0.1 | crates.io database dump | No | |
| Days the oldest outside issue waits for a reply | 417 | GitHub repository | Yes | |
| Maintainer replies over 365 days | 0 | GitHub repository | Yes | |
| Repository archived | false | GitHub repository | Yes | |
| Repository gone | false | GitHub repository | Yes | |
| Release commit or manifest in the repo | true | crates.io package | No | |
| Published docs | Not measured | Yes | ||
| Latest release fails cargo check | Not measured | Yes | ||
| Build check date | Not measured | Yes | ||
| Build check toolchain | Not measured | Yes |
SecurityNot measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Unpatched vulnerabilities past the grace window | Not measured | Yes | ||
| RustSec unmaintained advisory | Not measured | Yes | ||
| Deprecation notice | Not measured | Yes | ||
| Deprecated requirement | Not measured | Yes |
Distribution17 releases, 15 downloads over 30 days6 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Releases | 17 | crates.io database dump | No | |
| Downloads over 30 days | 15 | crates.io database dump | No | |
| Binary downloads over the last 3 releases | 1625 | GitHub releases | Yes | |
| Homebrew installs on request over 365 days | Not measured | Yes | ||
| Repology repository families | Not measured | Yes | ||
| Docker pull growth over 90 days | Not measured | Yes | ||
| Docker pulls at the growth baseline | Not measured | Yes | ||
| Every version a prerelease | false | crates.io database dump | Yes | |
| Every version 0.0.x | false | crates.io database dump | Yes | |
| Every version yanked | Not measured | Yes | ||
| Crate deleted from crates.io | Not measured | Yes |
Repository1,882 stars, 144 forks, 5 contributors, 173 commits. Stars alone never qualify a project.
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| GitHub stars | 1882 | GitHub repository | Yes — one part of the repository route | |
| GitHub forks | 144 | GitHub repository | Yes — one part of the repository route | |
| Contributors with a GitHub account | 5 | GitHub contributors | Yes — one part of the repository route | |
| Commits on the default branch | 173 | GitHub repository | No | |
| Repository's main crate left out of the entry | none | crates.io database dump | Yes |
Facts that never count
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| License | MIT | crates.io database dump | No | |
| Runs on, from listed crates and their direct dependencies | GPU support unknown | crates.io database dump | No | |
| What shows each backend | no dependency or feature matches a backend row | crates.io database dump | No | |
| Native code, from listed crates and their dependencies | Binds native code: zstd-sys (feature workspace) | crates.io database dump | No | |
| Python bindings, from direct dependencies of listed crates | No Python binding crate found | crates.io database dump | No | |
| Crates that depend on a listed crate directly | Not measured | No |
Corrections and review history
No correction applies to this entry.
Judgments
A judgment enters only through an approved issue and a merged pull request.
No judgment applies to this entry.