Skip to content

feat: cross-platform update notifications for OpenCode#53

Merged
1broseidon merged 4 commits into
1broseidon:mainfrom
Phototonic:feat/cross-platform-notifications
May 7, 2026
Merged

feat: cross-platform update notifications for OpenCode#53
1broseidon merged 4 commits into
1broseidon:mainfrom
Phototonic:feat/cross-platform-notifications

Conversation

@Phototonic
Copy link
Copy Markdown
Contributor

@Phototonic Phototonic commented May 7, 2026

Summary

This PR adds cross-platform update notifications for the OpenCode plugin, ensuring users actually see when a new cymbal version is available regardless of whether they are using TUI or Desktop mode.

Problem

Currently, cymbal update notices are injected into the OpenCode system prompt via output.system.push(text). This means:

  • The update notice is hidden background context for the AI agent
  • Users in Desktop mode never see it because there is no TUI toast API
  • Users in TUI mode rarely see it unless the agent chooses to mention it
  • The update check works correctly, but the delivery mechanism is invisible

This was reported in #23 where agents ignore the "use cymbal first" prompt as context grows, but the same invisible-delivery problem applies to update notices.

Solution

Phase 1: Enhanced OpenCode Plugin

The plugin (cmd/hook_assets/opencode/cymbal-opencode.js) now parses the reminder text for the "cymbal update:" block and spawns a native OS notification when an update is available:

  • macOS: osascript displaying a Notification Center notification
  • Linux: notify-send (only when DISPLAY or WAYLAND_DISPLAY is present)
  • Windows: PowerShell with System.Windows.Forms.NotifyIcon balloon tip

Key features:

  • Respects CYMBAL_NO_UPDATE_NOTIFIER environment variable
  • Tracks notified versions per session to prevent spam
  • All notification failures are swallowed so OpenCode never breaks
  • Uses detached spawn with stdio: "ignore" for fire-and-forget delivery

Phase 2: New cymbal hook notify Command

A new Go command provides structured update notification payloads for agent plugins:

cymbal hook notify --format=json --update=if-stale

Returns:

{
  "notify": true,
  "latestVersion": "v0.14.0",
  "title": "cymbal v0.14.0 is available",
  "body": "Update: brew upgrade 1broseidon/tap/cymbal",
  "command": "brew upgrade 1broseidon/tap/cymbal",
  "releaseURL": "https://github.com/1broseidon/cymbal/releases/latest"
}

Or {"notify": false} when no update is available or the user was already notified within the 24h throttle window.

This gives plugins a structured alternative to parsing human-readable reminder text.

Files Changed

File Change
cmd/hook_assets/opencode/cymbal-opencode.js Added notification helpers and parsing logic
cmd/hook_assets/opencode/cymbal-opencode.test.mjs New test suite with 14 tests
cmd/hook.go Added hookNotifyCmd and emitHookNotify()
cmd/hook_test.go Added tests for notify command
docs/AGENT_HOOKS.md Documented native OS notifications
docs/reference/commands.md Added hook notify command reference
README.md Mentioned OS notifications in OpenCode section
CHANGELOG.md Added unreleased entry

Testing

  • go test ./... passes (all packages)
  • node --test cmd/hook_assets/opencode/cymbal-opencode.test.mjs passes (14/14)
  • go build . succeeds
  • Manual QA: notification command generation verified on Windows
  • Manual QA: cymbal hook notify --help shows correct usage
  • Manual QA: cymbal hook notify --format=json returns correct payload
  • Manual QA: CYMBAL_NO_UPDATE_NOTIFIER=1 suppresses notifications

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Documentation update

Pre-flight Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Phototonic added 3 commits May 7, 2026 13:49
Add cross-platform notification support to the OpenCode plugin:

- Parse reminder text for update availability

- Show native OS notifications via osascript (macOS), notify-send (Linux),

  or PowerShell (Windows) when updates are available

- Respect CYMBAL_NO_UPDATE_NOTIFIER environment variable

- Track notified versions per session to prevent spam

- Add comprehensive test suite with 14 tests
Add structured update notification payload command for agent plugins:

- New 'cymbal hook notify' with --format=json|text and --update=cache|if-stale

- Returns structured payload when update available and throttle allows

- Calls updatecheck.MarkNotified after emitting payload

- Add test seams for status, shouldNotify, and markNotified

- Include comprehensive tests for JSON output, throttling, and opt-out
Update documentation for the new notification features:

- AGENT_HOOKS.md: Document native OS notifications in OpenCode section

- commands.md: Add cymbal hook notify command reference

- README.md: Mention OS notifications in OpenCode install section

- CHANGELOG.md: Add unreleased entry for notifications and hook notify
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 352354e645

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cmd/hook_assets/opencode/cymbal-opencode.js
Comment thread cmd/hook.go Outdated
Two fixes from automated code review:

1. Use structured cymbal hook notify command instead of parsing

   reminder text, so OpenCode plugin respects the persistent 24h

   per-version throttle via updatecheck.ShouldNotify/MarkNotified.

2. Capture fmt.Fprintln errors in text mode before calling

   MarkNotified, preventing false 'already notified' state when

   stdout is closed or piped to a failing consumer.

All tests pass. No breaking changes.
Copy link
Copy Markdown
Contributor Author

@Phototonic Phototonic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed both Codex review comments in commit ecd5ddc:

  1. Throttled notifications: The OpenCode plugin now uses cymbal hook notify --format=json --update=cache instead of parsing reminder text. This consults updatecheck.ShouldNotify and calls MarkNotified, honoring the persistent 24h per-version throttle across sessions.

  2. Text output errors: fmt.Fprintln errors in text mode are now captured in writeErr before MarkNotified is called. If stdout is closed or piped to a failing consumer, the error is returned early and the version is not marked as notified.

All tests pass.

@1broseidon 1broseidon merged commit c632072 into 1broseidon:main May 7, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants