{"id":49504925,"url":"https://github.com/nshkrdotcom/dexterity","last_synced_at":"2026-05-01T14:34:23.160Z","repository":{"id":350581650,"uuid":"1207476814","full_name":"nshkrdotcom/dexterity","owner":"nshkrdotcom","description":"Authoritative, ranked, token-budgeted codebase context for Elixir agents. Solves context window limitations by providing a deterministic Elixir semantic graph and agent-ready Repo Map for LLMs.","archived":false,"fork":false,"pushed_at":"2026-04-11T03:20:59.000Z","size":61,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-11T03:26:41.985Z","etag":null,"topics":["agent","ai","ai-agents","anthropic-mcp","codebase-analysis","context","context-management","context-window","developer-tools","elixir","elixir-lang","graph-analysis","indexer","llm","lsp","mcp","mcp-server","nshkr-devtools","otp","pagerank"],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nshkrdotcom.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-11T01:45:53.000Z","updated_at":"2026-04-11T03:21:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nshkrdotcom/dexterity","commit_stats":null,"previous_names":["nshkrdotcom/dexterity"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/nshkrdotcom/dexterity","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nshkrdotcom%2Fdexterity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nshkrdotcom%2Fdexterity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nshkrdotcom%2Fdexterity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nshkrdotcom%2Fdexterity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nshkrdotcom","download_url":"https://codeload.github.com/nshkrdotcom/dexterity/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nshkrdotcom%2Fdexterity/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32501403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","ai","ai-agents","anthropic-mcp","codebase-analysis","context","context-management","context-window","developer-tools","elixir","elixir-lang","graph-analysis","indexer","llm","lsp","mcp","mcp-server","nshkr-devtools","otp","pagerank"],"created_at":"2026-05-01T14:34:22.376Z","updated_at":"2026-05-01T14:34:23.137Z","avatar_url":"https://github.com/nshkrdotcom.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dexterity\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/dexterity.svg\" alt=\"Dexterity Logo\" width=\"200\" height=\"200\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Ranked, deterministic repository context for Elixir tooling, agents, and MCP clients.\n\u003c/p\u003e\n\nDexterity turns an Elixir codebase into a queryable context layer:\n\n- It reads semantic edges from a Dexter-produced `.dexter.db`.\n- It builds a ranked repository graph with metadata-derived links.\n- It exports normalized file and symbol graph snapshots for downstream consumers.\n- It renders a token-budgeted repo map for agent prompts.\n- It exposes semantic queries and an optional stdio MCP server.\n\nIf you want exact, repeatable codebase context instead of ad hoc grep output, this is the layer Dexterity provides.\n\nDexterity is also the right structural kernel to build on if you plan to add a separate semantic retrieval library or a higher-level code intelligence platform later. The graph, snapshot, impact, and runtime surfaces are meant to be consumed directly without reaching into internal servers.\n\n## What You Get\n\n- `Dexterity.get_repo_map/1` for ranked, prompt-ready repository context.\n- `Dexterity.get_ranked_files/1` with active-file, edit, conversation-term, and first-party prefix filtering inputs.\n- `Dexterity.get_ranked_symbols/1` for symbol-level ranking over the same repo state.\n- `Dexterity.get_impact_context/1` for adaptive, diff-aware symbol context.\n- `Dexterity.get_file_graph_snapshot/1`, `Dexterity.get_symbol_graph_snapshot/1`, and `Dexterity.get_structural_snapshot/1` for stable structural exports.\n- `Dexterity.get_symbols/2`, `Dexterity.find_symbols/2`, and `Dexterity.match_files/2` for targeted discovery.\n- `Dexterity.get_module_deps/2` and `Dexterity.get_file_blast_radius/2` for impact checks.\n- `Dexterity.get_export_analysis/1`, `Dexterity.get_unused_exports/1`, and `Dexterity.get_test_only_exports/1` for callback-aware export analysis.\n- `Dexterity.get_runtime_observations/1`, `Dexterity.record_runtime_observations/2`, and `Dexterity.import_cover_modules/2` for persisted runtime confirmation.\n- `Dexterity.Query` for definitions, references, blast radius, and cochange neighbors.\n- Mix tasks for indexing, status, map rendering, and query execution.\n- Optional MCP transport over stdio for editor and agent integrations.\n\n## Ecosystem Direction\n\nThe intended shape is a small ecosystem, not one monolith.\n\nDexterity should remain the structural kernel:\n- Dexter ingestion\n- file and symbol graphs\n- impact, dependency, cochange, and export/runtime analysis\n- stable structural snapshots\n- direct Elixir API, Mix tasks, and MCP transport\n\nA future sibling library can sit on top of that kernel for semantic retrieval:\n- chunking and corpus policy\n- embeddings or lexical/vector search\n- hybrid reranking over semantic plus structural signals\n- model/provider integration\n\nA higher-level platform can then sit on top of both:\n- review packets\n- agent workflows\n- diagnostics and test execution loops\n- long-running services or editor integrations\n\nThe important point is that those layers should consume Dexterity through its public API, Mix, or MCP surfaces, not by reaching into `GraphServer` or `SymbolGraphServer` internals.\n\n## Future Work Here\n\nThis repo should stay thin, but it may still need more work in service of the kernel role:\n\n- keep improving the structural export contract for downstream consumers\n- improve indexing freshness, invalidation, and fallback behavior\n- improve precision in graph, impact, and runtime-aware analysis\n- improve determinism, performance, and backend abstraction\n- add structural backends or ingestion paths only if they strengthen the kernel itself\n\nWhat should not accumulate here by default is the product/platform layer: embedding-provider churn, vector search experiments, agent workflow logic, or UI concerns.\n\n## Requirements\n\nDexterity itself is pure Elixir, but the default production backend depends on external tooling:\n\n1. `dexter` CLI must be installed and available on `PATH`, or configured via `:dexter_bin`.\n2. A Dexter index database must exist for the target repo, usually `.dexter.db`.\n3. `git` should be available if you want cochange analysis to be useful.\n4. Native build tooling required by `exqlite` must be available on the machine building dependencies.\n5. If you want cover-backed runtime confirmation, the OTP `tools` install and debug-info beams must be available, plus `elixirc` to build sample modules in the example flow.\n\nThe included example is fully real: it creates a temporary repo, builds a real Dexter index through `mix dexterity.index`, ingests real git history for cochanges, imports real OTP `:cover` runtime evidence, and exercises Dexterity's mix tasks, library APIs, and MCP request handling against the resulting `.dexter.db`.\n\n## Installation\n\nAdd Dexterity to your dependencies:\n\n```elixir\ndefp deps do\n  [\n    {:dexterity, \"~\u003e 0.1.0\"}\n  ]\nend\n```\n\nThen fetch dependencies:\n\n```bash\nmix deps.get\n```\n\n## First Run With The Real Dexter Backend\n\nConfigure the runtime:\n\n```elixir\n# config/runtime.exs\nconfig :dexterity,\n  repo_root: System.get_env(\"PROJECT_ROOT\") || File.cwd!(),\n  backend: Dexterity.Backend.Dexter,\n  dexter_bin: System.get_env(\"DEXTER_BIN\") || \"dexter\",\n  dexter_db: \".dexter.db\",\n  mcp_enabled: true\n```\n\nBuild or refresh the Dexter index for the repo:\n\n```bash\nmix dexterity.index --repo-root .\n```\n\nVerify the backend and graph state:\n\n```bash\nmix dexterity.status --repo-root .\n```\n\nGenerate a prompt-ready repo map:\n\n```bash\nmix dexterity.map \\\n  --repo-root . \\\n  --active-file lib/my_app/accounts.ex \\\n  --mentioned-file lib/my_app_web/live/dashboard_live.ex \\\n  --limit 20 \\\n  --token-budget 4096\n```\n\nRun semantic queries:\n\n```bash\nmix dexterity.query definition MyApp.Accounts register 2 --repo-root .\nmix dexterity.query references MyApp.Accounts register 2 --repo-root .\nmix dexterity.query blast lib/my_app/accounts.ex --repo-root . --depth 2\nmix dexterity.query blast_count lib/my_app/accounts.ex --repo-root .\nmix dexterity.query cochanges lib/my_app/accounts.ex --repo-root . --limit 10\nmix dexterity.query symbols refund --repo-root .\nmix dexterity.query files '%accounts%' --repo-root .\nmix dexterity.query ranked_files --repo-root . --active-file lib/my_app/accounts.ex --include-prefix lib/ --include-prefix test/ --include-prefix mix.exs --exclude-prefix deps/ --overscan-limit 200 --limit 10\nmix dexterity.query file_graph --repo-root .\nmix dexterity.query symbol_graph --repo-root .\nmix dexterity.query runtime_observations --repo-root .\nmix dexterity.query structural_snapshot --repo-root . --include-export-analysis --include-runtime-observations\nmix dexterity.query ranked_symbols --repo-root . --active-file lib/my_app/accounts.ex\nmix dexterity.query impact_context --repo-root . --changed-file lib/my_app/accounts.ex --token-budget 2048\nmix dexterity.query export_analysis --repo-root .\nmix dexterity.query unused_exports --repo-root .\nmix dexterity.query test_only_exports --repo-root .\n```\n\n## Using The Library In Code\n\n```elixir\n{:ok, repo_map} =\n  Dexterity.get_repo_map(\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter,\n    active_file: \"lib/my_app/accounts.ex\",\n    mentioned_files: [\"lib/my_app_web/live/dashboard_live.ex\"],\n    conversation_terms: [\"refund\"],\n    conversation_tokens: 120_000,\n    token_budget: :auto,\n    limit: 20\n  )\n\n{:ok, symbols} =\n  Dexterity.get_symbols(\n    \"lib/my_app/accounts.ex\",\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter\n  )\n\n{:ok, references} =\n  Dexterity.Query.find_references(\n    \"MyApp.Accounts\",\n    \"register\",\n    2,\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter\n  )\n\n{:ok, ranked_symbol_hits} =\n  Dexterity.find_symbols(\n    \"refund\",\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter\n  )\n\n{:ok, indexed_account_files} =\n  Dexterity.match_files(\n    \"%accounts%\",\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter\n  )\n\n{:ok, ranked_files} =\n  Dexterity.get_ranked_files(\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter,\n    active_file: \"lib/my_app/accounts.ex\",\n    include_prefixes: [\"lib/\", \"test/\", \"mix.exs\"],\n    exclude_prefixes: [\"deps/\"],\n    overscan_limit: 200,\n    limit: 12\n  )\n\n{:ok, file_graph} =\n  Dexterity.get_file_graph_snapshot(\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter\n  )\n\n{:ok, symbol_graph} =\n  Dexterity.get_symbol_graph_snapshot(\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter\n  )\n\n{:ok, ranked_symbols} =\n  Dexterity.get_ranked_symbols(\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter,\n    active_file: \"lib/my_app/accounts.ex\",\n    mentioned_files: [\"lib/my_app_web/live/dashboard_live.ex\"],\n    limit: 12\n  )\n\n{:ok, impact_context} =\n  Dexterity.get_impact_context(\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter,\n    changed_files: [\"lib/my_app/accounts.ex\"],\n    token_budget: 2048,\n    limit: 12\n  )\n\n{:ok, blast_count} =\n  Dexterity.get_file_blast_radius(\n    \"lib/my_app/accounts.ex\",\n    repo_root: \"/workspace/my_app\"\n  )\n\n{:ok, unused_exports} =\n  Dexterity.get_unused_exports(\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter\n  )\n\n{:ok, export_analysis} =\n  Dexterity.get_export_analysis(\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter\n  )\n\n{:ok, structural_snapshot} =\n  Dexterity.get_structural_snapshot(\n    repo_root: \"/workspace/my_app\",\n    backend: Dexterity.Backend.Dexter,\n    include_export_analysis: true,\n    include_runtime_observations: true\n  )\n```\n\n`Dexterity.get_repo_map/1` is the main file-level integration point for agent context. `get_ranked_symbols/1` and `get_impact_context/1` sit on top of the symbol graph and are the higher-precision surfaces to use when you already know what changed or which file the model is focused on. `get_file_graph_snapshot/1`, `get_symbol_graph_snapshot/1`, and `get_structural_snapshot/1` are the stable kernel exports to use when you are building a sibling semantic indexer or a larger platform on top of Dexterity. `get_export_analysis/1` separates ordinary public API from callback entrypoints and can fold in persisted runtime confirmation from `import_cover_modules/2`.\n\n## MCP Server\n\nDexterity can also serve the same context surface as a stdio JSON-RPC MCP server:\n\n```bash\nmix dexterity.mcp.serve --repo-root .\n```\n\nSupported tools include:\n\n- `get_repo_map`\n- `get_file_graph_snapshot`\n- `get_ranked_files`\n- `get_ranked_symbols`\n- `get_impact_context`\n- `find_symbols`\n- `match_files`\n- `get_symbols`\n- `get_symbol_graph_snapshot`\n- `get_structural_snapshot`\n- `get_export_analysis`\n- `get_runtime_observations`\n- `get_file_blast_radius`\n- `get_unused_exports`\n- `get_test_only_exports`\n- `get_module_deps`\n- `query_definition`\n- `query_references`\n- `query_blast`\n- `query_cochanges`\n- `status`\n\n## Examples\n\nStart with the focused ranked-files example if you want to validate first-party file selection:\n\n```bash\nmix run examples/ranked_files_surface.exs\n```\n\nThen run the full real-backend example:\n\n```bash\nmix run examples/comprehensive_real_backend.exs\n```\n\nTogether, the examples show:\n\n- first-party ranked-file filtering across API, Mix, and MCP surfaces\n- real Dexter indexing through `mix dexterity.index`\n- live mix-task status, map, and query execution\n- real git-driven cochange ingestion\n- ranked repo map generation with adaptive auto budgeting and conversation-term boosts\n- symbol-level ranking and adaptive impact-context rendering\n- normalized file, symbol, and combined structural snapshot export\n- semantic symbol and file lookup\n- definition and reference queries\n- dependency lookup and direct blast radius counts\n- cochange enrichment\n- callback-aware export analysis and unused/test-only filtered views\n- raw runtime observations plus real `:cover` import for runtime-confirmed exports\n- real file reindexing\n- live MCP JSON-RPC requests\n\nSee [examples/README.md](examples/README.md) for details.\n\n## Operational Notes\n\n- Dexterity does not compile or evaluate project code to build context.\n- The real backend is only as fresh as the underlying Dexter index.\n- Summary generation is opt-in and disabled by default.\n- Cochange data is additive; if `git` history is unavailable, ranking still works from semantic and metadata edges.\n\n## Documentation\n\n- Start with [Quickstart](guides/quickstart.md) and [Configuration](guides/configuration.md).\n- Runnable example documentation lives in [examples/README.md](examples/README.md).\n- HexDocs is configured from this repository via `mix docs`.\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnshkrdotcom%2Fdexterity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnshkrdotcom%2Fdexterity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnshkrdotcom%2Fdexterity/lists"}