Local RAG system with MCP server
Project description
vibe_me
Local-first RAG + MCP server for codebases, documentation folders and project context.
Semantic search · Literal grep · Multi-project context · MCP tools · Incremental watcher
What It Is
vibe_me indexes local code and documentation, stores embeddings locally, and exposes search/read tools through an MCP server for coding agents such as OpenCode or any MCP-compatible client.
It is designed so each user runs it locally with their own projects, local index, and configuration.
Features
- Local semantic search over code and docs.
- Literal grep for exact symbols, config keys and errors.
- Multi-project search for combining app repos with local docs.
- SQLite metadata plus local Qdrant vector storage.
- Stable per-project isolation by absolute project path.
- MCP server exposing tools to coding agents.
- Optional incremental watcher to keep indexes fresh.
Requirements
- Python 3.11 or newer.
- Enough disk space for local embeddings and Qdrant data.
- Internet access on first use to download the default embedding model.
- Semantic search uses
fastembed; PyTorch/CUDA is not required.
Install
Recommended for daily use:
pipx install vibe-me
This installs the vibe-me and vibe-me-mcp commands in an isolated environment and makes them available from any project.
If you prefer plain pip, install it into a Python environment that is available wherever your MCP client runs:
pip install vibe-me
Using pyenv
If you use pyenv, install vibe-me into a shared pyenv Python version, not inside each project virtualenv:
pyenv install 3.12
pyenv shell 3.12
python -m pip install --upgrade pip
python -m pip install vibe-me
Then make sure the pyenv shims are available in your shell:
which vibe-me
which vibe-me-mcp
If both commands resolve, you can use them from any project directory:
cd /path/to/any/project
vibe-me index .
vibe-me search "query"
For MCP clients such as OpenCode, the important part is that the client can find vibe-me-mcp. If command: ["vibe-me-mcp"] does not work, use the absolute path returned by:
which vibe-me-mcp
New virtualenvs created from that Python do not normally inherit globally installed packages. That is OK for vibe-me: you do not need to install it inside every project virtualenv. Install it once in a shared tooling Python and call the installed commands from your shell or MCP config.
Indexed data is shared across environments because it is stored outside virtualenvs by default:
~/.local/share/vibe-me
Install From GitHub
For the latest unreleased version:
pip install git+https://github.com/BorisFaj/vibe_me.git
Development Install
For contributing to vibe_me itself:
git clone https://github.com/BorisFaj/vibe_me.git
cd vibe_me
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Quick Start
Index the current project:
vibe-me index .
Run semantic search:
vibe-me search "where is authentication configured"
Run exact literal search:
vibe-me grep "class User"
Show index status:
vibe-me status
Keep an index fresh while you work:
vibe-me watch .
CLI Commands
vibe-me --help
vibe-me index .
vibe-me search "query" --project /path/to/project
vibe-me grep "literal text" --project /path/to/project
vibe-me search-many "query" -p /path/to/project -p /path/to/docs
vibe-me grep-many "literal text" -p /path/to/project -p /path/to/docs
vibe-me projects
vibe-me projects --json
vibe-me update-agents
vibe-me update-agents --target claude
vibe-me update-agents --target gemini
vibe-me mcp-stats
vibe-me mcp-log
vibe-me rename-project --project /path/to/project --name docs
vibe-me remove-project --project /path/to/project
vibe-me status --all
vibe-me watch .
Agent Instructions
Add a managed vibe-me MCP usage section to an agent instruction file:
vibe-me update-agents
By default this updates AGENTS.md in the current directory. It creates the file if needed and does not duplicate the section if it already exists.
Supported presets:
vibe-me update-agents --target agents
vibe-me update-agents --target claude
vibe-me update-agents --target gemini
These map to:
| Target | File |
|---|---|
agents |
AGENTS.md |
claude |
CLAUDE.md |
gemini |
GEMINI.md |
Use a custom file with:
vibe-me update-agents --file .github/copilot-instructions.md
Replace an existing managed section with the latest template:
vibe-me update-agents --force
Preview without writing:
vibe-me update-agents --dry-run
Manage Indexed Projects
List indexed projects:
vibe-me projects
vibe-me projects --json
Rename a project display name without changing its project_id:
vibe-me rename-project --project /path/to/project --name docs
If the current name is unique, you can also rename by name:
vibe-me rename-project --project-name old-name --name new-name
Renaming updates both SQLite metadata and Qdrant payloads, so future search results use the new name immediately.
Remove a project from the local index:
vibe-me remove-project --project /path/to/project
This removes SQLite metadata and Qdrant vectors for that project. It does not delete files from disk. Use --yes to skip the confirmation prompt.
MCP Usage Analytics
vibe_me records local MCP usage metadata in:
~/.local/share/vibe-me/usage.sqlite
It tracks tool calls, durations, result counts and estimated context savings. The estimate compares the context returned by vibe-me with an approximate baseline of reading the full files that search/grep/read results came from.
Token counts are estimates:
tokens ~= characters / 4
vibe_me cannot know the exact final LLM prompt or provider-side token usage, so these numbers should be read as local context-efficiency estimates, not billing-accurate token counts.
Show summary stats:
vibe-me mcp-stats
vibe-me mcp-stats --json
Show recent calls:
vibe-me mcp-log
vibe-me mcp-log --limit 50
vibe-me mcp-log --json
Clear local usage analytics:
vibe-me mcp-clear-stats
By default, usage analytics stores metadata and counts, not full returned file contents.
Local Data
By default, vibe_me stores its local index in:
~/.local/share/vibe-me
That directory contains SQLite metadata and local Qdrant vector storage. It is user-local data and should not be committed to your projects.
Override it with:
export VIBE_DATA_DIR=/path/to/vibe-me-data
Or override individual paths:
export VIBE_QDRANT_PATH=/path/to/qdrant
export VIBE_SQLITE_PATH=/path/to/index.sqlite
Configuration
Supported environment variables:
| Variable | Default | Purpose |
|---|---|---|
VIBE_DATA_DIR |
~/.local/share/vibe-me |
Base local storage directory |
VIBE_QDRANT_PATH |
$VIBE_DATA_DIR/qdrant |
Local Qdrant storage path |
VIBE_SQLITE_PATH |
$VIBE_DATA_DIR/index.sqlite |
SQLite metadata path |
VIBE_COLLECTION_NAME |
vibe_code |
Qdrant collection name |
VIBE_EMBEDDING_MODEL |
BAAI/bge-small-en-v1.5 |
FastEmbed model |
VIBE_DEFAULT_PROJECT |
current working directory | Default MCP project |
VIBE_AUTO_WATCH |
0 |
Start watcher automatically with MCP server |
See .env.example for a copyable template.
Default indexing excludes common dependency, build, cache and report folders such as .git, node_modules, .next, .vercel, coverage, playwright-report, dist and build. It also excludes large lock/report files such as package-lock.json, pnpm-lock.yaml, yarn.lock, coverage.xml and lcov.info.
MCP Server
Start the MCP server manually:
vibe-me-mcp
The server runs over stdio. Normally your MCP-compatible client starts it automatically.
The MCP server exposes tools for:
search_codebasegrep_codebaseread_filerefresh_indexindex_statussearch_many_codebasesgrep_many_codebaseslist_projectsremove_projectrename_projectusage_statsdefault_projectping
OpenCode Setup
Use examples/opencode.json as a template for your user config, commonly:
~/.config/opencode/opencode.json
Minimal OpenCode MCP config:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"vibe-me": {
"type": "local",
"command": ["vibe-me-mcp"],
"enabled": true,
"environment": {
"VIBE_AUTO_WATCH": "0"
}
}
},
"permission": {
"tool": {
"vibe-me_*": "allow"
}
}
}
This works when vibe-me-mcp is in the PATH visible to OpenCode. If you installed it into a shared pyenv Python and OpenCode cannot find it, use the absolute path returned by:
which vibe-me-mcp
Example with an explicit pyenv-style path:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"vibe-me": {
"type": "local",
"command": [
"/path/to/pyenv/versions/3.12.3/bin/vibe-me-mcp"
],
"enabled": true,
"environment": {
"VIBE_AUTO_WATCH": "0"
}
}
},
"permission": {
"tool": {
"vibe-me_*": "allow"
}
}
}
VIBE_AUTO_WATCH=0 is the safest default: the MCP server will not start indexing automatically when your client opens. Run indexing explicitly with:
vibe-me index .
or keep a project fresh from a separate terminal with:
vibe-me watch .
Use VIBE_AUTO_WATCH=1 if you want the MCP server to start a background watcher automatically for the default project.
Do not put shell placeholders such as ${cwd} or $PWD directly in opencode.json; OpenCode passes environment values literally. If your client does not launch MCP servers from the project directory, set a default project before launching it:
export VIBE_DEFAULT_PROJECT="$PWD"
opencode
Optional launcher:
#!/usr/bin/env bash
set -euo pipefail
export VIBE_DEFAULT_PROJECT="$PWD"
exec opencode "$@"
Project Identity
Each indexed folder is treated as a separate project.
project_id = absolute resolved project path
project_name = folder name unless overridden
Critical operations filter by project_id, so projects with similar names remain isolated.
Development
Install development dependencies:
pip install -e ".[dev]"
Run checks:
ruff check .
mypy rag mcp_server
pytest
python -m build
python -m twine check dist/*
Security Notes
vibe_me stores indexed chunks locally. If you index files containing secrets, those contents may be present in your local SQLite/Qdrant data. Keep your data directory private and do not commit it.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vibe_me-0.1.1.tar.gz.
File metadata
- Download URL: vibe_me-0.1.1.tar.gz
- Upload date:
- Size: 33.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9365a74fc372b7fa0c699d2614ae948ebc6bd71646bbddbe7d227b90b5b10e0a
|
|
| MD5 |
8c3365634baa32f6cf0a0b0f5b4cac37
|
|
| BLAKE2b-256 |
d99a113813c962961b93cc0e5bc10d02141243438fd2c7e7b7536131706cd7ed
|
Provenance
The following attestation bundles were made for vibe_me-0.1.1.tar.gz:
Publisher:
publish.yml on BorisFaj/vibe_me
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vibe_me-0.1.1.tar.gz -
Subject digest:
9365a74fc372b7fa0c699d2614ae948ebc6bd71646bbddbe7d227b90b5b10e0a - Sigstore transparency entry: 1655966818
- Sigstore integration time:
-
Permalink:
BorisFaj/vibe_me@40752c66c9322db8dbbbc1b183bf18f67d116a89 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/BorisFaj
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@40752c66c9322db8dbbbc1b183bf18f67d116a89 -
Trigger Event:
push
-
Statement type:
File details
Details for the file vibe_me-0.1.1-py3-none-any.whl.
File metadata
- Download URL: vibe_me-0.1.1-py3-none-any.whl
- Upload date:
- Size: 28.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e69fcc032b1408efb7f16f0f2560da51d651586ce470459158c141bdc49f04d
|
|
| MD5 |
20203298d0319ecfef5b5b41f492b14c
|
|
| BLAKE2b-256 |
7392ad7351021a51fa35e63238188fd2dc38016693a34708a585c5d44bbf15ba
|
Provenance
The following attestation bundles were made for vibe_me-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on BorisFaj/vibe_me
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vibe_me-0.1.1-py3-none-any.whl -
Subject digest:
7e69fcc032b1408efb7f16f0f2560da51d651586ce470459158c141bdc49f04d - Sigstore transparency entry: 1655967067
- Sigstore integration time:
-
Permalink:
BorisFaj/vibe_me@40752c66c9322db8dbbbc1b183bf18f67d116a89 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/BorisFaj
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@40752c66c9322db8dbbbc1b183bf18f67d116a89 -
Trigger Event:
push
-
Statement type: