{"_id":"@elianiva/pi-ckers","_rev":"2-30539e8f688d255b1722884d758e01e1","name":"@elianiva/pi-ckers","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@elianiva/pi-ckers","version":"1.0.0","keywords":["pi-package"],"author":{"name":"elianiva"},"license":"MIT","_id":"@elianiva/pi-ckers@1.0.0","maintainers":[{"name":"elianiva","email":"dicha.arkana03@gmail.com"}],"homepage":"https://github.com/elianiva/dotfiles/tree/main/packages/pi-ckers","bugs":{"url":"https://github.com/elianiva/dotfiles/issues"},"dist":{"shasum":"6961c241fca752df56a159daab90814ed84ee4f7","tarball":"https://registry.npmjs.org/@elianiva/pi-ckers/-/pi-ckers-1.0.0.tgz","fileCount":12,"integrity":"sha512-4eljvxMy80Wm4NIsEXZCaKCsXDYROAryidk6WT4Lf/E+ZnWVAZCZtno9GYPTQ2/asQUkj/s4Qgn4Kx4xgzL3gg==","signatures":[{"sig":"MEQCIBWu9couVyaRvJ4ZW2/yZ0p6rIO29cTnaCe1jwCCywMXAiAhTo4ahFsDLC/maYh8qvy7yioKGB9mJ+BkFYWBR3QSYw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":127679},"main":"./index.ts","engines":{"node":">=20"},"exports":{".":{"default":"./index.ts"},"./types":{"default":"./types.ts"},"./builtin/jj":{"default":"./builtin/jj.ts"},"./builtin/fff":{"default":"./builtin/fff.ts"},"./builtin/git":{"default":"./builtin/git.ts"},"./builtin/grep":{"default":"./builtin/grep.ts"},"./builtin/vcs-base":{"default":"./builtin/vcs-base.ts"}},"gitHead":"c8e2da9c05274ae6ee603f0f7c471d4a6b332089","_npmUser":{"name":"elianiva","email":"dicha.arkana03@gmail.com"},"repository":{"url":"git+https://github.com/elianiva/dotfiles.git","type":"git","directory":"packages/pi-ckers"},"_npmVersion":"11.6.2","description":"Modular namespace pickers for pi: @file:, @git:, @jj:","directories":{},"_nodeVersion":"24.11.1","dependencies":{"koffi":"^2.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^25.3.5"},"peerDependencies":{"@sinclair/typebox":"*","@mariozechner/pi-tui":"*","@mariozechner/pi-coding-agent":"*"},"trustedDependencies":["koffi"],"_npmOperationalInternal":{"tmp":"tmp/pi-ckers_1.0.0_1773142379450_0.2513218533155954","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@elianiva/pi-ckers","version":"1.1.0","description":"Modular namespace pickers for pi: @file:, @git:, @jj:","keywords":["pi-package"],"license":"MIT","author":{"name":"elianiva"},"main":"./index.ts","repository":{"type":"git","url":"git+https://github.com/elianiva/dotfiles.git","directory":"packages/pi-ckers"},"bugs":{"url":"https://github.com/elianiva/dotfiles/issues"},"homepage":"https://github.com/elianiva/dotfiles/tree/main/packages/pi-ckers","engines":{"node":">=20"},"exports":{".":{"default":"./index.ts"},"./types":{"default":"./types.ts"},"./builtin/fff":{"default":"./builtin/fff.ts"},"./builtin/grep":{"default":"./builtin/grep.ts"},"./builtin/git":{"default":"./builtin/git.ts"},"./builtin/jj":{"default":"./builtin/jj.ts"},"./builtin/vcs-base":{"default":"./builtin/vcs-base.ts"}},"dependencies":{"koffi":"^2.15.2"},"peerDependencies":{"@mariozechner/pi-coding-agent":"^0.64.0","@mariozechner/pi-tui":"^0.64.0","@sinclair/typebox":"^0.34.49"},"trustedDependencies":["koffi"],"devDependencies":{"@types/node":"^25.5.0"},"gitHead":"b6917a9eef6397eb5d8e7598bac9e00e7e8a9e49","_id":"@elianiva/pi-ckers@1.1.0","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-aJPBHZHMggyMIYvDhq4GCsFAIHDXJdQYTmsXyd/TIVrqkxFWfxlqOhJEOZ0HHZAF4UFG8vHD8xghzBByV1a6Lg==","shasum":"73bb85c346b72ca59308f6cd4f7d605e220573c6","tarball":"https://registry.npmjs.org/@elianiva/pi-ckers/-/pi-ckers-1.1.0.tgz","fileCount":12,"unpackedSize":127450,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQChUtPScpp60xJTOKIJfFaXbrdhw7zzXmne1TUdxdvVxQIhAOm87oyBRZ9M6v+vE1AlMQvaA3ii4N3AQSLZEl1fgiGb"}]},"_npmUser":{"name":"elianiva","email":"dicha.arkana03@gmail.com"},"directories":{},"maintainers":[{"name":"elianiva","email":"dicha.arkana03@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pi-ckers_1.1.0_1774824878605_0.5189937813828969"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-10T11:32:59.364Z","modified":"2026-03-29T22:54:38.862Z","1.0.0":"2026-03-10T11:32:59.604Z","1.1.0":"2026-03-29T22:54:38.750Z"},"bugs":{"url":"https://github.com/elianiva/dotfiles/issues"},"author":{"name":"elianiva"},"license":"MIT","homepage":"https://github.com/elianiva/dotfiles/tree/main/packages/pi-ckers","keywords":["pi-package"],"repository":{"type":"git","url":"git+https://github.com/elianiva/dotfiles.git","directory":"packages/pi-ckers"},"description":"Modular namespace pickers for pi: @file:, @git:, @jj:","maintainers":[{"name":"elianiva","email":"dicha.arkana03@gmail.com"}],"readme":"# @elianiva/pi-ckers\n\nNamespace-prefixed pickers for pi. This is a **library package**, not an auto-loading extension.\n\n## Why Namespaced Pickers?\n\nDumb models struggle to differentiate between directories and files purely based on trailing `/`. By using explicit prefixes like `@dir:` and `@file:`, you give the agent a clear hint about what you're referring to. No more ambiguous paths. This also allows me to scope my suggestions, when I want to search for dirs I don't want to also get file suggestions.\n\nThis also makes it extensible because you can have different namespaces, for example I use `@git:` or `@jj:` to point the agent to changes/revisions so it can review the diff, without having me to copy/paste the ID myself.\n\n## Why a Library Package?\n\n**Extensibility**: This is intentionally designed as a library you compose, not a ready-to-use extension. You build your own editor by combining pickers with other packages.\n\n**No hard dependencies**: This extension was made alongside my other extension, [@elianiva/pi-starship](https://github.com/elianiva/pi-starship), which also overrides the editor, but I want to compose them and not have them have hard dependencies for each other.\n\n**Overrides editor**: Since this wraps/replaces the editor component, it can't be an auto-loading extension because you may have other extension that already overrides the editor. The extension loading in Pi have no particular order, so you can't stack overriding editors. The way you use this extension is explicitly opt-in by wrapping your editor with `withPickers()`.\n\nSee how I use it [in my configuration](https://github.com/elianiva/dotfiles/blob/master/agents/pi/extensions/composed-editor).\n\n## Installation\n\n```bash\nbun add @elianiva/pi-ckers\n```\n\n## Usage\n\nCreate your own extension in `~/.pi/extensions/my-extension/`:\n\n```typescript\nimport type { ExtensionAPI } from \"@mariozechner/pi-coding-agent\";\nimport { withPickers } from \"@elianiva/pi-ckers\";\nimport { filePicker, dirPicker } from \"@elianiva/pi-ckers/builtin/fff\";\nimport { grepPicker } from \"@elianiva/pi-ckers/builtin/grep\";\nimport { gitPicker } from \"@elianiva/pi-ckers/builtin/git\";\nimport { jjPicker } from \"@elianiva/pi-ckers/builtin/jj\";\n\n// Wrap any editor with picker support\nconst EditorWithPickers = withPickers(YourEditorClass, [\n  filePicker(),\n  dirPicker(),\n  grepPicker(),\n  gitPicker(),\n  jjPicker(),\n]);\n\nexport default function myExtension(pi: ExtensionAPI) {\n  pi.on(\"session_start\", async (_event, ctx) => {\n    if (!ctx.hasUI) return;\n    ctx.ui.setEditorComponent(\n      // Pass ExtensionContext as 5th argument to initialize pickers\n      (tui, theme, kb) => new EditorWithPickers(tui, theme, kb, undefined, ctx)\n    );\n  });\n}\n```\n\n## Features\n\nType any namespace prefix in the editor:\n\n| Prefix | Description | Example |\n|--------|-------------|---------|\n| `@file:` | Fuzzy file picker | `@file:src/index` |\n| `@dir:` | Fuzzy directory picker | `@dir:components` |\n| `@grep:` | Grep file contents | `@grep:foo` |\n| `@git:` | Git revision picker | `@git:main` |\n| `@jj:` | Jujutsu change picker | `@jj:abc` |\n\n## API\n\n### `withPickers(EditorClass, pickers)`\n\nHigher-order function that adds picker autocomplete to any editor that extends CustomEditor. Make sure the constructor receives `ctx` as the 5th parameter.\n\n```typescript\nimport { CustomEditor } from \"@mariozechner/pi-coding-agent\";\nimport { withPickers } from \"@elianiva/pi-ckers\";\nimport { filePicker, grepPicker } from \"@elianiva/pi-ckers/builtin/fff\";\n\nconst MyEditor = withPickers(CustomEditor, [\n  filePicker(),\n  grepPicker(),\n  gitPicker(),\n]);\n```\n\n### `createPicker(config)`\n\n```typescript\nimport { createPicker } from \"@elianiva/pi-ckers\";\n\n// Static picker - handles filtering internally\nconst staticPicker = createPicker({\n  type: \"static\",\n  prefix: \"@emoji:\",\n  items: [\n    { value: \"@emoji:rocket\", label: \"🚀\", description: \"rocket\" },\n    { value: \"@emoji:fire\", label: \"🔥\", description: \"fire\" },\n  ],\n  maxResults: 20,\n});\n\n// Sync picker - you provide the search function\nconst syncPicker = createPicker({\n  type: \"sync\",\n  prefix: \"@my:\",\n  search(query, ctx) {\n    return [\n      { value: \"@my:result\", label: \"Result\", description: \"Details\" }\n    ];\n  },\n  init(ctx) {\n    // Optional: setup cache, watchers, etc.\n  },\n  clearCache() {\n    // Optional: clear cached data\n  },\n  destroy() {\n    // Optional: cleanup when session ends\n  }\n});\n```\n\nPicker types:\n- `type: \"static\"` - Provide `items` array, picker handles filtering\n- `type: \"sync\"` - Provide `search(query, ctx)` function\n\nCommon options for all types:\n- `prefix` - The namespace prefix (e.g., `\"@my:\"`)\n- `minQueryLength` - Minimum query length before showing completions (default: 0)\n- `init(ctx)` - Called once when picker is initialized\n- `clearCache()` - Called to clear cached data\n- `destroy()` - Called when session ends\n\n## Built-in Pickers\n\n### `filePicker()` / `dirPicker()`\n\n```typescript\nimport { filePicker, dirPicker } from \"@elianiva/pi-ckers/builtin/fff\";\n\nfilePicker({\n  maxResults?: 20,  // Maximum results to show\n})\n```\n\nUses [`fff`](https://github.com/dmtrKovalenko/fff.nvim) (fast fuzzy finder by [Dmitriy Kovalenko](https://github.com/dmtrKovalenko)) for fast file searching and typo-resistant algorithm.\n\nThe native binary is **auto-downloaded** on first use from the [fff.nvim releases](https://github.com/dmtrKovalenko/fff.nvim/releases), verified against upstream `sha256`, and cached in `node_modules/@elianiva/pi-ckers/bin/`.\n\n**Supported Platforms:**\n\n| Architecture | OS | Binary |\n|--------------|-----|--------|\n| aarch64 | macOS | `c-lib-aarch64-apple-darwin.dylib` |\n| x86_64 | macOS | `c-lib-x86_64-apple-darwin.dylib` |\n| aarch64 | Linux | `c-lib-aarch64-unknown-linux-gnu.so` |\n| x86_64 | Linux | `c-lib-x86_64-unknown-linux-gnu.so` |\n| aarch64 | Android | `c-lib-aarch64-linux-android.so` |\n| x86_64 | Android | `c-lib-x86_64-linux-android.so` |\n| x86_64 | Windows | `c-lib-x86_64-pc-windows-msvc.dll` |\n\nIf your platform is not supported, the picker will gracefully fall back to a basic implementation.\n\n> **Testing Status:** Currently only tested on **macOS ARM64 (aarch64)**. Other platforms should work but may have issues. Please report any problems if you have any.\n\n### `grepPicker()`\n\n```typescript\nimport { grepPicker } from \"@elianiva/pi-ckers/builtin/grep\";\n\ngrepPicker({\n  maxResults?: 20,      // Maximum results to show\n  minQueryLength?: 2,   // Minimum query length before searching\n})\n```\n\nSearches file contents using fff's live grep. Returns results in `@grep:path:line` format. Requires fff binary (same as file/dir pickers).\n\n### `gitPicker()`\n\n```typescript\nimport { gitPicker } from \"@elianiva/pi-ckers/builtin/git\";\n\ngitPicker()\n```\n\nShows branches, tags, and recent commits. Requires `git` in PATH.\n\n### `jjPicker()`\n\n```typescript\nimport { jjPicker } from \"@elianiva/pi-ckers/builtin/jj\";\n\njjPicker()\n```\n\nShows Jujutsu changes. Requires `jj` in `$PATH`.\n\n## Credits\n\n- **[fff.nvim](https://github.com/dmtrKovalenko/fff.nvim)** — Fast fuzzy file finder by [Dmitriy Kovalenko](https://github.com/dmtrKovalenko). The file/directory picker uses `fff` binaries which are auto-downloaded from the upstream releases.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}