A Python bookmark manager and URL shortcut system: terminal CLI, web command palette, Chrome OpenSearch integration, and parameterized redirects.
pipx is the recommended path for end users:
pipx install bunnify
pipx ensurepath # adds ~/.local/bin to PATH if needed (restart the shell)
bunnify --version
bunnify onboard # print bookmarks / setup / Chrome next stepspipx installs bunnify and bunnify-server under ~/.local/bin by default
(or $PIPX_BIN_DIR when set). Ensure that directory is on your PATH before
running either command. Prefer the pipx apps over any checkout
./scripts/bunnify still on PATH.
The wheel installs bunnify (CLI), bunnify-server (Django
server), and spotty-bunny (macOS search box; needs extra
macos). No repository checkout or uv is required at runtime.
Package on PyPI: pypi.org/project/bunnify.
pipx does not print package docs after install. Run:
bunnify onboardThat prints the ready-to-go checklist (bookmarks path, bunnify setup,
Chrome/Edge, and upgrade). Same text:
bunnify --onboardSummary of what it covers:
- Bookmarks at
~/.config/bunnify/bookmarks.json(required before the server starts) βbunnify setupcan install the example shortcuts, or seed from bunnify.json.example bunnify setupβ local on a laptop; remote for a home/always-on host
LOCAL.md- Chrome / Edge β match
BUNNIFY_BASE_URLfromconfig.env
CHROME_SETUP.md - Try it:
bunnify ghor address-bar keyword (e.g.b gh) - macOS Spotty Bunny (optional) β
pipx install 'bunnify[macos]'thenbunnify spotty-bunny install(LOCAL.md)
Preferred:
bunnify upgradeThat prints the version/commit you are running from, the PyPI target, then
the pipx app version/commit to after pipx upgrade. Use this instead of
bare pipx upgrade bunnify so you can see when PATH is still a git checkout.
On macOS, bunnify upgrade also refreshes installed server and Spotty Bunny
LaunchAgents when their plists are present (or run bunnify-server upgrade /
bunnify spotty-bunny upgrade manually).
pipx upgrade only updates ~/.local/bin/bunnify. If bunnify --version still
shows a checkout SHA, PATH is hitting ./scripts/bunnify or a repo .venv.
After pipx ensurepath, command -v bunnify should be ~/.local/bin/bunnify.
Bookmarks and ~/.config/bunnify/config.env are user data β upgrades do not
overwrite them. After a major server change, re-run bunnify setup only if
docs or release notes say so. Setup will offer to stop a different local
Bunnify build and start this CLI's build when the port is already in use.
Source and docs: github.com/the-hcma/bunnify.
bunnify setup offers to install the example bookmarks when none exist yet.
You can also create the file yourself from the
documented example
into XDG config:
mkdir -p ~/.config/bunnify
curl -fsSL https://raw.githubusercontent.com/the-hcma/bunnify/main/bunnify.json.example \
-o ~/.config/bunnify/bookmarks.json
# edit ~/.config/bunnify/bookmarks.json with your shortcutsSee Configuration
for overrides (BUNNIFY_BOOKMARKS, XDG_CONFIG_HOME).
bunnify setupLaptop / daily machine: choose local (default). On macOS, setup
installs the server LaunchAgent (com.thehcma.bunnify), verifies
/health, records the port, and saves settings to ~/.config/bunnify/config.env.
Elsewhere it starts a managed background server the same way as before. Point
Chrome or Edge at the same BUNNIFY_BASE_URL
(Chrome / Edge setup).
Home server / always-on host: choose remote on client devices and enter
that hostβs URL. Setup probes /health; if the host is unreachable it warns
and asks before saving. Prefer a centralized remote install when several
machines share one server β not as a laptopβs only dependency if you often go
offline.
One-time override without saving: bunnify --base-url https://β¦ shortcut.
Details: Local and remote setup.
bunnify # interactive REPL (Tab completion, history)
bunnify gh # open a shortcut in the browser
bunnify bun # Bunnify source on GitHub
bunnify pr the-hcma/bunnify 272 # parameterized shortcut
bunnify --fzf # fuzzy picker
bunnify --print-url ghUnknown keys exit non-zero in direct mode (no search-engine fallback).
- CLI / REPL β fuzzy Tab completion, fzf mode, Vim/Emacs edit keys
- Spotty Bunny β dual-Control search box (
spotty-bunny; extramacos; login LaunchAgent viainstall/upgrade/uninstall) - macOS server LaunchAgent β local setup installs
bunnify-serverunder launchd (bunnify-server install|status|upgrade|uninstall) - Web β
/cmd/command palette,/list/browser, smart/search/ - Chrome / Edge β OpenSearch at
/opensearch.xml(setup guide) - Parameters β URLs with
#{name}placeholders and optional defaults - Validation β JSON Schema on load; reserved keys
h/help
Optional Spotlight-style search box. Hold one Control and tap the other to
type a shortcut. Needs the macos extra (PyObjC).
pipx install 'bunnify[macos]'
pipx ensurepath
bunnify spotty-bunny install # login LaunchAgent (TCC + KeepAlive)
bunnify spotty-bunny statusinstall grants Accessibility and Input Monitoring to the interpreter
launchd will exec (typically the pipx venv Python), writes
~/Library/LaunchAgents/com.thehcma.bunnify.spotty-bunny.plist, and bootstraps
it. Bare spotty-bunny (or bunnify spotty-bunny with no subcommand) still
runs in the foreground for debugging.
bunnify upgrade # pipx package; on macOS refreshes LaunchAgents
bunnify spotty-bunny upgrade # manual plist bounce when neededOn macOS, bunnify upgrade rewrites both LaunchAgents when installed. Use
bunnify spotty-bunny upgrade only when you need to refresh Spotty without
upgrading the pipx package.
bunnify spotty-bunny uninstallThat boots the agent out, removes the plist, and stops a leftover overlay
process. Bookmarks and config.env are unchanged. Right-click the bunny icon
for Install Spotty Bunny (when the LaunchAgent is missing), Quit Spotty
Bunny, Uninstall Spotty Bunny, and (when installed and a newer PyPI
version is known) Upgrade Spotty Bunny. An up-arrow badge on the
icon and an About line mark an outdated install (PyPI is checked at most
once a day).
Left-click the bunny for About: bookmarks file, GitHub repo when that file lives in a GitHub checkout, and whether the CLI is talking to a local or remote server (with its URL).
Details: Local and remote setup.
Installed users manage the server with bunnify-server:
bunnify-server --help
bunnify-server install --port 8000 # macOS: server LaunchAgent only
bunnify-server status
bunnify-server upgrade # rewrite plist for current binary
# Foreground (systemd, debugging):
bunnify-server --foreground --noninteractive --port 8000
# Background managed daemon (non-macOS or manual):
bunnify-server --port 8000 --noninteractive --pid-dir ~/.local/share/bunnify/run
bunnify-server --stop --pid-dir ~/.local/share/bunnify/run
curl --max-time 2 http://127.0.0.1:8000/healthLocal setup: bunnify setup (macOS installs the server LaunchAgent; other
platforms start a managed background server). Stop with:
bunnify stop # macOS: boot out server LaunchAgent; else stop managed serverThat prints the URL and runtime directory before stopping. Details: Local and remote setup.
Linux production:
systemd user service
via setup-service from
repository-helpers.
macOS: prefer bunnify setup (local) or the commands above. Manual plist
copy is optional β see
LaunchAgent example
and LOCAL.md.
With the server running (default http://127.0.0.1:8000 after setup):
| URL | Purpose |
|---|---|
/cmd/ |
Command palette (recommended) |
/search/?q=pr+12345 |
Smart search |
/list/ |
Browse all bookmarks |
/<key>/ |
Direct redirect |
/opensearch.xml |
Chrome search engine descriptor |
{
"gh": {
"description": "GitHub",
"url": "https://github.com/"
},
"pr": {
"description": "Pull request",
"url": "https://github.com/#{repo}/pull/#{pr_number}",
"defaults": { "repo": "org/repo" }
}
}Required fields: description, url. Placeholders use #{parameter_name}.
Reload after edits: the server watches the JSON file, or run
load_bookmarks in a development checkout.
Contributors clone the repo and use uv β separate from the pipx path above.
git clone https://github.com/the-hcma/bunnify.git
cd bunnify
uv sync
uv run python manage.py migrate
mkdir -p ~/.config/bunnify
cp bunnify.json.example ~/.config/bunnify/bookmarks.json
./scripts/bunnify setup
./scripts/bunnify-server --console --log-level DEBUG # optional
./test_bunnifyFull guidelines:
CONTRIBUTING.md.
Quality gates: ./scripts/checks.
Wrappers under ./scripts/ prefer uv run when uv is on PATH, otherwise
the checkout .venv (same entry points systemd uses on service hosts).
| Doc | Audience |
|---|---|
| CONFIG.md | XDG paths and environment variables |
| LOCAL.md | Local vs remote setup, ports, Spotty Bunny |
| SYSTEMD.md | Linux user service |
| CHROME_SETUP.md | Browser search engine |
| QUICK_REFERENCE.md | Cheat sheet |
| RELEASING.md | Maintainers: PyPI releases |
Server won't start
bunnify-server --console --log-level DEBUG
# or in a checkout: ./scripts/bunnify-server --consoleBookmarks missing
ls -l ~/.config/bunnify/bookmarks.json
# run `bunnify setup` (offers the example), or copy bunnify.json.exampleCLI can't reach server
bunnify setup
curl -sf "$(grep BUNNIFY_BASE_URL ~/.config/bunnify/config.env | cut -d= -f2-)/health"Stale managed process
bunnify-server --stop --pid-dir ~/.local/share/bunnify/runMaintainers: docs/RELEASING.md (Release Please + PyPI).
MIT Β© 2026 Henrique Andrade (GitHub's thehcma) β see LICENSE.