{"id":47965083,"url":"https://github.com/mhiro2/code-shape.nvim","last_synced_at":"2026-04-04T10:29:04.341Z","repository":{"id":341389192,"uuid":"1169930652","full_name":"mhiro2/code-shape.nvim","owner":"mhiro2","description":"Structure-aware navigation for large codebases in Neovim - fast symbol search, call graph exploration, and hotspot-based refactoring prioritization","archived":false,"fork":false,"pushed_at":"2026-03-23T05:46:57.000Z","size":213,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-24T02:02:38.439Z","etag":null,"topics":["code-navigation","neovim","neovim-plugin","nvim","nvim-pluigin"],"latest_commit_sha":null,"homepage":"","language":"Lua","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/mhiro2.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-03-01T12:55:08.000Z","updated_at":"2026-03-23T05:46:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mhiro2/code-shape.nvim","commit_stats":null,"previous_names":["mhiro2/code-shape.nvim"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mhiro2/code-shape.nvim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhiro2%2Fcode-shape.nvim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhiro2%2Fcode-shape.nvim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhiro2%2Fcode-shape.nvim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhiro2%2Fcode-shape.nvim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mhiro2","download_url":"https://codeload.github.com/mhiro2/code-shape.nvim/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhiro2%2Fcode-shape.nvim/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31397051,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["code-navigation","neovim","neovim-plugin","nvim","nvim-pluigin"],"created_at":"2026-04-04T10:29:03.579Z","updated_at":"2026-04-04T10:29:04.328Z","avatar_url":"https://github.com/mhiro2.png","language":"Lua","readme":"# code-shape.nvim\n\n\u003e **Structure-aware navigation** for large repositories.\n\u003e\n\u003e - 🔎 **Defs**: fast symbol definition search from a local Rust index\n\u003e - 🕸️ **Calls**: follow call/reference edges from the selected symbol\n\u003e - 🔥 **Hotspots + Debt**: prioritize risky areas via git churn × complexity\n\n`code-shape.nvim` keeps a fast incremental index in a small Rust core and gives\nyou one workflow for exploration and refactoring prioritization.\n\n## 💡 Why code-shape.nvim?\n\nBuilt for codebases where the key question is **\"what should we touch first?\"**\n\n**Best fit:**\n- Large monorepos where LSP symbol search gets slow or unstable\n- Legacy refactoring where hotspot × complexity guides starting points\n- Environments that need fast startup/search via persisted snapshots\n\n**Not fit** — for small projects (≤10k LOC) or plain text search, `live_grep` / `lsp_workspace_symbols` are sufficient.\n\n## ✨ Features\n\n- ⚡ Millisecond-level symbol search from an incremental Rust index\n- 🧭 Unified picker with three modes: **Defs**, **Calls**, **Hotspots**\n- 🕸️ Call graph exploration from the selected symbol (`gc`, `l`, `h`, `r`)\n- 🔥 Hotspots ranked by git history (with optional churn/time-decay weighting)\n- 📊 Code metrics: cyclomatic complexity, LOC, nesting depth (via Tree-sitter)\n- 🎯 Tech debt scoring: hotspot × complexity for targeted refactoring\n- 🗂️ Automatic indexing of opened buffers + workspace symbol indexing\n- 💾 Snapshot persistence on startup/exit (`snapshot.*`)\n- 🌳 Multi-root support for monorepos and git worktrees (per-root stats/hotspots)\n- 🧩 External picker integrations for Telescope / fzf-lua / snacks.nvim\n\n## 🧭 Workflow: Defs → Calls → Hotspots\n\n1. **Defs** — find the symbol (`gc` to explore callers/callees)\n2. **Calls** — follow the call graph (`l` forward, `h` back)\n3. **Hotspots** — prioritize by git churn × complexity\n\nDetails and example scenario: `:help code-shape-workflow`\n\n## 📦 Requirements\n\n- Neovim `\u003e= 0.10`\n- A working LSP setup (for best results)\n- Optional: `git` (for Hotspots)\n\n## 🚀 Installation\n\n### lazy.nvim\n\n```lua\n{\n  \"mhiro2/code-shape.nvim\",\n  config = function()\n    require(\"code-shape\").setup({})\n  end,\n}\n```\n\n### packer.nvim\n\n```lua\nuse({\n  \"mhiro2/code-shape.nvim\",\n  config = function()\n    require(\"code-shape\").setup({})\n  end,\n})\n```\n\n## Quickstart\n\n1. Open your project in Neovim\n2. Run:\n\n```vim\n:CodeShapeIndex\n```\n\n3. Open the picker:\n\n```vim\n:CodeShape\n```\n\nType to search for symbol definitions.\n\n## 💻 Commands\n\n| Command              | Description                       |\n| -------------------- | --------------------------------- |\n| `:CodeShape`         | Open the picker UI                |\n| `:CodeShapeIndex`    | Build/refresh index (incremental) |\n| `:CodeShapeReindex`  | Full rebuild                      |\n| `:CodeShapeIndexCancel` | Cancel running workspace index |\n| `:CodeShapeStatus`   | Show index stats                  |\n| `:CodeShapeClear`    | Clear indexed symbols, hotspot scores, and tracked roots |\n| `:CodeShapeHotspots` | Open Hotspots view (drill into symbol metrics) |\n| `:CodeShapeCallsFromCursor` | Open Calls mode for symbol under cursor |\n| `:CodeShapeDiffImpact [--base=\u003cref\u003e] [--head=\u003cref\u003e] [--staged]` | Open AI-era diff impact view (risk order) |\n| `:CodeShapeTelescope [mode]` | Open with Telescope (defs/hotspots/impact) |\n| `:CodeShapeFzf [mode]`       | Open with fzf-lua (defs/hotspots/impact)   |\n| `:CodeShapeSnacks [mode]`    | Open with snacks.nvim (defs/hotspots/impact) |\n\n## ⌨️ Default Keymaps (in picker)\n\n\u003e [!IMPORTANT]\n\u003e `config.keymaps` in this section applies only to the built-in picker UI (`picker = \"builtin\"` or `nil`).\n\u003e If you use an external backend (`telescope` / `fzf_lua` / `snacks`), configure keymaps in that picker plugin or map `:CodeShape*` commands directly.\n\nAll bindings below can be customized via `config.keymaps`.\n\n### Normal Mode\n\n| Key      | Action                    |\n| -------- | ------------------------- |\n| `\u003cCR\u003e`   | Jump to symbol            |\n| `\u003cC-s\u003e`  | Split jump                |\n| `\u003cC-v\u003e`  | Vsplit jump               |\n| `j` / `k`| Next / Previous item      |\n| `q` / `\u003cEsc\u003e` | Close                |\n| `\u003cTab\u003e`  | Next mode (Defs→Calls→Hotspots) |\n| `\u003cS-Tab\u003e`| Previous mode             |\n| `t`      | Cycle kind filter (All/Func/Class/Var/Type) |\n| `gd`     | Go to definition (LSP)    |\n| `gr`     | Show references (LSP)     |\n| `gc`     | Build/follow call graph   |\n| `l`      | Follow selected graph node |\n| `h`      | Back to previous graph node |\n| `r`      | Refresh current graph node |\n\n### Insert Mode (in input window)\n\n| Key      | Action                    |\n| -------- | ------------------------- |\n| `\u003cCR\u003e`   | Jump to symbol            |\n| `\u003cC-n\u003e` / `\u003cC-p\u003e` | Next / Previous item |\n| `\u003cTab\u003e`  | Next mode                 |\n| `\u003cS-Tab\u003e`| Previous mode             |\n| `\u003cC-t\u003e`  | Cycle kind filter         |\n| `\u003cC-g\u003e`  | Build/follow call graph   |\n\n### Hotspots Drill-down (`:CodeShapeHotspots`)\n\n| Key      | Action                    |\n| -------- | ------------------------- |\n| `\u003cCR\u003e`   | Drill into file → show symbol metrics |\n| `\u003cBS\u003e`   | Back to file list         |\n| `h`      | Back to file list         |\n| `q`      | Close                     |\n| `\u003cEsc\u003e`  | Close                     |\n\nIn the symbol metrics view, `\u003cCR\u003e` jumps to the symbol location.\n\n### Mode Tabs\n\nThe picker supports three modes:\n\n- **Defs**: Search for symbol definitions (functions, classes, methods, etc.)\n- **Calls**: Explore call/reference edges in a lightweight graph panel (`gc`/`l` follow, `h` back, `r` refresh)\n- **Hotspots**: Browse files by change frequency\n\nUse `\u003cTab\u003e` / `\u003cS-Tab\u003e` to cycle between modes.\n\n#### Calls Mode Features\n\n**Navigation History**: The breadcrumb shows your path through the call graph:\n```\nPath (3/5): authenticate \u003e check_token \u003e validate_session\n```\nThe `(3/5)` indicates you're at position 3 of 5 in the history.\n\n**Section Summary**: A quick overview of graph edges:\n```\nCallers: 5 | Callees: 3 | Refs: 12\n```\n\n**Context Preservation**: When switching between modes, your query and selected symbol are preserved:\n- Defs → Calls: Selected symbol becomes the call graph center\n- Calls → Defs: Query is restored\n- Defs ↔ Hotspots: Query and selection position are maintained\n\n**External Picker Users**: Call graph navigation requires interactive `l`/`h`/`r` keys, which are not supported in external pickers. Use `:CodeShapeCallsFromCursor` to open the builtin UI directly in Calls mode for the symbol under cursor.\n\n### Kind Filters\n\nPress `t` (normal mode) or `\u003cC-t\u003e` (insert mode) to cycle through kind filters:\n\n- **All**: Show all symbols\n- **Func**: Methods, Constructors, Functions\n- **Class**: Classes, Interfaces, Structs\n- **Var**: Properties, Fields, Variables, Constants\n- **Type**: Enums, EnumMembers, TypeParameters\n\n## 🧺 Picker Integration (telescope / fzf-lua / snacks.nvim)\n\nSet `picker` in your config to use an external backend:\n\n```lua\nrequire(\"code-shape\").setup({\n  picker = \"telescope\",  -- \"builtin\" | \"telescope\" | \"fzf_lua\" | \"snacks\"\n})\n```\n\nPer-backend setup, keymaps, and Lua API: `:help code-shape-picker`\n\n## ⚙️ Configuration\n\nConfigure via `require(\"code-shape\").setup({ ... })`.\n\n\u003cdetails\u003e\u003csummary\u003eDefault Settings\u003c/summary\u003e\n\n```lua\n{\n  -- UI preferences\n  ui = {\n    width = 0.8,        -- width ratio (0-1) or absolute columns (integer \u003e= 1)\n    height = 0.8,       -- height ratio (0-1)\n    border = \"rounded\", -- border style: \"none\", \"single\", \"double\", \"rounded\", \"solid\", \"shadow\"\n    preview = true,     -- show preview window\n  },\n\n  -- Search settings\n  search = {\n    limit = 50,         -- max results\n    debounce_ms = 100,  -- debounce time for input\n  },\n\n  -- Hotspots (git churn)\n  hotspots = {\n    enabled = true,\n    since = \"3 months ago\", -- time range for git log\n    max_files = 1000,       -- max files to analyze\n    -- Optional hotspot scoring options\n    half_life_days = 30,    -- days for commit weight to decay to 0.5\n    use_churn = true,       -- use numstat for line change analysis\n  },\n\n  -- Code metrics (Tree-sitter based)\n  metrics = {\n    enabled = true,         -- compute metrics during indexing\n    complexity_cap = 50,    -- cap for tech debt normalization\n  },\n\n  -- Picker keymaps\n  keymaps = {\n    select = \"\u003cCR\u003e\",\n    open_vsplit = \"\u003cC-v\u003e\",\n    open_split = \"\u003cC-s\u003e\",\n    prev = \"k\",\n    prev_alt = \"\u003cUp\u003e\",\n    next = \"j\",\n    next_alt = \"\u003cDown\u003e\",\n    prev_insert = \"\u003cC-p\u003e\",\n    next_insert = \"\u003cC-n\u003e\",\n    mode_next = \"\u003cTab\u003e\",\n    mode_prev = \"\u003cS-Tab\u003e\",\n    cycle_kind_filter = \"t\",\n    goto_definition = \"gd\",\n    show_references = \"gr\",\n    show_calls = \"gc\",\n    graph_follow = \"l\",\n    graph_back = \"h\",\n    graph_refresh = \"r\",\n    close = \"q\",\n    close_alt = \"\u003cEsc\u003e\",\n  },\n\n  -- Snapshot persistence\n  snapshot = {\n    enabled = true,\n    load_on_start = true,\n    save_on_exit = true,\n    remote_cache = {\n      enabled = false,               -- optional (for shared/remote filesystem cache)\n      dir = \"/mnt/code-shape-cache\", -- base directory for remote cache\n      load_on_start = true,          -- pull remote snapshot before local load\n      save_on_exit = true,           -- push local snapshot after save\n    },\n  },\n\n  -- Picker backend: \"builtin\" (default), \"telescope\", \"fzf_lua\", \"snacks\"\n  -- picker = nil,\n\n  -- Debug mode (shows $/progress and $/log notifications)\n  debug = false,\n}\n```\n\n\u003c/details\u003e\n\n## 🏗️ How it works\n\n**Lua** handles UI/LSP, **Rust core** serves fast search via stdio JSON-RPC.\nIndexes LSP `documentSymbol` / `workspace/symbol` into an incremental n-gram inverted index.\n\n| Repo scale | code-shape p50 (ms) | lsp_workspace_symbols p50 (ms) | live_grep p50 (ms) |\n|------------|---------------------|--------------------------------|---------------------|\n| 100k LOC   | 0.606               | 0.400                          | 5                   |\n| 500k LOC   | 0.745               | 2.081                          | 5                   |\n| 1M LOC     | 1.371               | 4.223                          | 4                   |\n\nBenchmark details: [`benchmark/README.md`](./benchmark/README.md) | `:help code-shape-benchmark`\nAdvanced features (snapshots, multi-root, code metrics, AI-era diffs): `:help code-shape-advanced`\n\n## 📄 License\n\nMIT License. See [LICENSE](./LICENSE).\n\n## 🔁 Alternatives\n\n- [stevearc/aerial.nvim](https://github.com/stevearc/aerial.nvim)\n- [simrat39/symbols-outline.nvim](https://github.com/simrat39/symbols-outline.nvim)\n- [nvimdev/lspsaga.nvim](https://github.com/nvimdev/lspsaga.nvim)\n- [folke/trouble.nvim](https://github.com/folke/trouble.nvim)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhiro2%2Fcode-shape.nvim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmhiro2%2Fcode-shape.nvim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhiro2%2Fcode-shape.nvim/lists"}