Inbox & helper
Inbox & helper
homebot assumes you’ll forget. So it does everything that can’t lose data on its own, and puts the rest in one short list, in your face, with the fix attached.
$ homebot
🧹 Neatpik · laptop · 3 things need you (1 urgent)
1 ! A commit was refused
furniture/big.iso is 4.2 GB (limit 50 MB)
→ homebot save
2 • 2 new things to sort: track, ignore or snooze
~/.config/zed, ~/.config/ghostty
→ homebot triage
3 • Profile workstation changed since the last unpack
→ homebot unpack
Done for you since you last looked: sealed 1 secret, committed 4 files, pushed 1 commit.
Do the first one now: homebot next
Where it reaches you
| Where | What you see | Cost |
|---|---|---|
| New shell | 🧹 Neatpik: 3 things need you (1 urgent), run: homebot |
reads a cache file, no subprocess |
| Prompt | HOMEBOT_COUNT (e.g. 3!), shown by Starship |
one read per prompt |
| Desktop | notification when the set of urgent items changes, again daily while unresolved | notify-send / osascript |
homebot |
the full list |
The shell refreshes the cache in the background when it’s older than 30 minutes.
Every refresh rewrites the nudge, symbol and count from the persona in effect at
that moment. homebot persona use refreshes at once; if you edit persona: in
homebot.yml or a persona file by hand, the shell shows the old voice until the
next refresh. Run homebot refresh (or bare homebot) to apply it at once;
otherwise any command that changes things, the hourly helper or the shell’s
30-minute check does it.
With a persona (Neatpik unless you chose another), the inbox
header and nudge start with that persona’s emoji and name, or your command
name when one is set, as above. The neutral voice says homebot · laptop · …
and 🚚 homebot: … instead, with your command name in place of homebot
when one is set. Every refresh (homebot persona use, bare homebot,
homebot refresh or the helper) writes $XDG_CACHE_HOME/homebot/symbol for
the Spaceship prompt section when a persona is active, and a custom zsh prompt
can call homebot_symbol to read it; the Starship snippet below always shows
🚚. With persona: none, with --plain/HOMEBOT_PLAIN, or
when the persona selected in homebot.yml is broken, it removes that file and
zsh falls back to 🚚. An unusable persona selected in homebot.yml adds a
persona_broken todo item, and until it is fixed the nudge, the prompt symbol
and desktop notifications are neutral (the terminal output still falls back to
Neatpik); an unusable HOMEBOT_PERSONA only warns in that terminal session, and
a refresh started from that shell speaks as Neatpik (the hourly helper does not
see the variable and uses the homebot.yml choice).
What it watches
- Git has no name or email for you, so commits fail (a new machine; listed before the refused commit it causes)
- Signing is on but the key file (
~/.ssh/id_rsahere) isn’t on this machine, so every commit fails. The fix shown turns signing off in~/.config/git/config.local;homebot unlockbrings the key back once it’s inprivate/ - A commit was refused (guard reason attached)
- An automatic chore failed (seal, export, autosave, sync, link)
- Layout errors in the repo
- Secret conflict (changed here and elsewhere)
gitleaksmissing- Commit guard not installed
- This machine and the remote both have new commits
- The repo isn’t a git repository
- Files in the way of links
- A
~/.gitconfigthat overrides the repo’s~/.config/git/config(the fix moves it aside forhomebot cleanup) - Backups that
homebot link --backupmoved aside (homebot cleanup) - Links not made yet
- New things to triage
- Secrets to unlock, or not sealed yet
- Uncommitted changes, unpushed or unpulled commits
- No remote / remote unreachable
- Profile never unpacked here, or changed since
- An export is failing
- Background helper missing or stale
- An installed helper or guard points at a homebot path that is missing, not
executable or a versioned binary (
helper-path);homebot setuprewrites it - A homebot update needs attention (
update-available): a newer release underupdate: notify, or underupdate: autoone homebot can’t install on its own (see Updates) - Keys not set up
- The configured persona file is missing or unusable (
persona_broken); runhomebot persona validate <id>
The background helper
homebot setup installs it: a systemd user timer on Linux
(homebot-tidy.timer, 5 min after boot, then hourly), a launchd agent on
macOS (sh.homebot.tidy). Each run is homebot tidy --notify --quiet --helper
(the last flag marks the unattended run; a homebot tidy you type never checks for
updates):
- Guard: reinstall the commit guard if
core.hooksPathdrifted. - Seal: encrypt changed secrets.
- Export: refresh package snapshots due (about once a day).
- Autosave: commit tracked changes on the
autosave.commitcadence (off/hourly/daily). - Sync: pull (rebase), push if
autosave.push. - Link: fix links that are safe to fix (never moves your files).
- Refresh the inbox, notify if the urgent set changed.
- Update: with
update: notifyorauto, check for a new homebot release (see Updates).
Each step that fails becomes an urgent item; the rest still run. A lock file stops two runs from overlapping.
The timer or agent runs with the PATH and repo setup saw, and with each of
XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_STATE_HOME and XDG_CACHE_HOME
that was set then, so it shares state, cache and lock with your shell. After
changing one of them, run homebot setup again. It also gets any of
HTTPS_PROXY, HTTP_PROXY, NO_PROXY (and their lowercase forms),
SSL_CERT_FILE and SSL_CERT_DIR that setup saw, for the release check. setup refuses a relative
one: homebot, its helper and the shell integration treat a relative XDG_*
as unset.
Updates
The update key in homebot.yml decides what the helper does about new
homebot releases. With off (the default) it never asks. Otherwise, after a
tidy that ran, the helper checks GitHub for the latest release about once a
day (six hours after a check that failed, for example offline). Only one
update step runs at a time, and the whole step, check and upgrade together,
gets five minutes. Source and development builds never check. Nothing else
asks in the background: the inbox only reads what the helper saved, and
homebot version --check asks once when you run it. A check that fails raises
no item and doesn’t hide one that is showing: an update-available item stays,
saying what it said, until the running version is at least the latest release.
notify: a newer release becomes anupdate-availableto-do item, with the command that upgrades this install.auto: Homebrew cask and install-script installs upgrade on their own, once a release has been out for 48 hours since the helper first saw it, and at most one attempt a day. A cask install checks the latest release again right before upgrading. An install-script upgrade needscosign(the minimum version is in the item) and verifies the release signature first. A successful upgrade writes a journal entry and sends a desktop notification..deband.rpminstalls (which need root), Homebrew formula,go installand unrecognised installs get the inbox item with the command to run instead. A failed upgrade (signature check, timeout, missingcosign, any other error) becomes the item too, saying why; a Homebrew install left broken also sends a notification with thebrew reinstallcommand. If Homebrew still hasn’t offered the release 72 hours after the first try, the item says so.
homebot version --check shows what applies to this machine.
It never overwrites a real file, never commits a file git doesn’t already
track, other than sealed secrets and export snapshots (new files go through homebot triage; the one exception is the very
first commit of an empty repo), never decrypts (that needs your
passphrase) and never resolves a conflict for you.
Shell integration
Add this to your .zshrc:
eval "$(homebot shell zsh)"
Completion
homebot completion zsh|bash|fish prints a completion script for homebot.
Homebrew cask, Debian and RPM installs already ship the zsh completion
(_homebot), so with compinit run before the eval line they need nothing
more. (On a Homebrew cask, compinit finds it only if Homebrew’s shellenv
ran before it: see Homebrew.) Script and Go installs do not ship it: for zsh, source the script after
compinit and before the eval line:
autoload -Uz compinit && compinit
source <(homebot completion zsh)
eval "$(homebot shell zsh)"
If you set a command name (homebot name) and ~/.local/bin/<name> links to
homebot, homebot shell zsh also completes that name the same way. The line
does nothing until a completion for homebot is registered, whether by the
packaged _homebot or by the completion line. With a script or Go install, if
the completion line comes after the eval line, only homebot completes, not
the name; without it, neither completes. bash and fish complete homebot only,
never the name.
[env_var.HOMEBOT_COUNT]
style = 'bold yellow'
format = """[🚚 $env_value ]\
($style)"""
Add homebot to SPACESHIP_PROMPT_ORDER.
State
Per machine, outside the repo:
| Path | Holds |
|---|---|
$XDG_STATE_HOME/homebot |
links made, secret hashes, snoozes, journal, last tidy |
$XDG_CACHE_HOME/homebot |
nudge, count and symbol for the shell; voice.json, the last variant each persona said |