Skip to content

About

Desktop notifications for Command Code on macOS, Linux and Windows. Published as-is.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

command-notify

Desktop notifications for Command Code: know when the agent needs you or finishes a run while you work in another application.

Published as-is, not actively maintained. Issues and pull requests are welcome but may not get a response, and security reports are not handled. It is MIT licensed: fork it, fix it, and republish it freely.

Beta. This mod depends on Command Code's experimental Mods API, which may change and break compatibility. It was tested on macOS and Linux desktops with Command Code 1.82. Native Windows delivery is implemented but untested; if it works or fails for you, an issue saying so helps the next person.

Install

Requires Command Code and Node.js 22.6 or newer. Install the mod through Command Code's package manager, which also installs its notification dependency. There is no separate build or custom installer.

macOS

cmd mods add -g command-notify@beta
cmd

The package includes terminal-notifier through its node-notifier dependency. If alerter is already installed it takes priority; otherwise the bundled helper is used, with macOS's osascript as a final fallback. No Homebrew package is required for the default installation. Allow the notification sender in System Settings → Notifications, and check Focus settings if banners are hidden.

Windows (native x64/x86)

In PowerShell:

cmdc mods add -g command-notify@beta
cmdc

Windows uses cmdc, because cmd is the Windows command shell. See Command Code on Windows. The matching SnoreToast helper ships through node-notifier; no PowerShell notification script or separate helper download is required. Enable notifications for its sender in Windows Settings and check Do not disturb.

Windows ARM64 and Windows toasts from WSL are not supported by this beta. The helper's default application identity must work on the desktop; that behavior still needs real Windows verification. Leave windowsAppId at null unless you already have a registered application identity. The mod does not register a custom identity or create a branded Start Menu shortcut.

Linux (native desktop)

Install notify-send if it is missing, using your distribution's package manager:

# Debian / Ubuntu
sudo apt install libnotify-bin

# Fedora
sudo dnf install libnotify

# Arch Linux
sudo pacman -S libnotify

Then, from a terminal inside your desktop session:

cmd mods add -g command-notify@beta
cmd

A working desktop notification service is required. X11 and Wayland environments are supported by the delivery path, but actual desktop behavior remains unverified. SSH, containers, and WSL are outside this beta's supported scope; notifications are not forwarded to another machine or to the Windows host.

Installation scope and updates

-g installs for your user across projects. Omit it to install only for the current Git project; project mods load after the workspace is trusted. Restart any existing Command Code session after installation.

To refresh the beta source:

cmd mods update

On Windows use cmdc mods update. This command updates/reconciles configured mod sources, not just this mod. To pin a release instead, install an exact version such as command-notify@1.0.0-beta.3 in place of command-notify@beta.

Use it

Chat normally in Command Code, then switch to another application. There is no separate notification test step. The first session that creates the settings file shows a non-blocking notice with its location.

A notification is titled Command Code and identifies the session by its title, or the project folder name before a title exists. Linux includes that context in the body because its helper has no subtitle field.

Event What to expect
Agent asks a question Needs your input in interactive sessions.
Agent requests permission Needs approval: <tool>, with risk information when supplied.
Run finishes Finished with a short result excerpt when available.
Turn limit or mod stop hook ends a run Stopped at the turn cap or Stopped early (mod).
Run fails Failed: <message>.
Interruption An interruption notification when the host's event path reports one; duplicate outcomes are suppressed.

Question and permission alerts rely on events from the interactive Command Code UI. Headless runs can report outcomes, but do not expose the same prompt events. Background sub-agent completions are not separately announced. Pending alerts are removed or replaced where the backend supports it; completion alerts are left in the desktop's control. Bodies are shortened to about 150 characters. Notifications can contain project names, result excerpts, tool names, and error text; your OS may show those on the lock screen.

Delivery, sounds, expiry, and visibility depend on OS permissions, Focus/Do not disturb, desktop policy, and the selected helper. A successfully started helper cannot prove a banner appeared. Notification failures should produce a concise notice in Command Code, with the settings path and a recovery step, without interrupting the agent's work. Repeated identical problems are reported once per loaded mod instance.

Settings

Settings are per user, even when the mod is installed for one project:

Platform File
macOS / Linux ~/.commandcode/notify.json
Windows %USERPROFILE%\.commandcode\notify.json ($HOME\.commandcode\notify.json in PowerShell)

The mod creates the file with defaults when it first loads. Existing files are preserved. Edit it in any text editor; settings are reread for each notification. Use valid JSON, without comments. Missing fields keep their defaults. An invalid field uses its default and produces a warning; unreadable or malformed JSON uses the last valid settings, or defaults, and is never silently overwritten.

{
  "enabled": true,
  "backend": "auto",
  "questionFallback": "off",
  "questionText": "generic",
  "focusTerminalOnClick": true,
  "suppressWhenTerminalFocused": false,
  "replacePendingNotifications": true,
  "clearOnResolve": true,
  "quietHours": {
    "enabled": false,
    "start": "22:00",
    "end": "08:00",
    "bypassEvents": []
  },
  "debug": false,
  "debugVerbose": false,
  "alerterPath": null,
  "windowsAppId": null,
  "events": {
    "question": {"enabled": true, "sound": "Submarine", "timeout": 0},
    "permission": {"enabled": true, "sound": "Submarine", "timeout": 0},
    "done": {"enabled": true, "sound": "Glass", "timeout": 10},
    "error": {"enabled": true, "sound": "Basso", "timeout": 10}
  }
}
Setting Meaning
enabled Enable or disable all notifications.
backend auto (recommended), alerter, terminal-notifier, osascript, notify-send, or snoretoast. An unavailable choice warns and falls back to this platform's automatic order.
events.<event>.enabled Enable each of question, permission, done, and error independently.
events.<event>.sound macOS sound name or none. Windows maps any name to its default notification sound; Linux sound selection is unsupported.
events.<event>.timeout Requested seconds until dismissal. 0 passes no explicit timeout; it does not guarantee a persistent banner. Windows and osascript ignore this setting; Linux/macOS desktop policy may override it.
questionFallback off or tool_queued. The latter uses queued ask-tool events if a host version does not deliver question interaction events. It never enables itself.
questionText generic (recommended) or heuristic. Heuristic text can associate the wrong question header because host events lack correlation IDs.
focusTerminalOnClick macOS only: bring the terminal that raised a notification forward when you click it. No effect on Linux or Windows. See Click to focus.
suppressWhenTerminalFocused macOS only: suppress alerts while a recognized terminal is frontmost. A failed focus lookup allows delivery.
replacePendingNotifications Replace earlier pending alerts and earlier outcomes from the same run when supported. Outcomes from different runs are retained.
clearOnResolve Attempt to clear question/permission alerts after resolution. Run settlement always attempts to clear pending alerts, even when this is false. Removal is best effort.
quietHours.enabled Enable scheduled suppression.
quietHours.start / end Local 24-hour HH:MM; start inclusive, end exclusive. Overnight windows work; equal times suppress nothing.
quietHours.bypassEvents Event classes allowed through quiet hours, such as ["error"]. Does not bypass global disablement.
alerterPath macOS executable path override, or null to search PATH.
windowsAppId Already registered Windows application identity, or null for the helper's default.
debug Write diagnostic metadata to notify-debug.log beside the settings file. Off by default.
debugVerbose With debug, include helper arguments and notification text in that log. Off by default; avoid sharing verbose logs unredacted.

Change settings from a conversation

These commands save to the same user settings file:

Plain /notify shows the settings file location and available settings commands.

Command Effect
/notify on / /notify off Enable or disable notifications.
/notify backend auto Restore automatic backend choice and reset failure tracking. A specific backend name is also accepted.
/notify sound done none Silence completion alerts; substitute another event or sound name.
/notify timeout done 10 Request a ten-second completion banner; off passes no timeout.
/notify quiet-hours on 22:00 08:00 Enable an overnight quiet window.
/notify quiet-hours off Disable quiet hours.

Invalid command arguments change nothing. Setters refuse to overwrite malformed JSON. A lock prevents simultaneous sessions from overwriting each other's edits; if a write cannot obtain it, a notice explains the failure. Remove a leftover notify.json.lock only after closing all Command Code sessions that may write it.

Session overrides

Command Code's --mod-option flags override the file for that session:

cmd --mod-option enabled=false
cmd --mod-option sound=none

Use cmdc on Windows. Available flags are enabled=true|false, backend=<name>, sound=<name|none>, timeout=<seconds|off>, and debug=true|false. Sound and timeout flags affect every event class. A settings command tells you when a launch flag still overrides the saved value. Flag names are shared with other mods; prefer the JSON file if another mod uses these names.

Platform differences

Platform/helper Sound Expiry Clear pending alert Click to terminal
macOS: alerter Named or silent Requested Best effort Yes, while the session runs
macOS: bundled terminal-notifier Named or silent Requested Best effort Yes
macOS: osascript fallback Named or silent OS-controlled No No
Linux: notify-send No selection Desktop may ignore No No
Windows: bundled SnoreToast Default or silent OS-controlled Best effort No

macOS automatic order is alerter → terminal-notifier → osascript. Linux uses notify-send; Windows uses the helper matching the running Node.js architecture (x64 or ia32). Helpers for other platforms are never executed. Linux notifications escape markup characters; rendering may differ by desktop. Some macOS helpers can remain alive while waiting for interaction. Each loaded mod limits sticky helpers to 16; admitting another stops the oldest first, which may end its banner. If it cannot stop, the new helper is refused. Bounded helper operations can only be stopped while the Command Code session is still running.

Click to focus

Click to focus is macOS only. With focusTerminalOnClick on (the default), clicking a notification's body brings forward the terminal or editor the Command Code session runs in. On Linux and Windows the setting has no effect; clicking a notification there does whatever the desktop does by default.

Helper Click detected by What is raised Status
alerter @CONTENTCLICKED on its output iTerm2: the session's own window/tab/split (AppleScript, ITERM_SESSION_ID); Terminal.app: the tab on the session's tty; other terminals: the application via open -b Implemented; application activation checked, exact window selection awaiting real-click verification
bundled terminal-notifier the helper itself (-activate) the application Works
osascript fallback — — Not supported: clicking opens Script Editor (macOS behavior)

