{"id":51119048,"url":"https://github.com/sulthonzh/fuzzyfind","last_synced_at":"2026-06-25T00:30:39.836Z","repository":{"id":365022210,"uuid":"1268809969","full_name":"sulthonzh/fuzzyfind","owner":"sulthonzh","description":"Zero-dependency fuzzy string matching with scoring, filtering, and highlighting","archived":false,"fork":false,"pushed_at":"2026-06-15T13:40:33.000Z","size":9,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-15T15:19:26.129Z","etag":null,"topics":["filter","fuzzy","fzf","highlight","match","score","search"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sulthonzh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-06-14T00:51:11.000Z","updated_at":"2026-06-15T13:30:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sulthonzh/fuzzyfind","commit_stats":null,"previous_names":["sulthonzh/fuzzyfind"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/sulthonzh/fuzzyfind","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulthonzh%2Ffuzzyfind","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulthonzh%2Ffuzzyfind/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulthonzh%2Ffuzzyfind/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulthonzh%2Ffuzzyfind/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sulthonzh","download_url":"https://codeload.github.com/sulthonzh/fuzzyfind/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sulthonzh%2Ffuzzyfind/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34755061,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-24T02:00:07.484Z","response_time":106,"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":["filter","fuzzy","fzf","highlight","match","score","search"],"created_at":"2026-06-25T00:30:39.745Z","updated_at":"2026-06-25T00:30:39.816Z","avatar_url":"https://github.com/sulthonzh.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fuzzyfind\n\nZero-dependency fuzzy string matching with scoring, filtering, and highlighting — for when you need fzf-like search inside your Node app or CLI without shipping a native binary.\n\nInspired by [fzf](https://github.com/junegunn/fzf) and Sublime Text's fuzzy search.\n\n## Install\n\n```bash\nnpm install @sulthonzh/fuzzyfind\n```\n\n## Quick Start\n\n```js\nconst fuzzy = require('@sulthonzh/fuzzyfind');\n\n// Basic match\nconst m = fuzzy.match('sr', 'server');\n// → { score: 54, positions: [0, 2] }\n\n// Boolean check\nfuzzy.isMatch('abc', 'aXbXc'); // → true\n\n// Filter and rank\nconst results = fuzzy.filter('ser', [\n  'server.ts', 'client.ts', 'service.ts', 'utils.ts'\n]);\n// → [{ target: 'server.ts', score: ..., positions: [...] }, ...]\n\n// Highlight for terminal output\nconst hl = fuzzy.highlight('server', [0, 2]);\n// → '\\x1b[32ms\\x1b[0me\\x1b[32mr\\x1b[0mver'\n```\n\n## Real-World Examples\n\n### 1. Interactive File Picker\n\nBuild a fast file finder that ranks results by relevance — perfect for CLI tools, editors, or dashboards.\n\n```js\nconst fuzzy = require('@sulthonzh/fuzzyfind');\nconst { readFileSync } = require('fs');\n\nconst allFiles = readFileSync('file-list.txt', 'utf8').split('\\n').filter(Boolean);\n\nfunction findFiles(query, limit = 10) {\n  return fuzzy.filter(query, allFiles, { limit }).map(r =\u003e ({\n    path: r.target,\n    score: Math.round(r.score),\n  }));\n}\n\nconsole.log(findFiles('src test'));\n// [{ path: 'src/test.ts', score: 72 }, { path: 'test/src.js', score: 65 }, ...]\n```\n\n### 2. Autocomplete Ranking\n\nScore and rank suggestions for an autocomplete dropdown. The scoring algorithm naturally prefers prefix matches, word boundaries, and consecutive characters.\n\n```js\nconst fuzzy = require('@sulthonzh/fuzzyfind');\n\nconst commands = [\n  'git commit', 'git push', 'git pull', 'git checkout',\n  'git cherry-pick', 'git config', 'git clone', 'git branch',\n];\n\nfunction suggest(input) {\n  return fuzzy.filter(input, commands, { limit: 5 }).map(r =\u003e ({\n    command: r.target,\n    score: r.score,\n    positions: r.positions, // use for HTML \u003cmark\u003e highlighting\n  }));\n}\n\nconsole.log(suggest('gck'));\n// [{ command: 'git checkout', score: ..., positions: [0, 4, 7] }]\n```\n\n### 3. Command Palette (VS Code style)\n\nBuild a Sublime/VS Code-style command palette where users type abbreviated queries to find actions.\n\n```js\nconst fuzzy = require('@sulthonzh/fuzzyfind');\n\nconst actions = [\n  { id: 'file.save', label: 'File: Save' },\n  { id: 'file.open', label: 'File: Open Folder' },\n  { id: 'view.terminal', label: 'View: Toggle Terminal' },\n  { id: 'git.commit', label: 'Git: Commit' },\n  { id: 'preferences.settings', label: 'Preferences: Open Settings' },\n];\n\nfunction searchPalette(query) {\n  return fuzzy.filter(query, actions, { key: 'label', limit: 5 })\n    .map(r =\u003e ({ ...r.item, score: r.score }));\n}\n\nconsole.log(searchPalette('pref set'));\n// [{ id: 'preferences.settings', label: 'Preferences: Open Settings', score: ... }]\n```\n\n## How It Works\n\nThe scoring algorithm uses dynamic programming to find the optimal alignment of query characters within the target string. Scoring factors:\n\n| Factor | Effect |\n|--------|--------|\n| Character match | +16 base |\n| First query char matched early | +10 bonus |\n| Word boundary (after space, `/`, `_`, `-`, `.`) | +8 bonus |\n| camelCase transition | +7 bonus |\n| Consecutive match (no gap) | +12 bonus |\n| Uppercase letter matched | +2 bonus |\n| Gap between matched chars | −1 per char |\n| Leading/trailing unmatched chars | −0.1 per char |\n\n## API\n\n### `match(query, target, opts?) → { score, positions } | null`\n\nFuzzy match `query` against `target`. Returns match info or `null`.\n\nOptions:\n- `caseSensitive` (default: `false`) — case-sensitive matching\n\n### `isMatch(query, target, opts?) → boolean`\n\nQuick boolean check without computing full score.\n\n### `filter(query, targets, opts?) → Array`\n\nFilter and sort an array of strings or objects by fuzzy match score.\n\nOptions:\n- `key` — property name to match if targets are objects\n- `caseSensitive` — case-sensitive matching\n- `limit` — max number of results\n\nReturns `{ item, score, positions, target }[]` sorted by score descending.\n\n### `highlight(str, positions, ansi?, reset?) → string`\n\nWrap matched characters in ANSI escape codes for terminal display.\n\n### `highlightRanges(positions, length) → Array`\n\nGet structured highlight ranges for custom rendering (e.g., HTML `\u003cmark\u003e`).\n\n## CLI\n\n```bash\n# Search stdin\nls | fuzzyfind test\n\n# Search a file\nfuzzyfind config --file package.json\n\n# Search a comma-separated list\nfuzzyfind js --list \"javascript,typescript,python,rust\"\n\n# JSON output with scores\ncat files.txt | fuzzyfind src --json\n\n# Limit results\nls | fuzzyfind spec --limit 5\n\n# Version\nfuzzyfind --version\n```\n\n## Comparison\n\n| Feature | fuzzyfind | [fzf](https://github.com/junegunn/fzf) | [Fuse.js](https://fusejs.io) | [fuzzysort](https://github.com/farzher/fuzzysort) |\n|---------|-----------|-------|---------|------------|\n| Dependencies | **Zero** | Zero (Go binary) | 1 | Zero |\n| Language | JavaScript | Go (native binary) | JavaScript | JavaScript |\n| Scoring algorithm | DP (fzf-inspired) | Custom | Bitap + scoring | Prepared-index |\n| Runtime | Node.js | Standalone CLI | Browser/Node | Browser/Node |\n| Object key filtering | ✅ | Via `--filter` | ✅ | Manual |\n| Position tracking | ✅ | ✅ | ❌ | ✅ |\n| ANSI highlighting | ✅ | ✅ | ❌ | ❌ |\n| CLI included | ✅ | ✅ (standalone) | ❌ | ❌ |\n| Bundle size | ~6 KB | 2+ MB | ~15 KB | ~6 KB |\n| Pre-built index | ❌ | N/A | Optional | ✅ (faster cold start) |\n\n**When to use fuzzyfind:** You need fuzzy search as a library inside a Node app or CLI tool, with no native dependencies, and fzf-like scoring quality.\n\n**When to use fzf:** You need a standalone interactive terminal fuzzy finder.\n\n**When to use Fuse.js:** You need fuzzy search in the browser with loose/fuzzy matching (typo tolerance).\n\n**When to use fuzzysort:** You have large datasets and can afford a pre-indexing step for sub-millisecond lookups.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsulthonzh%2Ffuzzyfind","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsulthonzh%2Ffuzzyfind","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsulthonzh%2Ffuzzyfind/lists"}