Skip to main content

智能 AI 助手会话结束通知系统

Project description

VibeNotification

PyPI Python Platform License

English | 中文

Stop waiting when vibe coding — Give a notification when Claude Code or Codex finishes replies —

Blog walkthrough (Chinese): AI应用系列 一个简单的Vibe coding的通知系统

image-20251221214216954

Installation

  • Stable (PyPI): pip install vibe-notification
  • Dev: pip install -e .
  • Optional venv: python -m venv venv && source venv/bin/activate
  • Verify: python -m vibe_notification --test (should toast and chime when enabled)
  • Interactive setup: python -m vibe_notification --config
    • Default config file: ~/.config/vibe-notification/config.json
    • Make sure both sound and system notifications are enabled

Quick Start

Claude Code

  • Hooks you can use: Stop (on every reply), SessionEnd (when the session ends), SubagentStop (Task tool completes)
  • If you care about the whole Claude Code session actually ending, prefer SessionEnd. Stop is only per-reply.
  • Edit ~/.claude/settings.json and add a Stop hook:
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python -m vibe_notification"
          }
        ]
      }
    ]
  }
}
  • Example full settings snippet with environment variables:
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "env": {
    "ANTHROPIC_AUTH_TOKEN": "xxx",
    "ANTHROPIC_BASE_URL": "https://open.bigmodel.cn/api/anthropic",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.6",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-4.6",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-4.6",
    "ANTHROPIC_MODEL": "glm-4.6",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
    "DISABLE_ERROR_REPORTING": "1",
    "DISABLE_TELEMETRY": "1",
    "MCP_TIMEOUT": "60000"
  },
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "command": "python -m vibe_notification",
            "type": "command"
          }
        ]
      }
    ]
  },
  "includeCoAuthoredBy": false,
  "outputStyle": "engineer-professional"
}
  • Session end only:
{
  "hooks": {
    "SessionEnd": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python -m vibe_notification"
          }
        ]
      }
    ]
  }
}
  • Combine multiple hooks (Stop + SessionEnd):
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python -m vibe_notification"
          }
        ]
      }
    ],
    "SessionEnd": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python -m vibe_notification"
          }
        ]
      }
    ]
  }
}

Codex CLI

Add a notifier command to ~/.codex/config.toml so Codex triggers VibeNotification when the agent actually finishes a turn (agent-turn-complete):

notify = ["python3", "-m", "vibe_notification"]

Note: notify is turn-based, not session-exit-based. As of April 14, 2026, OpenAI's current Codex docs still describe notify and Stop/hook-style events as turn-scoped rather than whole-process-exit signals.

If you only want one notification after the whole Codex session exits, do not rely on notify. Use the built-in wrapper:

python -m vibe_notification --wrap-codex

You can pass normal Codex arguments through unchanged:

python -m vibe_notification --wrap-codex -- --help
python -m vibe_notification --wrap-codex -- -C /path/to/project

If you want this as your everyday entrypoint, add a shell alias such as:

alias codexn='python3 -m vibe_notification --wrap-codex --'

Then launch codexn; VibeNotification will fire only once, after the Codex process actually exits.

To inspect your local integration and spot config/semantic mismatches quickly:

python -m vibe_notification --doctor

Typical placement in config.toml:

model_provider = "xxx"
model = "gpt-5.1-codex-max"
model_reasoning_effort = "medium"
disable_response_storage = true
notify = ["python3", "-m", "vibe_notification"]

[model_providers.xxx]
name = "xxx"
base_url = "https://xxx/v1"
wire_api = "responses"
requires_openai_auth = true

[tui]
notifications = true

Configuration Recipes

Visual only (no sound)

  • Codex ~/.codex/config.toml:
notify = ["python3", "-m", "vibe_notification", "--sound", "0"]
  • Claude Code ~/.claude/settings.json:
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python -m vibe_notification --sound 0"
          }
        ]
      }
    ]
  }
}
  • Quick test:
python -m vibe_notification --sound 0 --test

Sound only (no system toast)

  • Codex:
notify = ["python3", "-m", "vibe_notification", "--notification", "0"]
  • Claude Code:
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python -m vibe_notification --notification 0"
          }
        ]
      }
    ]
  }
}
  • Quick test:
python -m vibe_notification --notification 0 --test

Temporary toggles (environment variables)

  • VIBE_NOTIFICATION_SOUND=0 — mute sound
  • VIBE_NOTIFICATION_NOTIFY=0 — disable system notification
  • VIBE_NOTIFICATION_LOG_LEVEL=DEBUG — enable debug logging; raw Codex payloads are also appended to ~/.config/vibe-notification/debug/codex-events.jsonl

Codex examples:

# Temporarily mute sound
notify = ["env", "VIBE_NOTIFICATION_SOUND=0", "python3", "-m", "vibe_notification"]

# Disable all notifications (for debugging)
notify = ["env", "VIBE_NOTIFICATION_NOTIFY=0", "VIBE_NOTIFICATION_SOUND=0", "python3", "-m", "vibe_notification"]

# Enable debug logging
notify = ["env", "VIBE_NOTIFICATION_LOG_LEVEL=DEBUG", "python3", "-m", "vibe_notification"]

Claude Code example:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "env VIBE_NOTIFICATION_SOUND=0 python -m vibe_notification"
          }
        ]
      }
    ]
  }
}

CLI tests:

VIBE_NOTIFICATION_SOUND=0 python -m vibe_notification --test
VIBE_NOTIFICATION_SOUND=0 VIBE_NOTIFICATION_NOTIFY=0 python -m vibe_notification --test
VIBE_NOTIFICATION_LOG_LEVEL=DEBUG python -m vibe_notification --test

Sound type

Available macOS sound types: Glass (default), Ping, Pop, Tink, Basso.

notify = ["env", "VIBE_NOTIFICATION_SOUND_TYPE=Ping", "python3", "-m", "vibe_notification"]
# Low tone
notify = ["env", "VIBE_NOTIFICATION_SOUND_TYPE=Basso", "python3", "-m", "vibe_notification"]

Claude Code:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "env VIBE_NOTIFICATION_SOUND_TYPE=Pop python -m vibe_notification"
          }
        ]
      }
    ]
  }
}

Test different sounds:

VIBE_NOTIFICATION_SOUND_TYPE=Tink python -m vibe_notification --test
VIBE_NOTIFICATION_SOUND_TYPE=Ping python -m vibe_notification --test

Volume control

Volume range is 0.0–1.0.

notify = ["env", "VIBE_NOTIFICATION_SOUND_VOLUME=0.2", "python3", "-m", "vibe_notification"]
notify = ["env", "VIBE_NOTIFICATION_SOUND_VOLUME=0.5", "python3", "-m", "vibe_notification"]
notify = ["env", "VIBE_NOTIFICATION_SOUND_VOLUME=0", "python3", "-m", "vibe_notification"] # mute

Claude Code:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "env VIBE_NOTIFICATION_SOUND_VOLUME=0.3 python -m vibe_notification"
          }
        ]
      }
    ]
  }
}

Quick test:

VIBE_NOTIFICATION_SOUND_VOLUME=0.1 python -m vibe_notification --test
VIBE_NOTIFICATION_SOUND_VOLUME=0.8 python -m vibe_notification --test

Notification timeout

Edit ~/.config/vibe-notification/config.json:

{
  "enable_sound": true,
  "enable_notification": true,
  "notification_timeout": 5000,
  "sound_type": "Glass",
  "sound_volume": 0.1,
  "log_level": "INFO"
}
  • 5000 = 5s auto-dismiss
  • 10000 = 10s (default)
  • 30000 = 30s
  • 0 = sticky, manual close

Or use the interactive config:

python -m vibe_notification --config

Prebuilt combos

Focus mode (low volume + toast only + short display):

notify = ["env", "VIBE_NOTIFICATION_SOUND_VOLUME=0.1", "VIBE_NOTIFICATION_SOUND_TYPE=Basso", "python3", "-m", "vibe_notification"]

Meeting mode (sound only, louder, specific tone):

notify = ["env", "VIBE_NOTIFICATION_NOTIFY=0", "VIBE_NOTIFICATION_SOUND_VOLUME=0.7", "VIBE_NOTIFICATION_SOUND_TYPE=Ping", "python3", "-m", "vibe_notification"]

Debug mode (all on + debug logs):

notify = ["env", "VIBE_NOTIFICATION_LOG_LEVEL=DEBUG", "python3", "-m", "vibe_notification"]

CLI Reference

Command-line options

Option Type Default Description
event_json positional - Optional Codex event JSON string
--test flag - Send a test notification
--config flag - Interactive configuration
--sound {0,1} choice config value Enable/disable sound (0=off, 1=on)
--notification {0,1} choice config value Enable/disable system notification (0=off, 1=on)
--log-level {DEBUG,INFO,WARNING,ERROR} choice config value Set log level
--version flag - Show version

Config file

Location: ~/.config/vibe-notification/config.json

Key Type Default Description
enable_sound bool true Enable sound
enable_notification bool true Enable system notification
notification_timeout int 10000 Duration in ms
sound_type string "default" Sound type
log_level string "INFO" Log level
detect_conversation_end bool true Detect end of conversation

Environment variables

Env Description Example
VIBE_NOTIFICATION_SOUND Override sound setting VIBE_NOTIFICATION_SOUND=0
VIBE_NOTIFICATION_NOTIFY Override notification setting VIBE_NOTIFICATION_NOTIFY=0
VIBE_NOTIFICATION_LOG_LEVEL Override log level VIBE_NOTIFICATION_LOG_LEVEL=DEBUG

Typical commands

# Test (toast + sound)
python -m vibe_notification --test

# Toast only
python -m vibe_notification --sound 0 --test

# Sound only
python -m vibe_notification --notification 0 --test

# Debug logs
python -m vibe_notification --log-level DEBUG --test

Hook usage examples

Claude Code:

echo '{"toolName": "Bash"}' | python -m vibe_notification
VIBE_NOTIFICATION_SOUND=0 echo '{"toolName": "Task"}' | python -m vibe_notification
VIBE_NOTIFICATION_NOTIFY=0 python -m vibe_notification

Codex:

python -m vibe_notification '{"type":"agent-turn-complete","thread-id":"thread-1","turn-id":"turn-1","cwd":"/tmp/project","input-messages":["fix tests"],"last-assistant-message":"Done"}'
python -m vibe_notification '{"type":"agent-turn-complete","thread-id":"thread-1","turn-id":"turn-1","cwd":"/tmp/project","input-messages":["fix tests"],"last-assistant-message":"Done"}' --notification 1 --sound 0
VIBE_NOTIFICATION_SOUND=1 VIBE_NOTIFICATION_NOTIFY=1 python -m vibe_notification '{"type":"agent-turn-complete","thread-id":"thread-1","turn-id":"turn-1","cwd":"/tmp/project","input-messages":["fix tests"],"last-assistant-message":"Done"}'

Publishing to PyPI

  1. Bump the version in pyproject.toml (single source of truth).
  2. Install tooling: python -m pip install --upgrade build twine.
  3. Build: python -m build (creates .tar.gz and .whl under dist/).
  4. Validate: python -m twine check dist/*.
  5. Upload: TWINE_USERNAME=__token__ TWINE_PASSWORD=<pypi-token> python -m twine upload dist/* (use --repository testpypi to dry run).
  6. Install + verify: pip install -U vibe-notification then python -m vibe_notification --test.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vibe_notification-1.0.13.tar.gz (45.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vibe_notification-1.0.13-py3-none-any.whl (52.3 kB view details)

Uploaded Python 3

File details

Details for the file vibe_notification-1.0.13.tar.gz.

File metadata

  • Download URL: vibe_notification-1.0.13.tar.gz
  • Upload date:
  • Size: 45.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for vibe_notification-1.0.13.tar.gz
Algorithm Hash digest
SHA256 b4e630ad203a441236231ed4704d3c49a6a16f5b8c1f5f274bf03a1b6e1d84b3
MD5 ec1e09ad1067636a902e0be9ab2888c8
BLAKE2b-256 e261ee37854f6c046ad150476bf77822a35dd5caa9173e2bfc44c01ef0f0ec4d

See more details on using hashes here.

File details

Details for the file vibe_notification-1.0.13-py3-none-any.whl.

File metadata

File hashes

Hashes for vibe_notification-1.0.13-py3-none-any.whl
Algorithm Hash digest
SHA256 8c4333c6b4f4b639bc2589fc8799af9686e34e2c3cbbf4abd8d28a92bbb2a8ef
MD5 bef43cd1dc30948a505f6011977bb3b0
BLAKE2b-256 e898b4a5c8473af7441c540061066d67089954a63f2a364d7e9914d4fa0445f8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page