{"id":51303699,"url":"https://github.com/rhydlewis/haunts","last_synced_at":"2026-06-30T22:30:40.966Z","repository":{"id":363138211,"uuid":"1260650250","full_name":"rhydlewis/haunts","owner":"rhydlewis","description":"Keyboard-first macOS folder launcher that's warm on first launch — jump to the folders you live in, in Finder, your editor, or a terminal.","archived":false,"fork":false,"pushed_at":"2026-06-07T15:36:35.000Z","size":2742,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T17:13:39.091Z","etag":null,"topics":["developer-tools","finder","frecency","fuzzy-finder","launcher","macos","menu-bar","productivity","sparkle","spotlight","swift","swiftui"],"latest_commit_sha":null,"homepage":"https://gethaunts.app","language":"Swift","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/rhydlewis.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":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-05T18:10:59.000Z","updated_at":"2026-06-07T15:36:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rhydlewis/haunts","commit_stats":null,"previous_names":["rhydlewis/haunts"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/rhydlewis/haunts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhydlewis%2Fhaunts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhydlewis%2Fhaunts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhydlewis%2Fhaunts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhydlewis%2Fhaunts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rhydlewis","download_url":"https://codeload.github.com/rhydlewis/haunts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhydlewis%2Fhaunts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34986247,"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-30T02:00:05.919Z","response_time":92,"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":["developer-tools","finder","frecency","fuzzy-finder","launcher","macos","menu-bar","productivity","sparkle","spotlight","swift","swiftui"],"created_at":"2026-06-30T22:30:37.390Z","updated_at":"2026-06-30T22:30:40.951Z","avatar_url":"https://github.com/rhydlewis.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Haunts\n\nA keyboard-driven folder launcher for macOS that's **warm on first launch**. Hit a\nhotkey, type a few letters, and jump straight to a folder in Finder, your editor, or\na terminal — ranked by a frecency model (frequency × recency) that's already useful\non day one, before it has watched you do anything.\n\nMost \"smart\" launchers start cold and take weeks to learn your habits. Haunts seeds\nits ranking on first run from signals that already exist on your machine — your git\nrepos, shell history, IDE recent-projects, your `zoxide`/`z`/`autojump` history, and\nSpotlight metadata — and blends them so the folders you actually work in surface\nimmediately.\n\n## Features\n\n- **Zero cold-start.** The day-one index is built from git repos + shell history\n  (fish/zsh/bash) + your jump database (`zoxide`/`z`/`autojump`) + IDE recents\n  (Zed, Xcode, PyCharm) + Spotlight usage, with no prior observation required.\n- **Cross-source ranking.** Each signal source is normalized independently (so one\n  high-volume source can't dominate) and folders that several sources agree on get a\n  small confidence boost.\n- **Learns as you go.** Opt-in live Finder-navigation tracking keeps the model fresh.\n- **Fast keyboard flow.** Summon, filter by subsequence match, open — without leaving\n  the keyboard.\n- **Native \u0026 dependency-free.** A menu-bar app with no zoxide/fzf/host-launcher\n  required.\n\n## Keyboard shortcuts\n\nWhile the palette is open:\n\n| Key | Action |\n| --- | --- |\n| `⌥Space` | Summon / dismiss the palette (rebindable in Preferences) |\n| type | Filter results by name |\n| `↑` / `↓` | Move selection |\n| `↩` | Open the selected folder in **Finder** |\n| `⌘↩` | Open in your **editor** |\n| `⌃↩` | Open in your **terminal** |\n| `⌘⌫` | **Forget** the selected folder (remove it from the learned set) |\n| `Esc` | Close the palette |\n\n\u003e The default summon chord is `⌥Space` — clear of macOS's reserved shortcuts\n\u003e (Spotlight, input source, Emoji \u0026 Symbols). Rebind it under **Settings → General**.\n\n## Build \u0026 run\n\nRequires macOS 14+ and a Swift 5.9 toolchain (Xcode 15+).\n\n```bash\n# Build\nswift build --package-path app\n\n# Run (menu-bar app — look for the ghost glyph in the menu bar)\nswift run --package-path app zforfinder\n\n# Test\nswift test --package-path app\n```\n\nOn first launch, grant Automation (Apple Events) access if you enable\n**Learn from navigation** — it's needed to observe the front Finder window.\n\n## Preferences\n\nOpen **Settings…** from the menu-bar item (or `⌘,` when a Haunts window is focused):\n\n- **General** — hotkey recorder, appearance (Light/Dark/System), launch at login.\n- **Ranking** — Balanced vs. Frequent ranking, subfolder frecency, and a\n  *Reset Learned Data…* button.\n- **Folders** — which roots to scan for git repos (with per-root depth).\n- **Open With** — editor priority + terminal of choice for the `⌘↩` / `⌃↩` verbs.\n\n## Architecture\n\nA Swift package (`app/`) split so the ranking logic stays pure and unit-testable:\n\n| Target | Role |\n| --- | --- |\n| `ZFFEngine` | Pure ranking/scoring — no AppKit, SwiftUI, or I/O. `WarmSeed`, `Frecency`, `Ranker`, `Scoring`, `Store`, `Rollup`. |\n| `HauntsAdapters` | Signal sources: editor recents, shell-history, and jump-database (`zoxide`/`z`/`autojump`) parsing. Foundation-only, never-throw. |\n| `HauntsCore` | `AppState` (index assembly), `Settings`, live `FinderTracker`. Testable without the executable. |\n| `zforfinder` | App shell: `AppDelegate`, the SwiftUI palette, the floating panel, and the global hotkey. |\n\n**How ranking works.** Each source contributes per-folder weights; `WarmSeed` scales\neach source to `0…1`, multiplies by a per-source trust weight, sums them, and adds a\nsmall bonus per additional agreeing source (transient folders like Downloads/Desktop\nare heavily down-weighted). Persisted visit history is then layered on top via\n`Frecency.blend`. All of the math is pure and deterministic — `now` is injected — so\nit's covered by unit tests in `app/Tests/ZFFEngineTests`.\n\nThe learned frecency store lives at\n`~/Library/Application Support/Haunts/frecency.json`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhydlewis%2Fhaunts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frhydlewis%2Fhaunts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhydlewis%2Fhaunts/lists"}