Mac · Command line

bluebellctl

bluebellctl is the lightweight command-line entry point bundled with bluebell Mac. Your tool’s completion callback invokes it to pass an event to the running Event Hub.

Installation

Copy the actual path from the app

bluebell does not install a global command or change PATH. On the Mac home screen, choose “Copy CLI path” under “Connect your terminal.” If the app is in Applications, a typical path is:

CLI path
/Applications/bluebellMac.app/Contents/Helpers/bluebellctl

Quote the full path in your hook configuration. Update it if you move or rename the app. If the app reports that bluebellctl is missing, the installation is incomplete.

Minimal command

Start with a local-only event

Terminal
'/Applications/bluebellMac.app/Contents/Helpers/bluebellctl' emit \
  --source 'My Agent' \
  --workspace-name 'Integration test' \
  --dedupe-key "bluebell-test:$(uuidgen)" \
  --local

After about 2 seconds, the event should appear under “Recent notifications” on the Mac home screen. --local never enters the cloud queue. Use it to check the command, socket, and Event Hub.

Once the local test succeeds, remove --local from your production hook. If remote delivery is turned off on Mac, multi-device events are treated as local-only when the Event Hub receives them. Turning delivery back on does not resend them.

Flags

Commands and arguments

Syntax
bluebellctl emit --source <name> --dedupe-key <stable-key> [options]
bluebellctl emit --stdin
bluebellctl --help
bluebellctl emit --help
Argument Required Description
--source Yes A user-defined source name, 1–64 characters. This is not an executable path.
--dedupe-key Yes A globally stable ID for one logical completion, up to 512 characters.
--event completed No Only completed is accepted; it is also the default.
--workspace-name No The project name shown on devices, up to 128 characters.
--summary No A short summary, up to 280 characters. Avoid including sensitive information.
--session-id / --turn-id No Local diagnostic fields, each up to 256 characters.
--workspace No The full path stays on your Mac and is not uploaded to CloudKit.
--occurred-at No An ISO-8601 timestamp, no more than 5 minutes in the future.
--local No Explicitly local-only; never enters CloudKit.

Machine input

Send JSON through stdin

JSON
{
  "source": "My Agent",
  "workspaceName": "bluebell",
  "summary": "Implementation complete",
  "dedupeKey": "my-agent:session-42:turn-7",
  "sessionID": "session-42",
  "turnID": "turn-7",
  "deliveryScope": "localOnly"
}

Only source and dedupeKey are required. Input is limited to 64 KiB; close stdin when finished. --stdin cannot be combined with other event flags. Omitting deliveryScope defaults to allDevices.

The key reliability rule

Reuse the same dedupeKey when retrying

Retries for the same logical completion must reuse one key; different completions must have different keys. Keys are global within the app and are not automatically separated by source. A useful format is source:session:turn .

If your tool has no turn ID, your adapter must persist an ID for the current turn. Do not use the session ID alone or generate a new timestamp or UUID on every retry. The Event Hub’s 2-second settlement window merges duplicate candidates; it cannot tell whether you selected the right lifecycle event.

Script handling

stdout and exit codes

stdout
{"accepted":true,"duplicate":false,"eventID":"…","message":"…"}
Exit code Meaning
0 The app accepted the event, including duplicates. This does not confirm a CloudKit write or delivery to a device.
2 An argument, JSON, or IPC transport error.
4 The app rejected the event.