
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
vde-notifier
Advanced tools
vde-notifier is a tmux-aware notification CLI for macOS. It surfaces long-running pane completions, plays a sound, and returns you to the exact session/window/pane with a single notification click.
tmux, vde-notifier-app (default notifier)pnpmvde-notifier is published as a macOS-only npm package (os: darwin, engines.node: >=22).
# install default notifier backend
brew tap yuki-yano/vde-notifier
brew install --cask yuki-yano/vde-notifier/vde-notifier-app
# optional fallback notifier backends
brew install terminal-notifier
brew install yuki-yano/swiftdialog/swift-dialog
# (or download the official pkg from https://github.com/swiftDialog/swiftDialog/releases)
bun x vde-notifier@latest # recommended
npx vde-notifier@latest
pnpm dlx vde-notifier@latest
(Optional) Install globally if you prefer a persistent binary:
bun install --global vde-notifier@latest
npm install -g vde-notifier@latest
pnpm add -g vde-notifier@latest
vde-notifier --title "Build finished" --message "webpack completed"
--title <string>: Override the notification title. Defaults to [session] window.pane (%paneId).--message <string>: Override the notification body. Defaults to cmd: <paneCurrentCommand> | tty: <clientTTY>.--sound <name>: macOS system sound (for example, Glass, Ping). Use None for silence.--codex: Consume Codex-style JSON (see below) from a trailing argument, CODEX_NOTIFICATION_PAYLOAD, or stdin (in that priority order) and build the notification from it.--skip-codex-subagent: Skip sending notifications when Codex payload belongs to a subagent turn (thread-id lookup from ~/.codex/sessions).--skip-codex-non-interactive: Skip sending notifications for Codex non-interactive turns (source: "exec" in ~/.codex/sessions, such as codex exec / codex review).--claude: Consume Claude Code JSON piped on stdin (supports transcript_path to pull the latest assistant reply).--skip-claude-non-interactive: Skip sending notifications when Claude non-interactive (-p/--print --output-format json) payloads are detected.--terminal <profile>: Force a terminal profile (alacritty, wezterm, ghostty, etc.).--term-bundle-id <bundleId>: Override the bundle identifier when auto detection is insufficient.--notifier <terminal-notifier|swiftdialog|vde-notifier-app>: Switch the notification backend. Defaults to vde-notifier-app.--dry-run: Skips sending a notification. Combine with --verbose to print the gathered tmux metadata and focus command.--verbose: Emits JSON logs describing notify and focus stages.--log-file <path>: Appends the same JSON diagnostics to the given file (one JSON object per line). Also propagates to focus-mode invocations.-- <command> [args...]: After sending the notification, execute another command and forward runtime arguments to it. With --codex, the resolved payload is also forwarded as the final argument.--help, -h: Show usage.--version, -v: Show CLI version.Short option bundling (for example, -hv) is intentionally unsupported.
When --notifier swiftdialog is selected, vde-notifier plays the requested sound locally and then sends dialog --notification ... with a primary action wired to the focus command. Clicking the notification will restore the tmux pane.
When --notifier vde-notifier-app is selected, vde-notifier calls the local Swift agent (vde-notifier-app notify ...) with action executable and arguments so notification clicks can restore the tmux pane without shell interpolation.
vde-notifier-app via Caskbrew tap yuki-yano/vde-notifier
brew install --cask yuki-yano/vde-notifier/vde-notifier-app
vde-notifier-app doctor
vde-notifier-app agent status
vde-notifier --title "Build finished" --message "Done" --sound Ping
vde-notifier-app notify --title "swift smoke" --message "click me" --sound Ping --action-exec /usr/bin/say --action-arg "clicked"
Environment overrides:
VDE_NOTIFIER_TERMINAL=alacritty sets the default terminal profile when --terminal is omitted.
Valid aliases: terminal, apple-terminal, mac-terminal, iterm, iterm2, alacritty, kitty, wezterm, hyper, ghostty (non-matching values fall back to Terminal.app).VDE_NOTIFIER_LOG_FILE=/path/to/diagnostics.log mirrors --log-file so every run writes diagnostics even without passing the CLI flag.export VDE_NOTIFIER_TERMINAL=alacritty
make build && vde-notifier --title "Build" --message "Done" --sound Ping
switch-client, select-window, select-paneMany hosted IDE agents run inside tmux. You can add a notification step after long tasks so the human operator gets paged immediately:
vde-notifier hydrates notifications from agent payloads in two ways:
--codex: pass a Codex-style JSON payload as the final argument (the format used by hosted Codex agents). You can also preload the same JSON via CODEX_NOTIFICATION_PAYLOAD; if neither is present, stdin is used.--claude: pipe Claude Code's JSON payload to stdin. If the payload contains transcript_path, vde-notifier opens the referenced transcript JSONL file and uses the latest assistant message.When using command chaining (-- <command> [args...]) with --codex, vde-notifier resolves the Codex payload from the final argument, CODEX_NOTIFICATION_PAYLOAD, or stdin using the same priority as notification generation. It sends the notification first, then executes the chained command with the same forwarded arguments and appends the resolved payload as the final argument when it came from the environment or stdin. If the final forwarded argument already is the payload JSON, it is reused and not appended twice.
Codex notifications always use the repository-scoped title Codex: <repo-name>, ignoring payload-provided titles. Claude notifications fall back to Claude: <repo-name> when no explicit title is supplied.
If either payload is malformed JSON, the command exits with a non-zero status.
For either flag the CLI looks for:
notification-title, notification_title, title)notification-message, notification_message, last-assistant-message, message, messages, transcript, or Claude transcripts)sound, respecting none, default, or full paths such as /System/Library/Sounds/Ping.aiff)thread-id, thread_id, threadId) to support --skip-codex-subagent / --skip-codex-non-interactive (via ~/.codex/sessions lookup)type: "result", subtype, result)Stop / SubagentStop hook payloads when the parent Claude process is running with -p / --printTo enable automatic notifications from Codex CLI/agents, add the following to ~/.codex/config.toml:
notify = ["bun", "x", "vde-notifier@latest", "--codex"]
If you also want to run another command from the same notify hook while keeping the same Codex payload for the chained command:
notify = ["bun", "x", "vde-notifier@latest", "--codex", "--", "other-command"]
At runtime this behaves like:
bun x vde-notifier@latest --codex -- other-command '{"message":"..."}'
The chained command receives the same resolved payload even when the notify hook supplied it via CODEX_NOTIFICATION_PAYLOAD or stdin. If you already passed the payload as the final forwarded argument, vde-notifier keeps the existing argument list unchanged.
For Claude Code (Claude Desktop) projects, add a Stop hook to ~/.config/claude/settings.json so every long-running tool run triggers a notification when it finishes:
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "bun x vde-notifier@latest --claude"
}
]
}
]
}
}
NPM publish and app/cask release are separated.
Workflow:
.github/workflows/publish.ymlTrigger:
npm-v* (example: npm-v0.1.1)package.json (for example, npm-v0.1.1 with "version": "0.1.1").Example:
git tag npm-v0.1.1
git push origin npm-v0.1.1
publish.yml also verifies that the target version is not already on npm and publishes with provenance (npm publish --provenance).
vde-notifier-app cask distribution expects this fixed asset name on yuki-yano/vde-notifier releases:
VdeNotifierApp.app.tar.gzRelease automation is defined in:
.github/workflows/release-vde-notifier-app.ymlThe workflow:
VdeNotifierApp.app.tar.gz on the target release tag.repository_dispatch to yuki-yano/homebrew-vde-notifier so cask version and sha256 are updated automatically.Repository secret required in yuki-yano/vde-notifier:
HOMEBREW_TAP_DISPATCH_TOKEN: token with write permission to yuki-yano/homebrew-vde-notifier.git tag app-v0.1.1
git push origin app-v0.1.1
release-vde-notifier-app workflow to complete.VdeNotifierApp.app.tar.gz.yuki-yano/homebrew-vde-notifier receives an update-cask run and commits updated version/sha256.If you need to regenerate the asset for an existing tag, run the workflow manually (workflow_dispatch) and set:
tag: app-v0.1.1 (existing app tag)If tap update does not run automatically, manually trigger update-cask.yml in
yuki-yano/homebrew-vde-notifier with the same app version (without app-v)
and the SHA256 of VdeNotifierApp.app.tar.gz.
Before tagging, you can build the exact release asset locally:
pnpm run swift:release-asset
/System/Library/Sounds/ and is not set to None.vde-notifier-app command is missing: Install the default notifier backend:
brew tap yuki-yano/vde-notifier && brew install --cask yuki-yano/vde-notifier/vde-notifier-app--verbose to inspect payload and focus command. Confirm osascript automation permission is granted.vde-notifier-app doctor stays notDetermined: Rebuild the app bundle (pnpm run swift:app) and verify the signature identifier (codesign -dv --verbose=4 build/VdeNotifierApp.app 2>&1 | rg '^Identifier=') is com.yuki-yano.vde-notifier-app.agent.bunx dlx or AI agents: If launched via package runners, vde-notifier reuses the current process.execPath so focus mode can start without PATH access.pnpm installpnpm run lintpnpm run testpnpm run pack:checkpnpm run buildpnpm run devpnpm run swift:testpnpm run swift:buildpnpm run swift:appFAQs
tmux focus notification CLI for macOS
The npm package vde-notifier receives a total of 12 weekly downloads. As such, vde-notifier popularity was classified as not popular.
We found that vde-notifier demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.