simargl
Semantic Index: Map Artifacts, Retrieve from Git Log
Task-to-code retrieval for software projects — given a description of a change, finds the files and modules it is likely to touch, by semantic search over the project's past tasks, commits and code, with local embedding models and no LLM.
What it does
simargl builds vector indexes of a project:
- units — the past tasks (or commits) of the project, each linked to the files it changed, from the SQLite database that mokosh gathers;
- files — the code and documents themselves, cut into chunks.
A new task description is embedded the same way and compared with them. The answer is the files and modules most likely to change, the similar past tasks behind them, and, if asked, their diffs.
Around that it offers:
- search in several modes: past tasks, code chunks, tasks averaged per file, and a query refined with the words of similar commits;
- rrf — several indexes merged by rank;
- retrieve — the matching text, ready to put into an LLM's context;
- blackhole — detect files that answer almost any query (generated files, changelogs) and push them down;
- ui — the same in the browser, plus Triangulation: one task asked of simargl, gamayun and svitovyd at once;
- an MCP server, so AI agents can search the history and the code themselves.
Embeddings run through Ollama, any OpenAI-compatible local server, or sentence-transformers. The index is a few plain files (int8 vectors and SQLite), and nothing leaves the machine.
Statement of need
Most of what a developer needs to know about a new task is in the project's history: someone has done something similar before, and the files they changed are where the new change will go. Plain text search finds only the exact words, and a task is rarely written in the words of the code. Code assistants that read the whole repository need a large model and send the code to it.
simargl searches the history by meaning, with small embedding models that run on a CPU, and points to files, not only to past tasks. It is meant for:
- developers who need to find where a task leads in a large or unfamiliar code base;
- AI coding agents, including ones on small local models, that need the right files before they read anything (through the MCP server or the command line);
- researchers in software engineering who study task-to-code retrieval and change impact and need a reproducible retrieval baseline over real project histories.
Install
pip install simargl # core + web UI: numpy, Flask, mokosh — no torch
pip install "simargl[torch]" # + local models via sentence-transformers (bge-small, bge-large, jina-code)
pip install "simargl[mcp]" # + the MCP server (simargl serve, simargl-mcp)
pip install "simargl[http]" # + MCP over HTTP/SSE (remote agents, LAN)
pip install "simargl[postgres]" # + the PostgreSQL / pgvector backend
pip install "simargl[gradio]" # + the older Gradio UI (simargl ui --gradio)
pip install "simargl[all]" # torch + MCP + HTTP
Python 3.10+. The core has no torch, so it installs anywhere Python runs; the embedding model can run in Ollama on the same machine or another one.
Quick start
cd my-project # a git clone
mokosh init && mokosh ingest # past tasks + commits -> units.db (installed with simargl)
simargl download # pull the default embedding model into Ollama
simargl index units units.db # the past tasks
simargl index files . # the code
simargl status
simargl search "Login fails after the session expires"
simargl search "Login fails after the session expires" --mode file
simargl ui # http://127.0.0.1:8099/
Both indexes go to .simargl/default/ in the current folder. To refresh: mokosh ingest, then
simargl index units again; simargl index files . re-embeds only the files changed since the
last run.
Commands
| Command | What it does |
|---|---|
simargl index units DB [--last N] [--mode auto|tasks|commits] |
Index the past tasks (or commits) of a mokosh database |
simargl index files PATH [--full] [--chunk-size N] |
Index code and documents (incremental; --full re-embeds everything) |
simargl search QUERY [--mode task|file|aggr|refine] |
Files, modules and similar past tasks for a query |
simargl rrf QUERY --sources task:default,file:code |
Several indexes or modes merged by reciprocal rank fusion |
simargl retrieve QUERY |
The matching text, ready for an LLM's context |
simargl blackhole [--method coverage_float] [--list] |
Detect files that answer almost any query |
simargl status |
What an index holds |
simargl vacuum |
Reclaim the space of deleted vectors |
simargl download [--model M] |
Get an embedding model ready |
simargl ui [--port 8099] [--host 0.0.0.0] [--root FOLDER] |
The web UI |
simargl serve [--http --port 8765] |
The MCP server (also simargl-mcp) |
simargl about |
Version and authorship |
Common options: --project P keeps several indexes side by side (.simargl/<P>/), --model M
picks the embedding model, --store-dir DIR puts the store elsewhere, --format json|paths|modules
changes the output of search, --diff adds the diffs of the past tasks, --top-n / --top-k set
how many files and past tasks to return.
Search modes
| Mode | How it finds files |
|---|---|
task (default) |
finds the most similar past tasks and returns the files they changed (--sort rank by similarity, --sort freq by how many of them changed the file) |
file |
compares the query with the chunks of the code itself |
aggr |
compares the query with every file's average over the past tasks that changed it |
refine |
expands the query with words from the most similar commits, then searches again |
--last N indexes only the N most recent tasks: in a project developed for years, recent work
describes today's code better than the whole history.
Example
The output below comes from a small demo shop project: 300 synthetic tasks built from a few dozen titles, and 13 Java files in the modules auth, checkout, billing and catalog.
$ simargl search "Customers are charged twice when two discount codes are used" --top-n 3 --top-k 5 --sort freq
Query: Customers are charged twice when two discount codes are used mode=task sort=freq
Files:
4.000 checkout/src/PriceCalculator.java [checkout]
1.000 checkout/src/DiscountRule.java [checkout]
Modules:
4.000 checkout
Similar units:
[0.766] SHOP-194 — Two discounts applied to one item
[0.766] SHOP-236 — Two discounts applied to one item
[0.766] SHOP-141 — Two discounts applied to one item
[0.766] SHOP-217 — Two discounts applied to one item
[0.766] SHOP-103 — Two discounts applied to one item
The five most similar past tasks were found, and the files they changed are counted: four of them
changed PriceCalculator.java, one DiscountRule.java.
Embedding models
New indexes use ollama://granite-embedding:30m (63 MB, 384 dimensions) unless --model says
otherwise. An index records its model in meta.json, and every search uses that model again.
# Ollama: uses what is pulled into Ollama, on this machine or another
--model ollama://granite-embedding:30m # default
--model ollama://nomic-embed-text
--model ollama://nomic-embed-text@192.168.1.10 # Ollama on another machine
# OpenAI-compatible local servers: LM Studio, llama.cpp, LiteLLM, Jan, Koboldcpp
--model openai://localhost:1234/nomic-embed-text # LM Studio
--model openai://localhost:8080/all-minilm # llama.cpp server
# sentence-transformers (needs simargl[torch]); usually the fastest for indexing a large history
--model bge-small # 384 dimensions
--model bge-large # 1024 dimensions, more RAM and disk
openai:// means an OpenAI-compatible API on your own machine: no cloud and no API key.
simargl download --model M gets a model ready (pulls it into Ollama, or downloads a local one).
Web UI
simargl ui # http://127.0.0.1:8099/
simargl ui --host 0.0.0.0 # reachable from other devices on the LAN
simargl ui --root ~/projects # look for .simargl stores under this folder
The UI lists the .simargl stores under the folder it was started in and remembers every store
opened there or indexed by the CLI (~/.simargl/stores.json). One store and one index are worked on
at a time.
- Search: every mode and parameter; files with score bars, modules, the similar past tasks with their diffs, and the answer as a map: the similar tasks and the files they changed, so the files many of them share stand out.
- Triangulation: one task asked of three tools at once: simargl (similar past tasks), gamayun (words that significantly lead to files, files that change together) and svitovyd (identifiers of the task that the code defines). Their answers are merged by equal-weight reciprocal rank fusion; each file shows its rank in every tool, and a strip shows how many files all three, two or one of them named. With a svitovyd map, a path the history remembers but today's code no longer has is matched to the moved file or marked not in today's code. With a gamayun project, a file that changes with at least 1 % of all past tasks (a messages file, the build) is marked a companion: often part of a change, rarely its core.
- RRF: several sources (
task:default,file:code, …) merged by rank. - Retrieve: the matching text, ready for an LLM.
- Blackholes: files that answer almost any query.
- Index: the embedding models (what each Ollama host has, pull a model), index the history or the code, vacuum.
- Status: what the index holds, and the whole index as a ZIP to search it on another machine without re-indexing.
The UI has 8 colour themes and 6 languages (English, Ukrainian, German, French, Spanish,
Portuguese). The task database itself is set up in mokosh ui.
MCP server
simargl-mcp # stdio, for local agents
simargl-mcp --http --port 8765 # HTTP/SSE, for remote agents and the LAN
simargl-mcp --store-dir /path/to/my-project/.simargl --project-id myproj
| Tool | What it does |
|---|---|
find |
files, modules and similar past tasks for a query (mode, sort, top_n, top_k, include_diff) |
rrf |
several sources merged by rank |
retrieve |
the matching text for an LLM's context |
index_files, index_units |
build or update an index |
status, vacuum, blackhole |
the index itself |
embedding, distance |
the vector of a text or file, and the cosine similarity of two |
The first connection takes 30–60 seconds while the embedding model loads; later calls are fast.
Pass --store-dir with an absolute path, so the server finds .simargl/ whatever folder the agent
starts it in. With --project-id set, the tools need no project_id argument.
Setup per agent
Claude Desktop (%APPDATA%\Claude\claude_desktop_config.json on Windows,
~/Library/Application Support/Claude/claude_desktop_config.json on macOS) and Claude Code
(~/.claude/settings.json):
{
"mcpServers": {
"simargl": {
"command": "simargl-mcp",
"args": ["--store-dir", "/path/to/my-project/.simargl", "--project-id", "myproj"]
}
}
}
Claude Code can also add it from a session:
/mcp add simargl simargl-mcp --store-dir /path/to/my-project/.simargl --project-id myproj
OpenCode (~/.config/opencode/config.json):
{ "mcp": { "simargl": { "command": ["simargl-mcp"], "cwd": "/path/to/my-project" } } }
OpenAI Codex CLI (~/.codex/config.yaml):
mcp_servers:
simargl:
command: simargl-mcp
cwd: /path/to/my-project
Cursor (.cursor/mcp.json in the project, or ~/.cursor/mcp.json):
{ "mcpServers": { "simargl": { "command": "simargl-mcp", "cwd": "${workspaceFolder}" } } }
Windsurf (~/.codeium/windsurf/mcp_settings.json):
{ "mcpServers": { "simargl": { "command": "simargl-mcp", "cwd": "/path/to/my-project" } } }
A remote server (any agent that takes a URL):
{ "mcpServers": { "simargl": { "url": "http://192.168.1.42:8765/sse" } } }
Any other MCP client: the command is simargl-mcp, and its working folder (or --store-dir)
is where .simargl/ lives.
With 1bcoder
Start 1bcoder in the project folder, so the server finds
.simargl/ there:
/mcp connect simargl simargl-mcp
/mcp connect simargl simargl-mcp --project-id myproj
/mcp connect simargl simargl-mcp --cwd /path/to/other-project --project-id other
/mcp tools simargl
A typical session:
/mcp call simargl/find {"query": "make the author field longer in the Book class", "mode": "file"} -> find_result
/var set find_files matches
/read {{find_files}}
make the author field longer in the Book class
/patch models.py code
Running on another machine or a phone
The index, the embedding model, the MCP server and the web UI can all run on another machine on the LAN: a server, a Raspberry Pi, or an Android phone with Termux. The laptop only opens the browser or connects an agent.
# on the phone (Termux)
pkg update && pkg install python git ollama
ollama serve &
ollama pull nomic-embed-text
pip install "simargl[http]"
simargl index units /sdcard/data/units.db --project myproj --model ollama://nomic-embed-text
simargl index files /sdcard/repos/my-project --project myproj --model ollama://nomic-embed-text
nohup simargl-mcp --http --port 8765 > ~/.simargl-mcp.log 2>&1 &
simargl ui --host 0.0.0.0
# on the laptop
/mcp connect simargl http://192.168.1.42:8765/sse # 1bcoder
http://192.168.1.42:8099/ # the web UI
| Component | Server / phone | Laptop |
|---|---|---|
Index (.simargl/), embedding model, MCP server, web UI |
yes | — |
| Agent / LLM (1bcoder, Claude, …) | — | yes |
| Source files | for indexing | for editing |
PostgreSQL + pgvector backend
For very large indexes, or for search through an HNSW index instead of a linear scan:
pip install "simargl[postgres]"
psql -c "CREATE EXTENSION IF NOT EXISTS vector;"
simargl index units units.db --backend postgres --db-url postgresql://user:pass@localhost/simargl
simargl index files . --backend postgres --db-url postgresql://user:pass@localhost/simargl
simargl-mcp --backend postgres --db-url postgresql://user:pass@localhost/simargl
| numpy (default) | postgres | |
|---|---|---|
| Install | nothing extra | psycopg2 + pgvector |
| Search | linear scan | HNSW (sub-linear) |
| Comfortable size | up to ~500k chunks | millions of chunks |
| Concurrent writes | no | yes |
| Phone / Termux | yes | harder |
Python API
from simargl.searcher import search, get_chunk_text
r = search("Login fails after the session expires", mode="task", top_n=10, top_k=10)
r["files"] # [{"path", "score", "module"}, ...]
r["modules"] # [{"module", "score"}, ...]
r["units"] # the similar past tasks: unit_id, text_preview, similarity, files (+ diff with include_diff=True)
r = search("Login fails after the session expires", mode="file", top_n=5)
for f in r["files"]:
print(f["path"], f["score"], get_chunk_text(f["path"], f["chunk_n"])) # the chunk that matched
project_id, store_dir, backend_type and db_url select the index, as on the command line.
Tests
git clone https://github.com/szholobetsky/simargl
cd simargl
pip install -e .
pip install pytest
pytest
Support
The project is on GitHub: github.com/szholobetsky/simargl. Questions, bug reports and suggestions go to its issues.
Part of the SIMARGL toolkit
simargl is one of ten tools that together form an intellectual development support system:
| Tool | Role |
|---|---|
| simargl | Task-to-code retrieval — given a task description, finds which files and modules are likely affected, using semantic similarity over git history |
| svitovyd | Project map — scans any codebase and produces a structural map of definitions and cross-file dependencies; queried from the CLI, a web UI with a layered map, or an MCP server |
| 1bcoder | AI coding assistant for small local models — surgical context management, agents, parallel inference, proc scripts |
| yasna | Session memory — indexes conversations from all AI agents so you can find what was discussed, when, and where |
| radogast | Context drift monitor — measures how far an AI agent's conversation has drifted from the original task |
| vyrii | Local AI web UI — chat, translate, web research, RAG and file management in the browser (Flask; Gradio optional); powered by Ollama or any OpenAI-compatible backend |
| syryn | Bluetooth identity beacon for headless devices — the device's IP is its Bluetooth name; hostname, mDNS and network interfaces on request |
| alkonost | Browser cockpit for 1bcoder's flows — the deepagent_* spec pipeline (plan tree → specs → task board) and the glossary (build, browse, search), tuned for small local models |
| gamayun | Statistical ontology without an LLM — builds triples of terms, identifiers, files and modules from task history or a folder of documents and code; every triple carries its significance test |
| mokosh | Dataset gathering — commits of a git repository and the tasks of its tracker (Jira, GitHub, GitLab, YouTrack) in one SQLite database that the other tools read |
- simargl finds the code related to a task by vector search over the task history (embeddings).
- svitovyd answers: how is the code structured and what depends on what?
- 1bcoder answers: how do I work with local models efficiently?
- yasna answers: where did I already discuss this?
- radogast answers: is the AI agent still on track toward the goal?
- vyrii answers: how do I access all of this through a browser?
- syryn answers: what is the address of this headless device?
- alkonost answers: how do I turn one task description into a reviewed, working plan — and see the project's glossary — without a big model or a big context window?
- gamayun finds the code related to a task through an ontology of significant links between words, files and modules (no LLM).
- mokosh prepares the initial dataset from version control and the issue tracker.
Together they cover the full development loop: understand the codebase, find relevant history, work with AI locally, remember what was decided, and verify the context stays on target.
The name comes from Slavic mythology. Simargl (Симаргл) is a winged guardian spirit — a fiery dog with wings, protector of seeds and the earth, messenger between the heavens and the world of men. A fitting name for a tool that retrieves the seeds of code most relevant to any task.
License
MIT. See LICENSE.
About
(c) 2026 Stanislav Zholobetskyi, Oleh Andriichuk
Institute for Information Recording, National Academy of Sciences of Ukraine, Kyiv
PhD research: «Intelligent Technology for Software Development and Maintenance Support»
Metadata
Release files for simargl 0.1.10
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| simargl-0.1.10.tar.gz | 116.6 kB | Without provenance | Details for simargl-0.1.10.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| simargl-0.1.10-py3-none-any.whl | Python 3 | none | any | Details for simargl-0.1.10-py3-none-any.whl |
Total release size: 238.8 kB
Release files / simargl-0.1.10.tar.gz
| Download URL | simargl-0.1.10.tar.gz |
|---|---|
| Size | 116.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
62e22da68b9a98a0443f3229eba6686ee8086307aec77250f9743996c79b20cf
|
|
BLAKE2b-256 checksum How to use checksums |
b05129d9fed56ff66394d62b68e02f1b70cb7a4eaeaf54508340d50d0897f14a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.9
|
Release files / simargl-0.1.10-py3-none-any.whl
| Download URL | simargl-0.1.10-py3-none-any.whl |
|---|---|
| Size | 122.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2dcbe604990c2667b85936b8adb027ae5117094540ba1697f883e9f18f8d6f5e
|
|
BLAKE2b-256 checksum How to use checksums |
dea7a01ee82a342d2091b81c62f4e92cea77f87fbd6a58e75a44e59d5fe06c1f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.9
|
Security for simargl 0.1.10
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.