# Triggering notifications from scripts

Your shell commands and scripts can send notifications to Solo directly from terminal output using supported [OSC sequences](../terminal/osc-kitty-protocol.md) and [bell events](./bell-sounds.md). This is useful for getting alerted when long-running tasks finish.

## Supported notification sequences

### OSC 9 (iTerm2-compatible)

```bash
echo -ne "\033]9;Build finished\007"
```

This sends a message-only terminal notification. The format is `ESC ] 9 ; <message> BEL`, where `BEL` is `\007` or `\a`.

### OSC 777 (libnotify-compatible)

```bash
echo -ne "\033]777;notify;Build;Compilation complete\007"
```

The format is `ESC ] 777 ; notify ; <title> ; <body> BEL`. This lets you provide both a title and a body.

### OSC 99 (Kitty-compatible)

Solo supports one-shot OSC 99 payloads and multipart payloads identified by `i=<id>`. Use `p=title` for a title payload or `p=body` for a body payload. Payloads can be plain text or base64 when `e=1`. For multipart payloads, reuse the same ID on every chunk: `d=0` marks a non-final chunk, `d=1` completes the assembly, and omitting `d` also treats the chunk as complete.

Periodic cleanup retains at most 50 pending multipart IDs and may discard the oldest excess assemblies. An incomplete assembly older than 60 seconds is pruned when periodic cleanup next runs.

For a simple one-shot body notification:

```bash
echo -ne "\033]99;p=body;Build finished\007"
```

For OSC 9, the message must contain at least one alphabetic character. For OSC 777 and OSC 99, at least one title or body field must contain an alphabetic character. Empty, whitespace-only, numeric-only, and other content with no alphabetic characters is ignored.

The content after the OSC selector is limited to 8 KiB (8,192 bytes) for OSC 9, OSC 777, and OSC 99. An oversized sequence is ignored. If an identified OSC 99 chunk exceeds the limit, Solo also abandons that pending multipart assembly.

### Terminal bell

```bash
echo -ne "\a"
# or
printf '\a'
```

A bare bell character triggers the terminal-notification path without any custom message text.

## Practical examples

### Notify on build completion

```bash
npm run build && echo -ne "\033]9;Build succeeded\007" || echo -ne "\033]9;Build failed!\007"
```

### Notify with title and body

```bash
echo -ne "\033]777;notify;Tests;All 152 tests passed\007"
```

### Notify from a Makefile

```makefile
test:
	pytest
	@printf '\033]9;Tests done\007'
```

### Notify at the end of a long task

```bash
sleep 300 && echo -ne "\033]9;Task finished after 5 minutes\007"
```

## How Solo routes them

Solo decides what to show you based on where your attention is:

- If Solo isn't focused, it can send a [native desktop notification](./macos-permissions.md).
- If Solo is focused, it shows an [in-app toast](./in-app-toasts.md) unless you're already viewing that same process.
- If you're already viewing that same process, Solo suppresses the notification instead of alerting you redundantly.

For native notifications, system permission must be granted. See [notification troubleshooting](../troubleshooting/notifications.md).

Terminal notifications are delivered only when the effective notification level for the project and process is **All**. **Important** still allows crash and [auto-restart-exhausted alerts](./auto-restart-notifications.md), but it suppresses BEL and OSC terminal alerts.

## Notification content

For OSC 9, your message becomes the notification body and Solo supplies project or process context around it.

For OSC 777 and OSC 99, your script can provide an explicit title and body.

Additional detail can go directly in the body, but keep the complete OSC content at or below 8 KiB (8,192 bytes):

```bash
echo -ne "\033]9;[api] Server restarted\007"
```

## Testing

Test your notification sequence by running the command in a Solo terminal and checking whether the notification appears. If nothing happens, verify:

1. The escape sequence syntax is correct.
2. Notification permissions are granted.
3. The process and project notification levels resolve to **All**.
4. You're not already focused on that same process.
5. You haven't hit the terminal notification rate limit.

---

Are you a human? Read this doc on the web: https://soloterm.com/docs/notifications/triggering-from-scripts
