Multi-repo code indexer with BM25 search. Claude Code integration built-in.
Project description
workspace-map
Multi-repo code indexer with BM25 search.
Index all your repos into one searchable index. Find code by natural language, not just exact strings. Optional Claude Code integration auto-detected.
Features
- Multi-repo indexing — Dart, Python, JavaScript/TypeScript, Shell, Markdown; language auto-detected per repo
- BM25 ranking — proper information retrieval scoring, not grep; documents ranked by relevance
- Symbol extraction — classes, functions, methods, enums, constants extracted per language and included in search scoring
- Incremental updates — mtime + size cache skips unchanged files;
wmap updatere-indexes only what changed - Natural language search — camelCase splitting (
billingService→billing service), synonym expansion, stop word filtering - Claude Code integration — auto-detects
~/.claude/; indexes hooks, skills, plans, memory files, rules, agents, commands, and session transcripts - LLM reranking — optional semantic reranking via Anthropic API (requires
pip install workspace-map[ai])
Quick Start
pip install workspace-map
# Initialize config in the current directory
wmap init
# Build the index from scratch
wmap rebuild
# Search
wmap find "authentication service"
wmap find "database migration handler"
wmap find "hook that fires before tool use"
wmap init writes a workspace-map.yaml in the current directory populated
with git repos auto-discovered up to 2 directories deep. Edit it to add names,
descriptions, and synonyms, then run wmap rebuild.
CLI Reference
| Command | Description |
|---|---|
wmap find "<query>" |
Search the index; returns ranked results with file paths |
wmap find "<query>" --top N |
Limit results to top N (default: 10) |
wmap find "<query>" --category code |
Filter by category: code, hook, skill, memory, plan, script, rule, session |
wmap find "<query>" --repo myrepo |
Filter to a single repo |
wmap init |
Write a starter workspace-map.yaml with auto-discovered repos |
wmap rebuild |
Full re-index of all repos and CC infra |
wmap rebuild --force |
Re-index all files, ignoring mtime cache |
wmap rebuild --verbose |
Print each file as it is indexed |
wmap update |
Incremental update — re-index only changed files |
wmap repos |
List all repos in the current config |
wmap hooks |
List all indexed Claude Code hooks |
wmap memory |
List all indexed memory files |
wmap skills |
List all indexed skills |
wmap plans |
List all indexed plan files |
wmap scripts |
List all indexed scripts |
wmap sessions |
List all indexed session transcripts |
wmap dirs |
List all directory-level entries in the index |
wmap stats |
Show index statistics: entry counts per category, index size, last build time |
wmap consolidate |
Merge duplicate entries and prune stale paths from the index |
wmap install-hook |
Install the PreToolUse Glob hook for Claude Code |
All commands accept --config <path> to use a config file other than
the default. Run wmap <command> --help for full flag reference.
Configuration
workspace-map looks for workspace-map.yaml in the current directory, then
~/.config/workspace-map/workspace-map.yaml.
repos:
- path: ~/projects/myapp
name: myapp
description: "Flutter mobile app — screens, widgets, services, state"
- path: ~/projects/myapp-backend
name: backend
description: "Cloud Functions — HTTP endpoints, database triggers"
# Additional non-git directories to index
extra_dirs:
- path: ~/.claude/skills
name: cc-skills
description: "Claude Code skill scripts"
# Synonym expansion — terms that map to each other in search
synonyms:
- [auth, authentication, login, signin]
- [purchase, in_app_purchase, subscription, billing]
# Patterns to exclude (relative to repo root)
exclude:
- "**/.dart_tool/**"
- "**/build/**"
- "**/*.g.dart"
# Override index location (default: ~/.cache/workspace-map/index.json)
# index_path: ~/my-index.json
Config keys
| Key | Default | Description |
|---|---|---|
repos[].path |
required | Path to git repo (supports ~) |
repos[].name |
required | Short identifier used in search output |
repos[].description |
"" |
Added to search scoring for the repo root |
repos[].lang |
auto-detected | Force language: dart, py, js, sh, etc. |
repos[].glob |
auto | Override file glob, e.g. lib/**/*.dart |
extra_dirs |
[] |
Additional directories indexed as a flat file list |
synonyms |
[] |
Lists of terms that expand to each other at query time |
exclude |
[] |
Glob patterns to skip (matched against relative paths) |
index_path |
~/.cache/workspace-map/index.json |
Where to write the index |
claude_code_enabled |
"auto" |
"auto", "true", or "false" |
Claude Code Integration
When ~/.claude/ is found, workspace-map automatically indexes Claude Code
infrastructure files alongside your source code:
| Category | Source | What gets indexed |
|---|---|---|
hook |
~/.claude/hooks/ |
Hook scripts with their wiring events parsed from settings.json |
skill |
~/.claude/skills/ |
Skill directories; description from SKILL.md frontmatter |
plan |
~/.claude/plans/ |
Plan markdown files |
memory |
~/.claude/projects/*/memory/ |
Per-project memory files; typed as feedback, reference, project, or main |
rule |
~/.claude/rules/ |
Rule markdown files |
script |
~/.claude/scripts/ |
Utility scripts with symbol extraction |
agent |
~/.claude/agents/ |
Agent definition files |
command |
~/.claude/commands/ |
Slash command definitions |
session |
~/.claude/projects/*/ |
Session transcripts (.jsonl) with title and date extracted |
Set claude_code_enabled: "false" in config to disable CC indexing entirely.
PreToolUse hook
wmap install-hook installs a PreToolUse hook that blocks exploratory Glob
calls and reminds to use wmap find instead. It writes the hook to
~/.claude/hooks/workspace-map-reminder.py and registers it in
~/.claude/settings.json under the Glob matcher.
wmap install-hook # install and register
wmap install-hook --dry-run # preview what would be installed
The hook distinguishes exact extension globs (**/*.dart, src/**/*.tsx)
from exploratory patterns and only blocks the latter.
Adding Language Support
Built-in extractors live in src/workspace_map/extractors/. Each module
handles one language.
-
Create
src/workspace_map/extractors/<lang>.pywith two functions:def extract_symbols_<lang>(content: str) -> list[dict]: """Return dicts with 'kind' and 'name' keys (optionally 'parent').""" ... def purpose_<lang>(path: str, content: str) -> str: """Return a short description of the file's purpose.""" ...
kindvalues follow the existing convention:"class","function","method","enum","mixin","extension","const". -
Self-register at module bottom:
from workspace_map.extractors import register register("<lang>", extract_symbols_<lang>, purpose_<lang>)
-
Add the auto-import to
src/workspace_map/extractors/__init__.py:from workspace_map.extractors import <lang> # noqa: E402, F401
-
Add file extension mapping in
src/workspace_map/config.py(_LANG_EXTENSIONSand_LANG_GLOBS). -
Add tests in
tests/test_extractor_<lang>.pyand updateREADME.md.
See src/workspace_map/extractors/dart.py for a complete reference
implementation with class/method/constant extraction and doc-comment
purpose inference.
License
MIT — see LICENSE.
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 workspace_map-0.1.0.tar.gz.
File metadata
- Download URL: workspace_map-0.1.0.tar.gz
- Upload date:
- Size: 52.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d3ffde35ae653da84da88762cc4a6951897688aba03278f76e1251c368f5e2d
|
|
| MD5 |
031379be572df73b94152e8828f189bc
|
|
| BLAKE2b-256 |
bc29953467c12f1935d25bed2d6ed6799797c4b0156b7d29ddbb1539d86ba48c
|
Provenance
The following attestation bundles were made for workspace_map-0.1.0.tar.gz:
Publisher:
publish.yml on Evey-Vendetta/workspace-map
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
workspace_map-0.1.0.tar.gz -
Subject digest:
9d3ffde35ae653da84da88762cc4a6951897688aba03278f76e1251c368f5e2d - Sigstore transparency entry: 1155039882
- Sigstore integration time:
-
Permalink:
Evey-Vendetta/workspace-map@febd46d3ec3701f1b8b8bf4301a3bc3222903721 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Evey-Vendetta
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@febd46d3ec3701f1b8b8bf4301a3bc3222903721 -
Trigger Event:
push
-
Statement type:
File details
Details for the file workspace_map-0.1.0-py3-none-any.whl.
File metadata
- Download URL: workspace_map-0.1.0-py3-none-any.whl
- Upload date:
- Size: 43.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b54e01d07adb8ef4c6d6e103b8de47f975cc3363abfc031aaaf7b527b68d874
|
|
| MD5 |
94d9d4d99655e02539994b340e690f87
|
|
| BLAKE2b-256 |
ee5bffa25c0c8c9cfaacd1faa9b6dc791ef00eaf257c5397d134662858dbf7ab
|
Provenance
The following attestation bundles were made for workspace_map-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on Evey-Vendetta/workspace-map
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
workspace_map-0.1.0-py3-none-any.whl -
Subject digest:
2b54e01d07adb8ef4c6d6e103b8de47f975cc3363abfc031aaaf7b527b68d874 - Sigstore transparency entry: 1155039884
- Sigstore integration time:
-
Permalink:
Evey-Vendetta/workspace-map@febd46d3ec3701f1b8b8bf4301a3bc3222903721 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Evey-Vendetta
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@febd46d3ec3701f1b8b8bf4301a3bc3222903721 -
Trigger Event:
push
-
Statement type: