toast

package module
v0.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2026 License: MIT Imports: 8 Imported by: 0

README

Toast

English | 简体中文

Toast is a small Go library for sending desktop notifications from native applications and lightweight tools. It supports macOS, Windows, and JavaScript WASM, with helper utilities for Windows toast click-to-focus workflows.

Features

  • Simple toast.Push API with functional options
  • macOS notifications through osascript or Objective-C
  • Windows toast notifications through Windows Runtime APIs
  • Windows protocol activation for clickable toast actions
  • Optional Windows focus helper for bringing the originating terminal or app to front
  • JavaScript/WASM notification support for browser environments

Install

go get github.com/hellolib/toast

Quick Start

package main

import "github.com/hellolib/toast"

func main() {
    _ = toast.Push("Build finished", toast.WithTitle("Agent Notify"))
}

Platform Examples

macOS
package main

import "github.com/hellolib/toast"

func main() {
    _ = toast.Push("Permission required",
        toast.WithTitle("Agent Notify"),
        toast.WithSubtitle("15:04:05"),
        toast.WithAudio(toast.Submarine),
    )
}

For Objective-C delivery:

_ = toast.Push("Task completed",
    toast.WithTitle("Agent Notify"),
    toast.WithObjectiveC(),
)
Windows
package main

import "github.com/hellolib/toast"

func main() {
    _ = toast.Push("Task completed",
        toast.WithAppID("agent-notify"),
        toast.WithTitle("Agent Notify"),
        toast.WithAudio(toast.Default),
        toast.WithLongDuration(),
    )
}

To add an image:

_ = toast.Push("Task completed",
    toast.WithTitle("Agent Notify"),
    toast.WithIcon(`C:\path\to\icon.png`),
)
JavaScript / WASM
package main

import (
    "fmt"

    "github.com/hellolib/toast"
)

func main() {
    _ = toast.Push("Saved",
        toast.WithTitle("WASM App"),
        toast.WithOnClick(func(event interface{}) {
            fmt.Println("clicked")
        }),
        toast.WithOnClose(func() {
            fmt.Println("closed")
        }),
    )
}

Windows Click-To-Focus

Windows toast clicks are delivered through activation. For ordinary Go command line tools, the practical approach is:

  1. Ship a small GUI-subsystem helper executable.
  2. Register a custom URL protocol that launches the helper.
  3. Send the toast with WithActivationType("protocol").
  4. Pass the protocol URI through WithActivationArguments.

This repository provides both the library API and a helper command for that flow. The helper is a separate executable so toast clicks do not flash a console window.

Target Selection

PrepareFocusActivation resolves the target window before the toast is sent. It walks up from the supplied PID, finds a visible top-level window, and embeds that window handle in the activation URI. When the toast is clicked, the helper first focuses that exact window handle. If the handle is no longer valid, it falls back to the PID-based process-tree lookup.

This avoids focusing the wrong window in shells launched from apps with multiple top-level windows, such as VS Code, Windows Terminal, or other Electron-based hosts.

Library Usage
package main

import (
    "fmt"
    "os"

    "github.com/hellolib/toast"
)

func main() {
    focus, err := toast.PrepareFocusActivation(
        os.Getppid(),
        `C:\path\to\toast-focus-helper.exe`,
    )
    if err != nil {
        panic(err)
    }

    _ = toast.Push("Click to focus the current terminal",
        toast.WithAppID("agent-notify"),
        toast.WithTitle("Agent Notify"),
        toast.WithMessage(fmt.Sprintf("helper: %s\nhwnd: 0x%x", focus.Helper, focus.Window)),
        toast.WithActivationType("protocol"),
        toast.WithActivationArguments(focus.Arguments),
    )
}

PrepareFocusActivation checks explicit helper candidates first. If none are provided or found, it looks next to the current executable for conventional names:

  • toast-focus-helper.exe
  • toast-focus-helper-arm64.exe
  • <app>-focus-helper.exe
  • <app>-helper.exe
Demo Commands

cmd/toast-focus is a runnable demo that sends a clickable toast. It expects the helper binary to be in the same directory.

make build

Artifacts are written to dist/:

  • toast-focus.exe
  • toast-focus-helper.exe
  • toast-focus-arm64.exe
  • toast-focus-helper-arm64.exe

For applications that only need the helper binaries:

make build-helpers

Make Targets

make test                 # Run Go tests
make build                # Build all Windows demo/helper binaries
make build-helpers        # Build only Windows focus helpers
make build-windows-amd64  # Build Windows amd64 demo/helper
make build-windows-arm64  # Build Windows arm64 demo/helper
make clean                # Remove dist/

API Overview

Common options:

  • toast.Push(message, opts...)
  • toast.WithTitle(title)
  • toast.WithMessage(message)
  • toast.WithAudio(audio)

macOS options:

  • toast.WithSubtitle(subtitle)
  • toast.WithObjectiveC()

Windows options:

  • toast.WithAppID(appID)
  • toast.WithIcon(path)
  • toast.WithIconRaw(bytes)
  • toast.WithActivationType(kind)
  • toast.WithActivationArguments(uri)
  • toast.WithProtocolAction(label, uri)
  • toast.WithLongDuration()
  • toast.WithShortDuration()

Windows focus helpers:

  • toast.FindFocusHelper(candidates...)
  • toast.RegisterFocusProtocol(helperPath, protocol...)
  • toast.PrepareFocusActivation(pid, helperCandidates...)
  • toast.FocusActivationForWindow(pid, hwnd, logPath, helperCandidates...)
  • toast.FocusActivationArguments(pid, protocol...)

FocusActivation.Window is the resolved Windows HWND used for precise click-to-focus. It may be zero when no suitable window is found before sending the toast.

JavaScript/WASM options:

  • toast.WithIcon(url)
  • toast.WithImage(url)
  • toast.WithRequireInteraction(true)
  • toast.WithOnClick(fn)
  • toast.WithOnShow(fn)
  • toast.WithOnClose(fn)
  • toast.WithOnError(fn)

License

MIT

Documentation

Index

Constants

View Source
const (
	// DefaultFocusProtocol is the protocol used by the bundled focus helper.
	DefaultFocusProtocol = "anfocus"
)

Variables

This section is empty.

Functions

func FindFocusHelper

func FindFocusHelper(_ ...string) (string, error)

FindFocusHelper is only supported on Windows.

func FocusActivationArguments

func FocusActivationArguments(pid int, protocols ...string) string

FocusActivationArguments formats the URI passed to WithActivationArguments.

func ParseFocusActivation added in v0.4.0

func ParseFocusActivation(uri string) (pid int, hwnd uintptr, logPath string, err error)

ParseFocusActivation 解析 helper 收到的激活 URI。 未识别的 hwnd/base64 一律降级为零值/空串,绝不报错阻断聚焦。

func PrepareFocusActivationVerbose added in v0.4.0

func PrepareFocusActivationVerbose(pid int, _ string, _ ...string) (FocusActivation, FocusDiag, error)

PrepareFocusActivationVerbose is only supported on Windows.

func Push

func Push(message string, opts ...NotificationOption) error

func RegisterFocusProtocol

func RegisterFocusProtocol(_ string, _ ...string) error

RegisterFocusProtocol is only supported on Windows.

func SelectHostWindow added in v0.4.0

func SelectHostWindow(chain []AncestorWindows) (hwnd uintptr, pid uint32, reason string)

SelectHostWindow 从祖先链中挑选宿主终端窗口。 P0 语义(行为保持):按 chain 顺序取第一个"可见 + 无 owner + 有标题"的窗口。 返回选中的 HWND(无则 0)、其所属 PID、以及人类可读的原因。

Types

type Action added in v0.4.0

type Action struct {
	Type      string
	Label     string
	Arguments string
}

Action defines an actionable button on a notification.

Only protocol-type action buttons are useful, as there's no way to receive feedback from the user's choice. Example:

Action{"protocol", "Open Maps", "bingmaps:?q=sushi"}

type AncestorWindows added in v0.4.0

type AncestorWindows struct {
	PID     uint32
	PPID    uint32
	Exe     string
	Windows []WindowInfo
}

AncestorWindows 归组一个祖先进程及其拥有的顶层窗口。

type Audio

type Audio string

type FocusActivation

type FocusActivation struct {
	Protocol  string
	Helper    string
	Arguments string
	Window    uintptr
}

FocusActivation describes the protocol activation data used to focus the source window when a Windows toast is clicked.

func FocusActivationForWindow added in v0.5.0

func FocusActivationForWindow(_ int, _ uintptr, _ string, _ ...string) (FocusActivation, error)

FocusActivationForWindow is only supported on Windows.

func PrepareFocusActivation

func PrepareFocusActivation(_ int, _ ...string) (FocusActivation, error)

PrepareFocusActivation is only supported on Windows.

type FocusDiag added in v0.4.0

type FocusDiag struct {
	StartPID     uint32
	Chain        []AncestorWindows
	SelectedHWND uintptr
	SelectedPID  uint32
	Reason       string
}

FocusDiag 记录一次 send(或 click 重走)的完整解析,用于可观测。

func (FocusDiag) String added in v0.4.0

func (d FocusDiag) String() string

type NotificationOption

type NotificationOption func(*notification)

func WithAudio

func WithAudio(audio Audio) NotificationOption

WithAudio

The audio to play when displaying the notification

func WithMessage

func WithMessage(msg string) NotificationOption

WithMessage

The single/multi line message to display for the notification.

func WithTitle

func WithTitle(title string) NotificationOption

WithTitle

The main title/heading for the notification.

type WindowInfo added in v0.4.0

type WindowInfo struct {
	HWND       uintptr
	OwnerPID   uint32
	Class      string
	Title      string
	Visible    bool
	HasOwner   bool
	Minimized  bool
	ExStyle    uint32
	X, Y, W, H int32
}

WindowInfo 是一个顶层窗口的朴素快照(除数值 HWND 外不含任何 Win32 句柄)。 中立类型,供 send 侧、helper、探针共用与单测。

Directories

Path Synopsis
assets
_generate command
Command generate renders the default "terminal" logo used as the Windows toast appLogoOverride image when a caller does not supply WithIcon.
Command generate renders the default "terminal" logo used as the Windows toast appLogoOverride image when a caller does not supply WithIcon.
cmd
toast-focus command
toast-focus sends a Windows toast notification whose click action focuses the terminal window that launched this process.
toast-focus sends a Windows toast notification whose click action focuses the terminal window that launched this process.
toast-focus-helper command
toast-focus-helper is launched by the anfocus: protocol.
toast-focus-helper is launched by the anfocus: protocol.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL