Bunnify
A Python bookmark manager and URL shortcut system: terminal CLI, web command palette, Chrome OpenSearch integration, and parameterized redirects.
Install
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 steps
pipx 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.
After install or upgrade
pipx does not print package docs after install. Run:
bunnify onboard
That prints the ready-to-go checklist (bookmarks path, bunnify setup,
Chrome/Edge, and upgrade). Same text:
bunnify --onboard
Summary 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)
Upgrade
Preferred:
bunnify upgrade
That 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.
Quick start
1. Bookmarks file
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 shortcuts
See Configuration
for overrides (BUNNIFY_BOOKMARKS, XDG_CONFIG_HOME).
2. Configure local or remote mode
bunnify setup
Laptop / 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.
3. Run shortcuts
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 gh
Unknown keys exit non-zero in direct mode (no search-engine fallback).
Features
- 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
Spotty Bunny (macOS)
Optional Spotlight-style search box. Hold one Control and tap the other to
type a shortcut. Needs the macos extra (PyObjC).
Install
pipx install 'bunnify[macos]'
pipx ensurepath
bunnify spotty-bunny install # login LaunchAgent (TCC + KeepAlive)
bunnify spotty-bunny status
install 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.
Upgrade
bunnify upgrade # pipx package; on macOS refreshes LaunchAgents
bunnify spotty-bunny upgrade # manual plist bounce when needed
On 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.
Uninstall
bunnify spotty-bunny uninstall
That 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.
Server lifecycle
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/health
Local 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 server
That 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.
Web usage
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 |
Bookmarks format
{
"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.
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_bunnify
Full 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).
Documentation
| 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 |
Troubleshooting
Server won't start
bunnify-server --console --log-level DEBUG
# or in a checkout: ./scripts/bunnify-server --console
Bookmarks missing
ls -l ~/.config/bunnify/bookmarks.json
# run `bunnify setup` (offers the example), or copy bunnify.json.example
CLI 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/run
Releasing
Maintainers: docs/RELEASING.md (Release Please + PyPI).
License
MIT © 2026 Henrique Andrade (GitHub's thehcma) — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bunnify-0.12.1.tar.gz.
File metadata
- Download URL: bunnify-0.12.1.tar.gz
- Upload date:
- Size: 191.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb8bbb4bd48e32a95dba4ec637f422dd3418693b65bca2401416b8d1a1335fea
|
|
| MD5 |
318d89daf03e19e356d6daaaf0a5ee65
|
|
| BLAKE2b-256 |
74cdf57f8fe7776870a35189bf3738ec6b3b93dbe56e3c083f6c2227ec4ae344
|
Provenance
The following attestation bundles were made for bunnify-0.12.1.tar.gz:
Publisher:
release-please.yml on the-hcma/bunnify
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bunnify-0.12.1.tar.gz -
Subject digest:
eb8bbb4bd48e32a95dba4ec637f422dd3418693b65bca2401416b8d1a1335fea - Sigstore transparency entry: 2678452399
- Sigstore integration time:
-
Permalink:
the-hcma/bunnify@8219563f83fe58795001d7979d0cfd77e46e6ee7 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/the-hcma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@8219563f83fe58795001d7979d0cfd77e46e6ee7 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bunnify-0.12.1-py3-none-any.whl.
File metadata
- Download URL: bunnify-0.12.1-py3-none-any.whl
- Upload date:
- Size: 224.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
003d614e12203acfaab46abba31ff5d65ce61c882201672bac597ff80990e445
|
|
| MD5 |
dc8794cb8c7480a567b86711e65438cd
|
|
| BLAKE2b-256 |
7703a95f80b377ec0259b967c02c2ba19f759e33ed404bc9296a02c42406acb3
|
Provenance
The following attestation bundles were made for bunnify-0.12.1-py3-none-any.whl:
Publisher:
release-please.yml on the-hcma/bunnify
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bunnify-0.12.1-py3-none-any.whl -
Subject digest:
003d614e12203acfaab46abba31ff5d65ce61c882201672bac597ff80990e445 - Sigstore transparency entry: 2678452571
- Sigstore integration time:
-
Permalink:
the-hcma/bunnify@8219563f83fe58795001d7979d0cfd77e46e6ee7 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/the-hcma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@8219563f83fe58795001d7979d0cfd77e46e6ee7 -
Trigger Event:
push
-
Statement type: