Skip to main content

kosha (कोश) — a treasury of your repo and environment context for coding agents. FTS5 + vector search + call graph, no LLMs required.

Project description

kosha

kosha (कोश) — a treasury of repo and installed-package context for humans and coding assistants.

Persistent knowledge of your codebase and installed packages — FTS5 + vector search + call graph, merged with Reciprocal Rank Fusion. Each result includes the code snippet, callers, callees, and PageRank. No LLMs required.

Install

kosha is a dev dependency — it indexes code at development time so AI coding assistants can search it. It does not ship with your application.

uv add --dev koshas        # uv (recommended)
pip install --group dev koshas

Setup (one-time per project)

Kosha(install_skill=True)   # writes .agents/skills/kosha/SKILL.md

Commit .agents/skills/kosha/SKILL.md so every contributor — human and AI — picks up the skill automatically.

Sync (once per session, re-run when things change)

k = Kosha()                                       # auto-detects git repo root
k.sync(pkgs=['fasthtml', 'fastcore', 'litesearch'])

Subsequent calls are incremental — only changed files and new package versions are re-indexed. Re-run k.sync() whenever the env or repo changes materially: after uv add / pip install / version bumps, after pulling or merging significant code changes, or when results look stale. Calling it too often is harmless; calling it too rarely silently feeds the agent stale context. Indexes:

  • .kosha/code.db — repo chunks + embeddings (project-local)
  • .kosha/graph.db — call graph (project-local)
  • $XDG_DATA_HOME/kosha/env.db — installed packages (shared across repos)

The four-step workflow

The high-value pattern: inventory → disambiguate → narrow → trace. Skip steps that don’t apply (table at the end of this section).

Step 1 — Inventory

Query the indexes directly to see what’s installed and what each package exposes. pkgs_in_env, dep_stack, and public_api are all indexed SQLite reads, sub-second on typical envs — no cache file is needed. (A markdown cache without invalidation goes silently stale when packages change, and the reads are already fast enough that no cache is earning its keep.)

pkgs   = k.pkgs_in_env(pyproject=True)                              # [{name, version}, ...]
layers = k.dep_stack(seeds=[p['name'] for p in pkgs], depth=2)      # BFS, by coupling
for p in pkgs:
    api = k.public_api(p['name'], limit=30)                         # public surface + docstrings
    # use `pkgs`, `layers`, `api` directly — no intermediate file needed

Step 2 — Disambiguate

If the task names a domain (“payments”, “ui”, “http client”) and several installed packages could plausibly serve it, ask the user which to use before searching deeper. env_context() auto-detects package names in plain query tokens, so this call is cheap.

hits = k.env_context('toast notification', limit=30)         # cheap, no graph enrichment
by_pkg = {}
for r in hits: by_pkg.setdefault(r['metadata'].get('package'), []).append(r)
candidates = sorted(by_pkg, key=lambda p: -len(by_pkg[p]))[:4]
# If multiple candidates have comparable hit counts, present them and wait for the user.

Step 3 — Narrow

Once the package set is known, run context() once with a package: filter. The result is already enriched with pagerank, callers, callees, co_dispatched — do not loop and call ni() afterwards.

results = k.context('toast notification package:monsterui', limit=10)
for r in results:
    m = r['metadata']
    print(f"{m['mod_name']}  L{m.get('lineno','?')}  pr={r.get('pagerank',0):.4f}  "
          f"callers={list(r['callers'])[:2]}  callees={list(r['callees'])[:2]}")

Step 4 — Trace

Reach for these only when the task spans packages or you need entry points.

k.api_call_paths('myapp', 'fasthtml', k=15)        # how myapp reaches into fasthtml
k.short_path('myapp.routes.checkout', 'stripe.Webhook.construct_event')
k.top_nodes('fasthtml', k=5)                       # entry points to read first
k.neighbors('myapp.payments.verify', depth=2)

When to skip steps

Situation Steps
Trivial “how does X work” lookup in a known package 3 only
First time working in this repo / env 1 → 3
Task names a domain, multiple packages could fit 1 → 2 → 3
Task spans packages, or you need entry points 1 → 3 → 4

context() reference

The main entry point. Parses key:value filters, auto-detects package names, fans out repo + env searches in parallel, and merges with chained RRF. With graph=True (default) each result is enriched from .kosha/graph.db.

Each result is a dict with:

  • content — code snippet
  • metadata{mod_name, path, lineno, type, package?, docstring?}
  • graph fields — pagerank, in_degree, out_degree, callers, callees, co_dispatched

(co_dispatched lists siblings registered together at module level — route groups, plugin tables — the pattern to follow when adding a new handler. Inspect any result with dir(r) or r.keys().)

Filters

Token Example Effect
package:name package:fasthtml Env search restricted to one package
file:glob file:routes* Repo results by filename
path:pattern path:api/* Repo results by path
lang:ext lang:py By language
type:node type:FunctionDef By AST node type

Plurals (packages:, paths:) and comma-separated values are supported.

# Combined: functions in payments/, restricted to one package
k.context('handle stripe webhook type:FunctionDef path:payments/ package:fasthtml', limit=5)

Graph API

Call Returns
k.ni(node) Node row + callers + callees + co_dispatched + pagerank
k.short_path(a, b) Shortest call chain between two nodes
k.neighbors(node, depth=2) All nodes within N hops
k.graph.ranked(k=10, module='pkg') Top nodes by PageRank
k.public_api(pkg, limit=200) Public entries (__all__ + @patch) with docstrings
k.gn(where=...) / k.ge(where=...) Direct graph_nodes / graph_edges queries

CLI

For shell harnesses (GitHub Copilot CLI, Claude Code hooks, scripts). Markdown by default; --as_json pipes cleanly into jq. Run kosha with no args to see all subcommands.

kosha sync                                          # once per checkout
kosha context "embed a query" --as_json | jq '.[].metadata.mod_name'
kosha public-api fastcore
kosha api-paths kosha litesearch --k 10
kosha ni "fastcore.basics.merge"

Harness install

# Project-local (default; auto-discovered by Claude Code, Continue.dev, Cursor, Copilot)
#   .agents/skills/kosha/SKILL.md   ← written by Kosha(install_skill=True); commit it
# Claude Code, global across all projects on this machine:
mkdir -p ~/.claude/skills/kosha && cp .agents/skills/kosha/SKILL.md ~/.claude/skills/kosha/
# Other harnesses: place SKILL.md at whatever path the harness scans (e.g. .continue/skills/kosha/).

pyskills

kosha is registered as a pyskill (entry point kosha.skill). LLM hosts can list_pyskills() to discover it without importing, then doc(kosha.skill) for the full surface and instantiate Kosha directly.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

koshas-0.0.9.tar.gz (34.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

koshas-0.0.9-py3-none-any.whl (37.5 kB view details)

Uploaded Python 3

File details

Details for the file koshas-0.0.9.tar.gz.

File metadata

  • Download URL: koshas-0.0.9.tar.gz
  • Upload date:
  • Size: 34.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for koshas-0.0.9.tar.gz
Algorithm Hash digest
SHA256 79fee3d4d05dbe6043de057f98cb8969a3913afeafcfd477d167708143a083f7
MD5 b2a3310ca8984a1961f4dad6af2583db
BLAKE2b-256 95ce2d761f6ebea8f3249dc3f6f6c1f803da90e2d91333760f0851aa58cb6ab8

See more details on using hashes here.

File details

Details for the file koshas-0.0.9-py3-none-any.whl.

File metadata

  • Download URL: koshas-0.0.9-py3-none-any.whl
  • Upload date:
  • Size: 37.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for koshas-0.0.9-py3-none-any.whl
Algorithm Hash digest
SHA256 d2108eb6d1782529e4d3153c8065244dea1b9f8a15088ecb4fdfbe5dbfffaa47
MD5 a9aa27be69344cb53be5ccee30661d9e
BLAKE2b-256 80234259b88eae7c7e74b72c13568c3a1b711a570eed0f587713a66f8c3aa10b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page