Ask AI
Ask AI Start conversation ↵

I'm an AI assistant with Grove's codebase and documentation in context.

Ask me anything about Grove.

EXAMPLE QUESTIONS

Know when your agents need attention

Grove's dashboard is pull only. You have to be looking at it, and push notifications close that gap.

Get told when it matters

  • Your phone buzzes when an agent finishes its turn, asks you something, or its workspace breaks.
  • Tap one and you land on that workspace.
  • Grove runs no second status engine. The broker watches the same activity stream the Activity Dashboard already computes for moments worth a buzz.
  • You choose which triggers reach each channel, and everything is off until you turn it on.

What fires a notification

Each trigger has its own switch.

State Meaning Default
waiting The turn finished. The agent may need you. On
blocked The agent is waiting on a permission prompt or a question. On
error The run or init failed. On
idle The agent went quiet. Off
Event Meaning Default
error The workspace hit an error. On
orphaned_detected Its worktree is gone. On
offline_detected Its tmux session vanished. On
created, killed, paused, resumed, respawned Routine lifecycle verbs. Off
  • on lists the agent states that alert, and on_lifecycle lists the workspace events. Routine verbs are off by default.
  • on_question adds the prompt and its options to the alert, so you can answer from the tray.
  • A session already waiting when the daemon starts is recorded without an alert, and a 30 second window stops one state from buzzing twice.
  • Enable it in any layer of the config cascade.

Severity: how loudly it lands

Every notification carries low, normal, high, or urgent severity.

  • A finished turn is normal.
  • A question, blocked state, or workspace error is high.
  • An idle agent or routine lifecycle event is low.
  • Gotify maps severity through priorities from 0 to 10.
  • Webhook maps severity through priorities on ntfy's scale from 1 to 5.

Channels

Delivery is pluggable across two channels today, and secrets never live in config. Each channel holds the name of the environment variable that carries its token, so a committed .grove/config.json stays safe to publish.

Gotify Point Grove at a running Gotify server for OS level push with no extra app. The body is markdown with the agent, the reason, the task and every question option on its own line, and Android opens the workspace on tap.
Webhook A JSON POST to any URL, speaking ntfy's publish format directly, so any relay can consume it. The JSON carries both renderings plus severity, trigger and any open questions with their ids.

Limitations

  • The daemon sends them, so a TUI only setup without the daemon receives no alerts. A down or slow channel is skipped, never retried.
  • Gotify needs an application token rather than a client token. Grove only sends messages.
  • A Gotify push cannot be retracted. A resolved question can remain in your tray.
  • Question alerts need a harness that surfaces the question. Claude Code and Codex questions through an MCP tool work. Codex interactive approval prompts produce no alert.

Enabling it

Add notifications to any configuration layer.

~/.config/grove/config.json
{
  "notifications": {
    "enabled": true,
    "deep_link_base_url": "https://grove.example.com",
    "on": ["waiting", "blocked", "error"],
    "on_question": true,
    "on_lifecycle": ["error", "offline_detected", "orphaned_detected"],
    "gotify": {
      "enabled": true,
      "server_url": "https://gotify.example.com",
      "token_env": "GROVE_GOTIFY_TOKEN",
      "markdown": true,
      "priorities": { "low": 2, "normal": 5, "high": 8, "urgent": 9 }
    },
    "webhook": {
      "enabled": true,
      "url": "https://ntfy.sh",
      "topic": "grove-alerts",
      "token_env": "GROVE_NTFY_TOKEN",
      "priorities": { "low": 2, "normal": 3, "high": 4, "urgent": 5 }
    }
  }
}

Export the tokens in the daemon's environment.

export GROVE_GOTIFY_TOKEN="your-gotify-app-token"
export GROVE_NTFY_TOKEN="your-ntfy-token"   # only if your topic needs auth
  • deep_link_base_url is where your web dashboard is reachable. Its default is http://localhost:3000, which a phone resolves to itself, so set an address your phone can reach, or "" for no link.
  • The Configuration Reference lists every field and default.