{"id":51747761,"url":"https://github.com/cobanov/herdr-ntfysh","last_synced_at":"2026-07-18T21:39:50.119Z","repository":{"id":368863742,"uuid":"1287188318","full_name":"cobanov/herdr-ntfysh","owner":"cobanov","description":"herdr plugin: push ntfy notifications when an agent finishes or needs your input","archived":false,"fork":false,"pushed_at":"2026-07-02T13:51:52.000Z","size":36,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-18T21:39:48.937Z","etag":null,"topics":["herdr","herdr-plugin","notifications","ntfy"],"latest_commit_sha":null,"homepage":null,"language":"Go","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/cobanov.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":null,"dco":null,"cla":null}},"created_at":"2026-07-02T13:08:16.000Z","updated_at":"2026-07-13T07:57:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cobanov/herdr-ntfysh","commit_stats":null,"previous_names":["cobanov/herdr-ntfysh"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/cobanov/herdr-ntfysh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cobanov%2Fherdr-ntfysh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cobanov%2Fherdr-ntfysh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cobanov%2Fherdr-ntfysh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cobanov%2Fherdr-ntfysh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cobanov","download_url":"https://codeload.github.com/cobanov/herdr-ntfysh/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cobanov%2Fherdr-ntfysh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35632492,"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-07-18T02:00:07.223Z","response_time":61,"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":["herdr","herdr-plugin","notifications","ntfy"],"created_at":"2026-07-18T21:39:49.518Z","updated_at":"2026-07-18T21:39:50.113Z","avatar_url":"https://github.com/cobanov.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# herdr-ntfysh\n\n\u003e Get an [ntfy](https://ntfy.sh) push the moment a [herdr](https://herdr.dev) agent finishes or needs your input.\n\n[![release](https://img.shields.io/github/v/release/cobanov/herdr-ntfysh?color=2ea44f)](https://github.com/cobanov/herdr-ntfysh/releases)\n[![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)\n![go](https://img.shields.io/badge/Go-stdlib%20only-00ADD8?logo=go\u0026logoColor=white)\n![herdr plugin](https://img.shields.io/badge/herdr-plugin-0f172a)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/preview.svg\" alt=\"ntfy notifications: 'Claude - done' and 'Codex - needs input'\" width=\"620\"\u003e\n\u003c/p\u003e\n\nStart a long task, walk away, and your phone (or desktop) pings when the agent is **done** or **blocked** — across every workspace. One small Go binary, **zero runtime dependencies**.\n\n## Quick start\n\n```bash\n# 1 · Install — herdr compiles it during install (needs Go ≥ 1.23, once)\nherdr plugin install cobanov/herdr-ntfysh\n\n# 2 · Configure your ntfy server + topic\ncp .env.example \"$(herdr plugin config-dir cobanov.herdr-ntfysh)/.env\"\n$EDITOR \"$(herdr plugin config-dir cobanov.herdr-ntfysh)/.env\"\n\n# 3 · Send a test push to confirm it works\nherdr plugin action invoke cobanov.herdr-ntfysh.test\n```\n\nMinimum config is two lines:\n\n```ini\nHERDR_NTFY_SERVER=https://ntfy.example.com\nHERDR_NTFY_TOPIC=herd\n```\n\nDone. From now on, `done` and `blocked` notifications fire automatically for agents in **every** workspace — no restart, no per-workspace setup.\n\n## Features\n\n- 🔔 **Pings when it matters** — notifies on `done` and `blocked` by default; `working`/`idle` are opt-in.\n- 🌍 **All workspaces** — one global hook covers every pane.\n- 🎯 **Reliable \"done\"** — catches both herdr's explicit `done` and a `working → idle` turn end.\n- 🤫 **No spam** — per-pane, windowed debounce.\n- 🔐 **Self-hosted friendly** — Bearer token, Basic auth, custom CA or insecure TLS.\n- 📦 **Zero deps** — a single static Go binary, no `node`/`curl`.\n- 🛟 **Fail-safe** — a bad config or an unreachable server never disrupts herdr.\n\n## Configuration\n\nSettings live in `.env` inside the plugin's config dir (or as env vars, which override the file). Most-used keys:\n\n| Key | Default | What it does |\n|---|---|---|\n| `HERDR_NTFY_SERVER` | — | ntfy base URL incl. scheme *(required)* |\n| `HERDR_NTFY_TOPIC` | — | ntfy topic *(required)* |\n| `HERDR_NTFY_TOKEN` | — | ntfy access token (Bearer auth) |\n| `HERDR_NTFY_USERNAME` / `_PASSWORD` | — | HTTP Basic auth |\n| `HERDR_NTFY_NOTIFY_ON` | `done,blocked` | which kinds notify (`done,blocked,working,idle`) |\n| `HERDR_NTFY_DEDUP_WINDOW` | `10` | seconds to suppress a repeat of the same kind |\n| `HERDR_NTFY_TLS_INSECURE` / `_CA_FILE` | — | self-signed / custom-CA TLS |\n| `HERDR_NTFY_DEBUG` | `false` | log raw event + decision for troubleshooting |\n\nSee [`.env.example`](./.env.example) for the complete list (priority, title prefix, tags, click URL, …).\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSelf-hosted ntfy\u003c/b\u003e — auth \u0026amp; TLS\u003c/summary\u003e\n\nPick at most one auth method (a token wins over basic credentials):\n\n```ini\nHERDR_NTFY_TOKEN=tk_xxxxxxxxxxxx      # access token (Bearer)\n# — or —\nHERDR_NTFY_USERNAME=herder\nHERDR_NTFY_PASSWORD=changeme\n```\n\nFor a private certificate, prefer pinning your CA over disabling verification:\n\n```ini\nHERDR_NTFY_CA_FILE=/etc/ssl/certs/my-ntfy-ca.pem   # recommended\nHERDR_NTFY_TLS_INSECURE=true                        # last resort\n```\n\u003c/details\u003e\n\n## Actions\n\n```bash\nherdr plugin action invoke cobanov.herdr-ntfysh.doctor   # print resolved config (secrets redacted)\nherdr plugin action invoke cobanov.herdr-ntfysh.test     # send a test push through the whole pipeline\n```\n\nBind the test action to a key in `~/.config/herdr/config.toml` if you like:\n\n```toml\n[[keys.command]]\nkey = \"prefix+n\"\ntype = \"shell\"\ncommand = \"herdr plugin action invoke cobanov.herdr-ntfysh.test\"\n```\n\n## How it works\n\nherdr rolls each pane up to `idle · working · blocked · done` and fires\n`pane.agent_status_changed`. This plugin maps those transitions to a push:\nentering **blocked** alerts you, and a completed turn — herdr's explicit `done`\n**or** a `working → idle` transition — alerts you as **done**. It debounces\nrepeats per pane and reads config fresh on every event, so changes need no\nrestart. See [ARCHITECTURE.md](./ARCHITECTURE.md) for the design.\n\n## Troubleshooting\n\n- **No notifications?** Run `…doctor` to check server/topic/auth, then `…test`. Set `HERDR_NTFY_DEBUG=1` and read `herdr plugin log list --plugin cobanov.herdr-ntfysh`.\n- **TLS errors** on a self-hosted server → set `HERDR_NTFY_CA_FILE` (preferred) or `HERDR_NTFY_TLS_INSECURE=true`.\n- **Too noisy?** Raise `HERDR_NTFY_DEDUP_WINDOW`, or set `HERDR_NTFY_NOTIFY_ON=blocked`.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eWhy another ntfy plugin?\u003c/b\u003e\u003c/summary\u003e\n\nA ground-up rewrite of the idea behind [zom-2018/herdr-ntfy-notify](https://github.com/zom-2018/herdr-ntfy-notify), built to the quality bar of the first-class herdr plugins:\n\n| | herdr-ntfysh | zom-2018/herdr-ntfy-notify |\n|---|---|---|\n| Language | Go, single static binary | Node `.mjs` |\n| Runtime deps | **none** (Go stdlib only) | `node` + shells out to `curl` |\n| Debounce / dedup | ✅ per-pane, windowed, persisted | ❌ can re-fire |\n| Completion detection | explicit `done` **and** `working → idle` | raw status only |\n| Self-signed TLS | ✅ custom CA **or** insecure toggle | partial |\n| Header safety | ASCII-clean, emoji via ntfy tags | raw emoji in headers |\n| `--doctor` / `--debug` | ✅ | ❌ |\n| Failure policy | never disrupts herdr | unclear |\n| Tests | unit + e2e smoke | unit only |\n\u003c/details\u003e\n\n## License\n\nMIT — see [LICENSE](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcobanov%2Fherdr-ntfysh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcobanov%2Fherdr-ntfysh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcobanov%2Fherdr-ntfysh/lists"}