{"id":45094114,"url":"https://github.com/obsfx/promptscout","last_synced_at":"2026-02-19T18:08:49.970Z","repository":{"id":338019674,"uuid":"1154835173","full_name":"obsfx/promptscout","owner":"obsfx","description":"Enrich coding agent prompts with codebase context using a local LLM","archived":false,"fork":false,"pushed_at":"2026-02-12T21:11:20.000Z","size":321,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-12T21:22:49.275Z","etag":null,"topics":["agent","ai","coding-agent","context-engineering","llamacpp","node","prompt-engineering","qwen3","qwen3-4b"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/obsfx.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-02-10T20:38:40.000Z","updated_at":"2026-02-12T15:24:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/obsfx/promptscout","commit_stats":null,"previous_names":["obsfx/promptscout"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/obsfx/promptscout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obsfx%2Fpromptscout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obsfx%2Fpromptscout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obsfx%2Fpromptscout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obsfx%2Fpromptscout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/obsfx","download_url":"https://codeload.github.com/obsfx/promptscout/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obsfx%2Fpromptscout/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29626858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T18:02:07.722Z","status":"ssl_error","status_checked_at":"2026-02-19T18:01:46.144Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["agent","ai","coding-agent","context-engineering","llamacpp","node","prompt-engineering","qwen3","qwen3-4b"],"created_at":"2026-02-19T18:08:48.863Z","updated_at":"2026-02-19T18:08:49.964Z","avatar_url":"https://github.com/obsfx.png","language":"TypeScript","readme":"# promptscout\n\nA CLI tool that enriches your coding agent prompts with codebase context using a local LLM. No API keys, no cloud. Runs on your machine.\n\n**Designed as a Claude Code plugin.** It hooks into your prompt submission flow and adds codebase context before Claude sees it.\n\n\u003cimg width=\"1715\" height=\"1230\" alt=\"CleanShot 2026-02-13 at 02 49 39\" src=\"https://github.com/user-attachments/assets/d37eba7d-8697-4a2a-b231-b4217b90692e\" /\u003e\n\n\n## Motivation\n\nWhen you ask a coding agent like Claude Code, Cursor, or Copilot to work on your codebase, the agent spends time and tokens discovering which files matter. It greps, reads, explores, all on your dime.\n\npromptscout does that discovery locally, for free. A small local LLM reads your prompt, searches your codebase with `ripgrep` and `git`, and appends the results to your original prompt. The paid agent gets a prompt that already contains the relevant file paths, code snippets, and commit history. It can skip straight to the actual work.\n\nYour original prompt is never modified. promptscout only appends context.\n\n## How It Works\n\n```mermaid\nflowchart LR\n    A[\"Raw Prompt\"] --\u003e B[\"Local LLM\u003cbr/\u003e(Qwen 3 4B)\"]\n    B --\u003e|\"tool calls\"| C[\"ripgrep / git\"]\n    C --\u003e D[\"Original Prompt\u003cbr/\u003e+ Discovered Context\"]\n\n    subgraph B_ctx[\" \"]\n        direction TB\n        T[\"Project Tree\u003cbr/\u003e(git ls-files)\"]\n    end\n    T -.-\u003e|\"context\"| B\n```\n\n1. You run `promptscout \"check the auth module, there might be a token refresh bug\"`\n2. The local LLM sees your prompt along with the project file tree (`git ls-files`) and decides which search tools to call\n3. The LLM outputs tool calls directly as JSON (e.g. `file_finder(\"auth\")`, `section_finder(\"token\")`, `git_history(\"refresh\")`)\n4. Each tool runs against your codebase using `ripgrep` and `git`\n5. The output is your original prompt unchanged, followed by the discovered context\n6. The result is copied to your clipboard, ready to paste into your coding agent\n\n## Installation\n\n### Prerequisites\n\n- Node.js \u003e= 20\n- C++ compiler (Xcode Command Line Tools on macOS, `build-essential` on Linux)\n- [ripgrep](https://github.com/BurntSushi/ripgrep) (`rg`) for fast codebase search\n- `git` (for project tree generation and commit history search)\n- ~3GB disk space for the model\n\n### Install\n\n```bash\nnpm install -g promptscout\n```\n\nOr from source:\n\n```bash\ngit clone https://github.com/obsfx/promptscout.git\ncd promptscout\npnpm install\npnpm build\npnpm link --global\n```\n\n### Setup\n\nRun `promptscout setup` to create the data directory and download the `Qwen 3 4B` model (~2.5GB). The model is stored in `~/.promptscout/models/`.\n\n## Claude Code Plugin\n\n\u003cimg src=\"https://raw.githubusercontent.com/lobehub/lobe-icons/refs/heads/master/packages/static-png/dark/claude-color.png\" alt=\"Claude\" width=\"48\" /\u003e\n\npromptscout ships with a Claude Code plugin that enriches every prompt you send. Once installed, it runs in the background. No manual copy-pasting needed.\n\n### Install the plugin\n\n```bash\n# Add the promptscout marketplace\nclaude /plugin marketplace add obsfx/promptscout\n\n# Install the plugin\nclaude /plugin install promptscout\n```\n\nOr in Claude Code interactive mode:\n\n```\n/plugin marketplace add obsfx/promptscout\n/plugin install promptscout\n```\n\nOnce installed, every prompt you submit in Claude Code gets enriched with codebase context via the `UserPromptSubmit` hook. The plugin passes your prompt through `promptscout` with `--json-output --no-clipboard` and injects the result as additional context.\n\nWhen context is found, the plugin shows a summary notification:\n\n```\npromptscout: enriched context (+5 files) (+3 sections) (+1 definitions)\n```\n\nIf `promptscout` is not installed or fails for any reason, the plugin falls back silently and your original prompt goes through unchanged.\n\n## Model\n\npromptscout uses `Qwen 3 4B` (`Q4_K_M` quantization) running locally via [node-llama-cpp](https://github.com/withcatai/node-llama-cpp). The model uses GPU acceleration automatically when available (Metal on macOS, CUDA on Linux).\n\n- Size: ~2.5GB (`GGUF Q4_K_M`)\n- Context: 8192 tokens\n- Latency: ~2s per prompt (Metal, Apple Silicon)\n- Purpose: Decides which search tools to call based on your prompt and the project file tree. Does not rewrite your text.\n\n## Tools\n\npromptscout has 5 built-in search tools. The LLM picks which ones to call and with what keywords:\n\n| Tool | What it does |\n|---|---|\n| `file_finder` | Finds files matching a keyword. Results scored by filename relevance. |\n| `section_finder` | Finds code lines matching a keyword. Returns `file:line:code` entries. |\n| `definition_finder` | Finds function, class, type, and struct definitions across languages. |\n| `import_tracer` | Finds import/require/include statements referencing a module. |\n| `git_history` | Finds recent commits that added or removed code matching a keyword. |\n\nAll search tools use `ripgrep`, which respects `.gitignore` and skips binary files automatically.\n\n## Usage\n\n```bash\n# Basic usage (result copied to clipboard)\npromptscout \"check the camera module, we need to add timeout handling\"\n\n# Dry run (print to stdout, skip clipboard)\npromptscout --dry-run --no-clipboard \"refactor the search module\"\n\n# Specify project directory\npromptscout --project-dir /path/to/project \"check the auth flow\"\n\n# JSON output (for programmatic use)\npromptscout --json-output \"fix the pagination bug\"\n```\n\n### Options\n\n```\n\u003cprompt\u003e                     Raw prompt to enrich\n-o, --output \u003cfile\u003e          Write result to file\n--dry-run                    Show result without copying or saving\n--json-output                Output JSON instead of plain text\n--no-clipboard               Skip clipboard copy\n--project-dir \u003cdir\u003e          Project root directory\n```\n\n## Commands\n\n### `promptscout setup`\n\nInitialize promptscout and download the default model. Creates the data directory at `~/.promptscout/` and downloads `Qwen 3 4B` (~2.5GB).\n\n```bash\npromptscout setup\n```\n\n### `promptscout history`\n\nView prompt history with paginated table output.\n\n```bash\n# Show history for current directory (default: 10 per page)\npromptscout history\n\n# Show all history across directories\npromptscout history -a\n\n# Paginate results\npromptscout history -p 2 -n 5\n\n# Show full detail of a specific entry\npromptscout history show 42\n\n# Clear all history\npromptscout history clear\n```\n\n## Examples\n\n### Swift project (macOS audio capture tool)\n\n```\n$ promptscout \"I want to add a new audio format export feature. check the current\naudio processing pipeline and see how formats are handled\"\n```\n\n```\nI want to add a new audio format export feature. check the current audio processing\npipeline and see how formats are handled\n\nContext from codebase:\n\n\u003cfile_finder query=\"audio\"\u003e\nSources/Core/AudioCaptureSession.swift\nSources/Core/AudioTapManager.swift\nSources/Info.plist\nSources/main.swift\nSources/CLI/ArgumentParser.swift\nSources/CLI/ExitCodes.swift\nREADME.md\nentitlements.plist\nSources/IO/RingBuffer.swift\nPackage.swift\n\u003c/file_finder\u003e\n\n\u003cdefinition_finder query=\"format\"\u003e\nSources/main.swift:49:              let tapFormat = tapManager.tapFormat else {\nSources/main.swift:53:        let outputSampleRate = UInt32(tapFormat.mSampleRate)\nSources/main.swift:55:        let sourceChannels = Int(tapFormat.mChannelsPerFrame)\nSources/Core/InputDeviceQuery.swift:41:    var formatAddress = AudioObjectPropertyAddress(\nSources/Core/InputDeviceQuery.swift:46:    var format = AudioStreamBasicDescription()\nSources/Core/AudioTapManager.swift:23:        case .formatQueryFailed(let status):\nSources/Core/AudioTapManager.swift:34:    private(set) var tapFormat: AudioStreamBasicDescription?\nSources/Core/AudioTapManager.swift:103:    private func queryTapFormat(tapID: AudioObjectID) throws -\u003e AudioStreamBasicDescription {\nSources/Core/AudioTapManager.swift:110:        var format = AudioStreamBasicDescription()\nSources/Core/AudioTapManager.swift:112:        let status = AudioObjectGetPropertyData(tapID, \u0026address, 0, nil, \u0026size, \u0026format)\n\u003c/definition_finder\u003e\n\n\u003cimport_tracer query=\"audio\"\u003e\nSources/IO/RingBuffer.swift:39:    /// Write bytes into the ring buffer. Called from the real-time audio thread.\nREADME.md:13:Download the latest build from the releases page.\nREADME.md:77:Record from the default microphone instead of system audio.\nREADME.md:149:The included entitlements.plist declares com.apple.security.device.audio-input.\n\u003c/import_tracer\u003e\n```\n\n### TypeScript project (task management CLI)\n\n```\n$ promptscout \"I want to add task filtering by status and tags. check how tasks\nare stored and queried\"\n```\n\n```\nI want to add task filtering by status and tags. check how tasks are stored and queried\n\nContext from codebase:\n\n\u003cfile_finder query=\"task\"\u003e\nsrc/services/task.ts\nsrc/commands/task.ts\nsrc/commands/subtask.ts\ntests/commands/subtask.test.ts\ntests/commands/task.test.ts\npackage.json\nsrc/services/epic.ts\nREADME.md\nCLAUDE.md\nsrc/services/history.ts\n\u003c/file_finder\u003e\n\n\u003csection_finder query=\"status\"\u003e\nsrc/services/task.ts:9:  TaskStatus,\nsrc/services/task.ts:73:  status?: TaskStatus;\nsrc/services/task.ts:81:  if (options?.status) {\nsrc/services/task.ts:82:    conditions.push(eq(tasks.status, options.status));\nsrc/services/list.ts:56:  if (options?.statuses \u0026\u0026 options.statuses.length \u003e 0) {\nsrc/services/list.ts:57:    const placeholders = options.statuses.map(() =\u003e \"?\").join(\", \");\nsrc/services/list.ts:58:    conditions.push(`status IN (${placeholders})`);\n\u003c/section_finder\u003e\n\n\u003csection_finder query=\"tag\"\u003e\nsrc/services/task.ts:56:    tags: input.tags ?? null,\nsrc/services/task.ts:140:  if (input.tags !== undefined) updates.tags = input.tags;\nsrc/commands/task.ts:29:  .option(\"--tags \u003ctags\u003e\", \"Comma-separated tags\")\nsrc/commands/task.ts:91:  .option(\"--tags \u003ctags\u003e\", \"New tags (comma-separated)\")\n\u003c/section_finder\u003e\n\n\u003cdefinition_finder query=\"task\"\u003e\nsrc/services/task.ts:16:export function createTask(input: CreateTaskInput): Task {\nsrc/services/task.ts:66:export function getTask(id: string): Task | undefined {\nsrc/services/task.ts:72:export function listTasks(options?: {\nsrc/services/task.ts:116:export function updateTask(id: string, input: UpdateTaskInput): Task {\n\u003c/definition_finder\u003e\n\n\u003cimport_tracer query=\"task\"\u003e\nsrc/services/task.ts:3:import { tasks, projects, epics } from \"../db/schema\";\nsrc/services/comment.ts:3:import { comments, tasks } from \"../db/schema\";\nsrc/services/dependency.ts:3:import { dependencies, tasks } from \"../db/schema\";\nsrc/commands/task.ts:8:} from \"../services/task\";\n\u003c/import_tracer\u003e\n```\n\n### React/TypeScript project (terminal ebook downloader)\n\n```\n$ promptscout \"I need to refactor the search module. check how search and pagination\ncurrently work and find the related components\"\n```\n\n```\nI need to refactor the search module. check how search and pagination currently work\nand find the related components\n\nContext from codebase:\n\n\u003cfile_finder query=\"search\"\u003e\nsrc/tui/layouts/search/search-input/SearchInput.tsx\nsrc/tui/layouts/search/search-input/SearchWarning.tsx\nsrc/tui/layouts/search/index.tsx\nsrc/tui/layouts/search/search-input/index.tsx\nsrc/options.ts\nsrc/labels.ts\nsrc/constants.ts\nsrc/utils.ts\nsrc/settings.ts\nCLAUDE.md\n\u003c/file_finder\u003e\n\n\u003cdefinition_finder query=\"search\"\u003e\nsrc/api/data/document.ts:3:export async function getDocument(searchURL: string): Promise\u003cDocument\u003e {\nsrc/constants.ts:1:export const SEARCH_MIN_CHAR = 3;\nsrc/settings.ts:11:export const SEARCH_PAGE_SIZE = 25;\nsrc/tui/store/events.ts:31:    const searchURL = get().mirrorAdapter?.getSearchURL(query, pageNumber, SEARCH_PAGE_SIZE);\nsrc/tui/store/events.ts:68:    const entries = await store.search(store.searchValue, store.currentPage);\nsrc/tui/layouts/search/index.tsx:8:const Search: React.FC = () =\u003e {\n\u003c/definition_finder\u003e\n```\n\n### No-context detection\n\nWhen the prompt has no technical keywords (pure acknowledgment), promptscout returns it unchanged:\n\n```\n$ promptscout \"thanks, that works perfectly\"\n```\n\n```\nthanks, that works perfectly\n```\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobsfx%2Fpromptscout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fobsfx%2Fpromptscout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobsfx%2Fpromptscout/lists"}