The terminal is identified from __CFBundleIdentifier (the app that launched the session), falling back to a recognized TERM_PROGRAM. Known limits:

  • With alerter, the click is reported back to the running session, so a click after the session has exited, or from Notification Center after the banner has closed, does nothing.
  • For terminals other than iTerm2 and Terminal.app, and with terminal-notifier, the whole application is activated, so macOS raises its most recently used window, which may not be the session's.
  • Selecting the exact iTerm2 or Terminal.app window uses AppleScript, so macOS may ask once whether to allow automating that terminal. If you decline, or the script fails or does not finish within 10 seconds, the application is activated instead.
  • In tmux attached from a different terminal, __CFBundleIdentifier can name the wrong application. Sessions over SSH with an unrecognized TERM_PROGRAM get no click action. suppressWhenTerminalFocused uses TERM_PROGRAM only.

Troubleshooting

  • Nothing appears: check enabled, the relevant event's enabled, quiet hours, and OS notification permissions/Focus. Continue a normal conversation with Command Code and watch for its failure notice. Silent OS suppression may produce no helper error.
  • Linux helper missing: install the libnotify package above and run from a terminal in your logged-in desktop session. A headless environment does not become a desktop merely by installing notify-send.
  • Windows silent delivery: check Windows notification settings and the helper's sender identity. Keep windowsAppId: null unless you know the configured identity is registered. Report the OS, Node architecture, Command Code version, and any failure notice; Windows desktop delivery is still awaiting beta verification.
  • Helper missing or cannot start: reinstall the mod through Command Code's package manager, check executable permissions/security software, and restart.
  • Helper marked unhealthy: correct the reported problem, then restart Command Code or use /notify backend auto. Later notifications skip failing helpers; already submitted notifications are not reposted automatically.
  • Invalid settings: repair the JSON file at the path in the notice. Rename it if you want to preserve it while allowing defaults to be recreated next session.
  • Question alerts missing after a host update: try questionFallback: "tool_queued" in the settings file. Generic question text is safest. Mods API changes may require a new mod release.
  • Need diagnostic detail: temporarily set debug: true, reproduce through normal conversation, and inspect notify-debug.log beside the settings file. Standard diagnostics omit notification bodies but may include local paths and identifiers. Review and redact logs before sharing them.

Uninstall

Close running Command Code sessions, then remove the same source and scope used at installation. For the global beta installation above:

macOS / Linux:

cmd mods remove -g command-notify@beta

Windows PowerShell:

cmdc mods remove -g command-notify@beta

For project installation, omit -g and run inside that project. If you installed an exact version, use that version instead of @beta. Restarting ensures the mod is no longer loaded. Removing a package does not dismiss every existing OS banner.

Settings and diagnostics are intentionally retained so a reinstall preserves preferences. To remove them too, delete only these files after closing sessions:

macOS / Linux:

rm -f "$HOME/.commandcode/notify.json" "$HOME/.commandcode/notify-debug.log" "$HOME/.commandcode/notify.json.lock"

Windows PowerShell:

Remove-Item -LiteralPath "$HOME\.commandcode\notify.json", "$HOME\.commandcode\notify-debug.log", "$HOME\.commandcode\notify.json.lock" -ErrorAction SilentlyContinue

Do not delete the whole .commandcode directory: it contains other Command Code settings. OS notification history is cleared separately in the notification center. Any custom Windows identity you registered manually must also be removed manually.

On Windows, the bundled SnoreToast 0.7.0 also creates artifacts outside .commandcode. With the default application identity, these include:

  • %APPDATA%\Microsoft\Windows\Start Menu\Programs\SnoreToast\0.7.0\SnoreToast.lnk.
  • HKCU\SOFTWARE\Classes\CLSID\{eb1fdd5b-8f70-4b5a-b230-998a2dc19303}\LocalServer32, which points to the bundled SnoreToast executable.
  • Extracted icon files under %TEMP%\snoretoast\0.7.0\.

Before removing the package, inspect the shortcut target and the registry entry's value and record whether they point into this mod's dependency installation. After closing sessions, remove only that shortcut and that CLSID registration if this installation created them and no other application uses them. Remove only the extracted files belonging to this helper version from the temporary directory; leave other versions alone. Do not remove shared SnoreToast registrations or shortcuts: other applications may depend on the same identity. If ownership is uncertain, leave the shared artifacts in place.

Privacy and license

The mod itself sends no network requests and needs no API keys. Notification text is handed to local OS helpers. Debug logging is opt-in; verbose logging can store conversation excerpts. Runtime settings and logs live outside this repository. SnoreToast also emits notification XML, including title and message text, to the Windows debug output channel (OutputDebugStringW). This native-helper output is independent of the mod's debug and debugVerbose settings and can be captured by debugging tools even when both settings are off.

MIT; see LICENSE. Third-party helpers and dependencies retain their own licenses, supplied with those packages. Publication steps are in RELEASING.md.

About

Desktop notifications for Command Code on macOS, Linux and Windows. Published as-is.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages