semtools

App Listed

Semantic search and document parsing tools for the command line

Checked · Sources

Downloads
541
Dependents
Not applicable
Stars
1,882
Forks
144
Contributors
5
Commits
173
Latest release
3.0.1 ·

About

From the project README ·

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 format
  • semtools search - Local semantic keyword search using multilingual embeddings with cosine similarity matching and per-line context matching
  • semtools 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 parse subcommand: LlamaIndex Cloud API key
  • For the ask subcommand: 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):

  1. CLI arguments (e.g., --api-key, --model, --base-url)
  2. Config file (~/.semtools_config.json or custom path via -c)
  3. Environment variables (LLAMA_CLOUD_API_KEY, OPENAI_API_KEY)
  4. 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 key
  • base_url: API endpoint (default: "https://api.cloud.llamaindex.ai")
  • num_ongoing_requests: Number of concurrent requests (default: 10)
  • parse_kwargs: Additional parsing parameters
  • check_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 key
  • base_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

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.

semtools beside the projects that share a topic with it
ProjectDownloadsDependentsStarsLatest releaseRuns on (GPU)Native codeLicense
semtools This page App Listed

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

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
ck App Listed

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
tinysearch App Listed

🔍 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
trieve App Listed

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
lnx App Listed Dormant

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
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 days
  • dormancy: last activity 2026-03-11, 243 days ago, E = 365: active
  • rot: oldest unanswered issue 417 days (limit 270), no maintainer reply in 365 days
  • featured: not featured: unknown homebrew_on_request_365d, repology_families, docker_pull_growth_90d
  • listed: 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
Adoption541 binary downloads per release4 not measured
Adoption measurements
SignalValueSourceFetchedCounts
Active dependentsNot measuredYes
New dependents (365 days)Not measuredYes
Peak active dependentsNot measuredYes
Active dependents as a share of the peakNot measuredYes
Binary downloads per release541GitHub releasesYes
MaintenanceLatest human commit: 8 months ago4 not measured
Maintenance measurements
SignalValueSourceFetchedCounts
Latest human commit2026-03-11GitHub repositoryYes
Latest release2026-03-11GitHub releasesYes
First release2025-08-26crates.io database dumpYes
Latest version3.0.1crates.io database dumpNo
Days the oldest outside issue waits for a reply417GitHub repositoryYes
Maintainer replies over 365 days0GitHub repositoryYes
Repository archivedfalseGitHub repositoryYes
Repository gonefalseGitHub repositoryYes
Release commit or manifest in the repotruecrates.io packageNo
Published docsNot measuredYes
Latest release fails cargo checkNot measuredYes
Build check dateNot measuredYes
Build check toolchainNot measuredYes
SecurityNot measured
Security measurements
SignalValueSourceFetchedCounts
Unpatched vulnerabilities past the grace windowNot measuredYes
RustSec unmaintained advisoryNot measuredYes
Deprecation noticeNot measuredYes
Deprecated requirementNot measuredYes
Distribution17 releases, 15 downloads over 30 days6 not measured
Distribution measurements
SignalValueSourceFetchedCounts
Releases17crates.io database dumpNo
Downloads over 30 days15crates.io database dumpNo
Binary downloads over the last 3 releases1625GitHub releasesYes
Homebrew installs on request over 365 daysNot measuredYes
Repology repository familiesNot measuredYes
Docker pull growth over 90 daysNot measuredYes
Docker pulls at the growth baselineNot measuredYes
Every version a prereleasefalsecrates.io database dumpYes
Every version 0.0.xfalsecrates.io database dumpYes
Every version yankedNot measuredYes
Crate deleted from crates.ioNot measuredYes
Repository1,882 stars, 144 forks, 5 contributors, 173 commits. Stars alone never qualify a project.
Repository measurements
SignalValueSourceFetchedCounts
GitHub stars1882GitHub repositoryYes — one part of the repository route
GitHub forks144GitHub repositoryYes — one part of the repository route
Contributors with a GitHub account5GitHub contributorsYes — one part of the repository route
Commits on the default branch173GitHub repositoryNo
Repository's main crate left out of the entrynonecrates.io database dumpYes
Facts that never count
Facts that never count measurements
SignalValueSourceFetchedCounts
LicenseMITcrates.io database dumpNo
Runs on, from listed crates and their direct dependenciesGPU support unknowncrates.io database dumpNo
What shows each backendno dependency or feature matches a backend rowcrates.io database dumpNo
Native code, from listed crates and their dependenciesBinds native code: zstd-sys (feature workspace)crates.io database dumpNo
Python bindings, from direct dependencies of listed cratesNo Python binding crate foundcrates.io database dumpNo
Crates that depend on a listed crate directlyNot measuredNo

Corrections and review history

Report a correction

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.