From 730d56c0f96caa7fe5f6e5d84070dd830684b736 Mon Sep 17 00:00:00 2001 From: Gabriel Tavares Date: Sat, 23 May 2026 20:18:29 +0100 Subject: [PATCH 1/2] claude-code-hermit: push_notifications defaults to true, derived from channel choice in /hatch Removes the explicit push opt-in question from both Quick and Advanced wizards. /hatch now derives push_notifications from the channel choice: false when any channel is configured (channel is the doorbell), true when no channel is configured (push is the only doorbell). Re-init leaves the existing value untouched to preserve manual toggles. Flips the global default in config.json.template and hermit-start.py so legacy installs without the field also resolve to true at boot. --- plugins/claude-code-hermit/CHANGELOG.md | 6 +++++ .../docs/config-reference.md | 2 +- .../scripts/hermit-start.py | 2 +- .../claude-code-hermit/skills/hatch/SKILL.md | 26 ++++++------------- .../skills/hermit-evolve/SKILL.md | 2 +- .../skills/hermit-settings/SKILL.md | 6 ++--- .../state-templates/config.json.template | 2 +- 7 files changed, 21 insertions(+), 25 deletions(-) diff --git a/plugins/claude-code-hermit/CHANGELOG.md b/plugins/claude-code-hermit/CHANGELOG.md index c17c009c..65fdca3a 100644 --- a/plugins/claude-code-hermit/CHANGELOG.md +++ b/plugins/claude-code-hermit/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased] + +### Changed + +- **hatch: push_notifications now defaults to true** — `/hatch` derives the flag from the channel choice (no channel → true, channel configured → false) and the explicit opt-in question is removed from both Quick and Advanced wizards. Existing installs without the field now also resolve to `true` at boot in `hermit-start.py` for a consistent global default. Toggle via `/hermit-settings push-notifications`. + ## [1.1.3] - 2026-05-23 ### Fixed diff --git a/plugins/claude-code-hermit/docs/config-reference.md b/plugins/claude-code-hermit/docs/config-reference.md index e9733615..7777f6f2 100644 --- a/plugins/claude-code-hermit/docs/config-reference.md +++ b/plugins/claude-code-hermit/docs/config-reference.md @@ -23,7 +23,7 @@ Full schema for `.claude-code-hermit/config.json`. Generated by `/claude-code-he | `auto_session` | boolean | `true` | Auto-start session on boot. | | `boot_skill` | string \| null | `null` | Overrides the default `/claude-code-hermit:session` bootstrap that `hermit-start.py` sends into the tmux REPL on always-on launch. Set to a namespaced skill (e.g. `"/claude-code-homeassistant-hermit:ha-boot"`) to run a domain hermit's custom boot. The domain skill is responsible for calling `/claude-code-hermit:session-start` itself. Populated automatically by `/hatch` when an activated hermit declares `hermit.boot_skill` in its `.claude-plugin/hermit-meta.json`; operators can override via `/hermit-settings boot-skill`. | | `always_on` | boolean | `false` | Set to `true` by `hermit-start`. Affects routine framing and channel behavior. | -| `push_notifications` | boolean | `false` | If `true`, fires `PushNotification` (desktop notification, plus mobile push if Remote Control is connected) on proactive alerts when no channel is enabled, when a configured channel is unreachable (missing pairing/`dm_channel_id`, empty `allowed_users`), or as a last-resort signal if a successful resolve's reply call fails. In always-on Docker / headless tmux only the Remote Control mobile push is visible. Push is one-way — operator→hermit replies still need a channel. Toggle via `/hermit-settings push-notifications`. | +| `push_notifications` | boolean | `true` | If `true`, fires `PushNotification` (desktop notification, plus mobile push if Remote Control is connected) on proactive alerts when no channel is enabled, when a configured channel is unreachable (missing pairing/`dm_channel_id`, empty `allowed_users`), or as a last-resort signal if a successful resolve's reply call fails. In always-on Docker / headless tmux only the Remote Control mobile push is visible. Push is one-way — operator→hermit replies still need a channel. Toggle via `/hermit-settings push-notifications`. | | `quality_gate` | object | `{"tier": "budget"}` | Post-implementation quality gate at step (e.5) of `/proposal-act`. `tier` is one of: `"budget"` (never runs `/claude-code-hermit:simplify`; default), `"balanced"` (delegates to the `quality-gate-judge` haiku subagent per-implementation), `"quality"` (always runs `/claude-code-hermit:simplify`). Cost per implementation: Budget = $0, Balanced ≈ $0.005 (judge) + occasional ~$0.25 (`/simplify` on RUN), Quality ≈ $0.25-$0.35. Anything outside the enum or a missing key resolves to `budget` at runtime (default-safe). Tune via `/hermit-settings quality-gate`. **Note:** if you use `claude-code-dev-hermit:dev-quality` to gate commits, keep `tier: "budget"` to avoid double-firing `/simplify` (`/dev-quality` already runs it pre-commit). | --- diff --git a/plugins/claude-code-hermit/scripts/hermit-start.py b/plugins/claude-code-hermit/scripts/hermit-start.py index bcc16d88..3b94daa3 100755 --- a/plugins/claude-code-hermit/scripts/hermit-start.py +++ b/plugins/claude-code-hermit/scripts/hermit-start.py @@ -42,7 +42,7 @@ 'ask_budget': False, 'always_on': False, 'chrome': False, - 'push_notifications': False, + 'push_notifications': True, 'idle_behavior': 'discover', 'idle_budget': '$0.50', 'routines': [ diff --git a/plugins/claude-code-hermit/skills/hatch/SKILL.md b/plugins/claude-code-hermit/skills/hatch/SKILL.md index 2d75ba9f..068f292b 100644 --- a/plugins/claude-code-hermit/skills/hatch/SKILL.md +++ b/plugins/claude-code-hermit/skills/hatch/SKILL.md @@ -287,11 +287,8 @@ questions: [ ] ``` -- **If None:** record `channels: {}`. Ask one follow-up before proceeding to Phase 6: - > "Send a PushNotification on proactive alerts (desktop notification in your terminal app, plus mobile push if Remote Control is connected)? Note: in always-on Docker or headless tmux without a host-terminal surface, only the Remote Control mobile push will be visible. Note: push is one-way — operator → hermit replies (micro-proposals, session-recovery prompts) need a channel. (yes / no) [no]" - - Set `push_notifications: true` on yes; leave at default `false` on no. Then proceed to Phase 6. Do not ask channel follow-ups. -- **If Discord or Telegram:** create a channel entry under the `channels` object (e.g., `channels.discord`). Boot script maps the key to the full plugin identifier. Then ask follow-ups below — including the push fallback follow-up at the end (push covers configured-but-unpaired states and recovers if the channel later breaks). +- **If None:** record `channels: {}`. Proceed to Phase 6. Do not ask channel follow-ups. +- **If Discord or Telegram:** create a channel entry under the `channels` object (e.g., `channels.discord`). Boot script maps the key to the full plugin identifier. Then ask follow-ups below. - Channel plugins require Bun and manual setup (bot creation, token, pairing). After saving the preference to `config.json`, note: > **Channel preference saved.** Activation depends on how you run hermit: @@ -326,10 +323,6 @@ questions: [ - **Access control:** If "Restrict" and a numeric ID was typed via Other, record in `channels..allowed_users` as `[""]`. If "Allow everyone" or no ID provided, omit the key (absent = accept all). Note: "Add more user IDs later with `/claude-code-hermit:hermit-settings channels`. An empty array [] blocks all messages." - **Morning brief:** If "Yes — 07:00", record as `channels..morning_brief: { "enabled": true, "time": "07:00" }`. If "No", omit the key (or set to `null`). -- **Push fallback (asked AFTER the two channel follow-ups above):** - > "Also enable PushNotification as a last-resort fallback if the channel becomes unreachable (e.g. pairing lost, token expired)? (yes / no) [no]" - - Set `push_notifications: true` on yes; leave at default `false` on no. This covers the configured-but-unpaired window after `/hatch` and any later channel breakage. #### Phase 6 — Deployment (AskUserQuestion batch, 3 questions) @@ -404,7 +397,7 @@ For routines — if Yes: use the config defaults (`active_hours.start = 08:00`, 5. **Overlay operator choices** from the wizard: - From Phase 2: `agent_name`, `language`, `timezone`, `sign_off`. - From Phase 3: `escalation`, `remote`, `ask_budget`, `idle_behavior`. - - From Phase 5: `channels.` populated per Phase 5 rules (state_dir, allowed_users, morning_brief). Set `push_notifications` from the Phase 5 opt-in follow-up (asked for all three channel choices — None, Discord, Telegram). + - From Phase 5: `channels.` populated per Phase 5 rules (state_dir, allowed_users, morning_brief). Set `push_notifications` from the Phase 5 channel choice on **fresh hatch only**: `false` if any channel was selected (channel is the doorbell); `true` if None (push is the doorbell). On re-init (`is_reinit == true`), do **not** re-derive — leave the existing `push_notifications` value untouched, same as any field the wizard didn't ask about. This preserves a manual `/hermit-settings push-notifications` toggle across re-inits. This rule is shared with Quick Turn 3 (Quick is fresh-only by Step 1.6's gate, so the re-init carve-out only affects Advanced). - From Phase 6: `permission_mode`; append routines (morning, evening) if enabled — heartbeat-restart is already in the template. - From Phase 4: append `scheduled_checks` entries per the per-plugin mapping in Phase 4 (only `claude-code-setup` and `claude-md-management` contribute — 3 entries total when both selected; `skill-creator` and `feature-dev` add zero entries). 6. **Write merged object** as `.claude-code-hermit/config.json`. @@ -835,10 +828,7 @@ questions: [ Record `sign_off`, `deployment` (one of `docker` / `tmux` / `interactive`), `channel` (one of `none` / `discord` / `telegram`). -Ask one follow-up before the confirm bundle (asked for ALL channel choices — None, Discord, Telegram — since push covers both the no-channel and configured-but-unreachable cases): -> "Send a PushNotification as fallback when the channel is unreachable (desktop notification in your terminal app, plus mobile push if Remote Control is connected)? In always-on Docker / headless tmux only the Remote Control mobile push will be visible. (yes / no) [no]" - -Record `push_notifications: true` on yes, `false` on no. +`push_notifications` is derived from Turn 3's channel choice in Step 5 — no follow-up question. Set to `false` if any channel was selected, `true` if None. **Derived values from this turn (used in the confirm bundle and Step 5 overlay):** - `permission_mode`: `auto` (same default for both Docker and non-Docker deployments). Requires CC 2.1.148+ and Max/Team/Enterprise/API plan — not on Pro or Haiku. If the operator is on an ineligible plan, they'll see an "unavailable" error at launch and should run `/hermit-settings permissions` to switch to `acceptEdits`. @@ -863,7 +853,7 @@ Quick setup will apply: Plugins: all 4 installed Routines: morning 08:30, evening 22:30, heartbeat 04:00 Channel: {channel or None} (allow-everyone; token + pairing later) - Push fallback: {enabled | disabled} + Push notifications: {enabled | disabled} Hermit ext: {activated or none} Visibility: {.local — plugin installed at scope | committed — plugin installed at project scope} Files: {CLAUDE.local.md | CLAUDE.md}, .gitignore, {.claude/settings.local.json | .claude/settings.json} @@ -872,7 +862,7 @@ Quick setup will apply: Customize restarts the wizard from scratch; your Quick answers won't carry over. ``` -The `Visibility:` and `Files:` lines are dynamic based on `hatch_target`. The `Push fallback:` line is always shown (push applies to both empty-channel and configured-but-unreachable states). +The `Visibility:` and `Files:` lines are dynamic based on `hatch_target`. The `Push notifications:` line is always shown (derived from the Channel: choice — enabled when Channel is None, disabled when a channel was selected). Ask: @@ -902,7 +892,7 @@ Quick replaces Step 4 entirely and applies these defaults silently at the shared | Advanced Phase 4 equivalent | plugins + scheduled_checks | install all 4; write 3 scheduled_checks entries per Phase 4 mapping | | Advanced Phase 4b equivalent | `.baseline-pending` marker | same eligibility check as Advanced | | Advanced Phase 5 equivalent | channels..* | state_dir + enabled + dm_channel_id=null; omit allowed_users + morning_brief | -| Quick Turn 3 follow-up | push_notifications | from the Turn 3 follow-up (asked for all channel choices) | +| Quick Turn 3 channel choice | push_notifications | derived: true if channel = None, false if any channel selected | | Advanced Phase 6 equivalent | permission_mode, routines | permission_mode = `auto`; routines = morning 08:30 + evening 22:30 + (template) heartbeat 04:00 | | Step 6 | CLAUDE.md / CLAUDE.local.md append | apply silently to `hatch_target` file (default "keep" if marker already present) | | Step 7 | .gitignore append | apply silently (per-line idempotent) | @@ -953,7 +943,7 @@ Identity: Config: Plugins: claude-code-setup, claude-md-management, skill-creator, feature-dev Channels: none - Push fallback: {enabled | disabled} + Push notifications: {enabled | disabled} Budget prompts: enabled Morning brief: disabled Heartbeat: disabled diff --git a/plugins/claude-code-hermit/skills/hermit-evolve/SKILL.md b/plugins/claude-code-hermit/skills/hermit-evolve/SKILL.md index 52bf927a..ba66eb28 100644 --- a/plugins/claude-code-hermit/skills/hermit-evolve/SKILL.md +++ b/plugins/claude-code-hermit/skills/hermit-evolve/SKILL.md @@ -88,7 +88,7 @@ For each new key, check the table below. If the key is interactive, ask the oper **Silent keys** (add with default if missing): - `always_on` (0.0.1): `false` | `auto_session` (0.0.1): `true` - `model` (0.0.1): `"sonnet"` | `permission_mode` (0.0.1): `"auto"` | `ask_budget` (0.0.1): `false` -- `tmux_session_name` (0.0.1): `"hermit-{project_name}"` | `chrome` (0.0.1): `false` | `push_notifications` (1.1.2): `false` +- `tmux_session_name` (0.0.1): `"hermit-{project_name}"` | `chrome` (0.0.1): `false` | `push_notifications` (1.1.2): `true` - `channels` (0.0.1): `{}` | `monitors` (0.3.14): `[]` - `heartbeat.waiting_timeout` (0.3.0): `null` | `heartbeat.stale_threshold` (0.0.9): `"2h"` - `idle_budget` (0.0.9): `"$0.50"` | `routines` (0.0.9): `[]` diff --git a/plugins/claude-code-hermit/skills/hermit-settings/SKILL.md b/plugins/claude-code-hermit/skills/hermit-settings/SKILL.md index e8b20696..185c2b6b 100644 --- a/plugins/claude-code-hermit/skills/hermit-settings/SKILL.md +++ b/plugins/claude-code-hermit/skills/hermit-settings/SKILL.md @@ -31,7 +31,7 @@ View or modify the hermit configuration for this project. /claude-code-hermit:hermit-settings scheduled-checks — manage scheduled plugin skill checks /claude-code-hermit:hermit-settings boot-skill — view/clear/change the always-on boot skill /claude-code-hermit:hermit-settings quality-gate — set post-implementation /claude-code-hermit:simplify gate tier (budget|balanced|quality) -/claude-code-hermit:hermit-settings push-notifications — toggle PushNotification fallback (fires when no channel is enabled or a configured channel is unreachable) +/claude-code-hermit:hermit-settings push-notifications — toggle PushNotification (default-on doorbell when no channel; fires when no channel is enabled or a configured channel is unreachable) ``` ## Plan @@ -362,8 +362,8 @@ Note: if you have `claude-code-dev-hermit:dev-quality` installed and you commit **If argument is "push-notifications":** Ask: "Send a PushNotification (desktop notification in your terminal app, plus mobile push if Remote Control is connected) on proactive alerts? Fires when no channel is enabled OR a configured channel is unreachable (missing pairing, empty allowed_users, all-disabled). In always-on Docker or headless tmux only the Remote Control mobile push will be visible. Note: push is one-way; operator-→hermit replies (micro-proposals, session recovery) require a channel. - on — enable push fallback - off — disable push fallback + on — enable push notifications + off — disable push notifications [current: ]" Update `push_notifications` in config.json (`true` for on, `false` for off). diff --git a/plugins/claude-code-hermit/state-templates/config.json.template b/plugins/claude-code-hermit/state-templates/config.json.template index 0dd4c134..95f5ac81 100644 --- a/plugins/claude-code-hermit/state-templates/config.json.template +++ b/plugins/claude-code-hermit/state-templates/config.json.template @@ -14,7 +14,7 @@ "ask_budget": false, "always_on": false, "chrome": false, - "push_notifications": false, + "push_notifications": true, "idle_behavior": "discover", "idle_budget": "$0.50", "routines": [ From e35f3f4bf435c5611418cd64169b5e093b590536 Mon Sep 17 00:00:00 2001 From: Gabriel Tavares Date: Sat, 23 May 2026 20:38:01 +0100 Subject: [PATCH 2/2] claude-code-hermit: tighten push_notifications CHANGELOG, add upgrade instructions --- plugins/claude-code-hermit/CHANGELOG.md | 6 +++++- plugins/claude-code-hermit/skills/hermit-settings/SKILL.md | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/claude-code-hermit/CHANGELOG.md b/plugins/claude-code-hermit/CHANGELOG.md index 65fdca3a..be929fd6 100644 --- a/plugins/claude-code-hermit/CHANGELOG.md +++ b/plugins/claude-code-hermit/CHANGELOG.md @@ -4,7 +4,11 @@ ### Changed -- **hatch: push_notifications now defaults to true** — `/hatch` derives the flag from the channel choice (no channel → true, channel configured → false) and the explicit opt-in question is removed from both Quick and Advanced wizards. Existing installs without the field now also resolve to `true` at boot in `hermit-start.py` for a consistent global default. Toggle via `/hermit-settings push-notifications`. +- **hatch: push_notifications now defaults to true** — derived from channel choice in `/hatch` (no channel → on, channel → off); explicit opt-in removed. Toggle via `/hermit-settings push-notifications`. + +### Upgrade Instructions + +1. If `push_notifications` is absent from `config.json`, set it to `true` and notify the operator: "`push_notifications` now defaults to `true` — you'll get a desktop/Remote Control push when no channel is enabled or a configured channel is unreachable. Run `/hermit-settings push-notifications off` to disable." If the key is already present, leave it untouched. ## [1.1.3] - 2026-05-23 diff --git a/plugins/claude-code-hermit/skills/hermit-settings/SKILL.md b/plugins/claude-code-hermit/skills/hermit-settings/SKILL.md index 185c2b6b..555e4b71 100644 --- a/plugins/claude-code-hermit/skills/hermit-settings/SKILL.md +++ b/plugins/claude-code-hermit/skills/hermit-settings/SKILL.md @@ -31,7 +31,7 @@ View or modify the hermit configuration for this project. /claude-code-hermit:hermit-settings scheduled-checks — manage scheduled plugin skill checks /claude-code-hermit:hermit-settings boot-skill — view/clear/change the always-on boot skill /claude-code-hermit:hermit-settings quality-gate — set post-implementation /claude-code-hermit:simplify gate tier (budget|balanced|quality) -/claude-code-hermit:hermit-settings push-notifications — toggle PushNotification (default-on doorbell when no channel; fires when no channel is enabled or a configured channel is unreachable) +/claude-code-hermit:hermit-settings push-notifications — toggle PushNotification doorbell (fires when no channel is enabled or a configured channel is unreachable) ``` ## Plan