Skip to main content

Event system for AI CLI agents

Project description

trigr

AI CLI coding agents (Claude Code, Codex, Gemini CLI) are reactive — they only work when a human types a message. They have no native event system, no triggers, no way to react to external events autonomously.

trigr fixes that. It's a lightweight event system that delivers events into a running agent session. The agent calls trigr watch, goes to sleep, and wakes up when something happens.

Agent runs trigr watch (background task or blocking)
    → blocks until event
    → event arrives → prints JSON → exits
    → agent wakes up, processes event
    → agent runs trigr watch again
    → "asleep" until next event

One tool. One pattern. Works with any agent.

Install

uv tool install trigr

Quick Start

# Initialize trigr in your project
trigr init

# Terminal 1: watch for events (auto-starts server)
trigr watch

# Terminal 2: send an event
trigr emit hello --data '{"msg": "world"}'
# → Terminal 1 prints the event JSON and exits

Agent Integration

Claude Code

trigr watch runs as a background task — the agent can chat with the user while waiting for events. When an event arrives, the background task exits and the agent gets notified.

# In a Claude Code skill or agent instruction:
# "Run trigr watch as a background task. When it completes, process the event and restart."
trigr watch --timeout 3600

Codex CLI / Gemini CLI

trigr watch runs as a blocking call. The agent waits for the next event, processes it, and restarts the loop.

Agent How trigr watch runs Background chatting?
Claude Code Background task Yes
Codex CLI Blocking call No (not needed)
Gemini CLI Blocking call No

Event Sources

trigr supports three ways to produce events:

1. Manual / Programmatic

Anything can POST events — other terminals, scripts, webhooks, other agents:

trigr emit code_review --data '{"pr": 42, "repo": "myapp"}'

2. Pollers

Shell commands that run on an interval. If stdout is non-empty, it becomes an event:

[pollers.check-inbox]
interval = 60
command = "python check_mail.py"

3. Cron Jobs

Shell commands on a cron schedule:

[crons.daily-summary]
cron = "0 9 * * *"
command = "python daily_report.py"

Pollers and cron commands are language-agnostic. Write a script in any language that prints JSON to stdout. trigr runs it on schedule.

Delayed Events

The agent can schedule its own future events — perfect for follow-ups:

# "Follow up in 48 hours if no response"
trigr emit followup --data '{"candidate": "C-4821"}' --delay 48h

# Supported units: s (seconds), m (minutes), h (hours), d (days)

trigr.toml

Project-local configuration. Created by trigr init.

[server]
host = "127.0.0.1"
port = 9374

[pollers.check-inbox]
interval = 60
command = "python check_mail.py"

[crons.morning-sync]
cron = "0 9 * * *"
command = "echo '{\"type\": \"morning\"}'"

Add jobs from the CLI:

trigr add inbox-check --interval 60 --command "python check_mail.py"
trigr add daily-report --cron "0 9 * * *" --command "python report.py"

Commands

Command Description
trigr init Create trigr.toml in the current directory
trigr serve [-f] Start server (detached by default, -f foreground)
trigr watch [--timeout 300] Block until event, print JSON, exit
trigr emit <type> [--data '{}'] [--delay 10s] Push event to queue
trigr add <name> -c "cmd" (--interval N | --cron "...") Add poller/cron to config
trigr status Show server state

How It Works

trigr serve → FastAPI server + APScheduler
                ├── POST /emit    (push events to priority queue)
                ├── GET  /next    (long-poll, blocks until event ready)
                └── GET  /status  (queue depth, registered jobs)

Events sit in an in-memory priority queue sorted by delivery time. GET /next blocks until an event whose fire_at has passed, then returns it as JSON.

The server auto-starts when you run trigr watch or trigr emit. A .trigr.pid file lives next to trigr.toml, so multiple projects can run independent servers on different ports.

Poller Output Format

Poller commands should print JSON to stdout. If the JSON has a type field, it's used as the event type. Otherwise it defaults to poller.<name>.

# Poller script example
echo '{"type": "new_email", "data": {"from": "jane@example.com", "subject": "Re: Role"}}'

If stdout is empty, no event is created. This lets pollers silently skip cycles when nothing is new.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

trigr-1.0.1.tar.gz (28.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

trigr-1.0.1-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file trigr-1.0.1.tar.gz.

File metadata

  • Download URL: trigr-1.0.1.tar.gz
  • Upload date:
  • Size: 28.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for trigr-1.0.1.tar.gz
Algorithm Hash digest
SHA256 2a27c5ce0a518784295cac44c8b8b345bdb10cb147df3621d55b007a6efa83a4
MD5 359a1c11fb2b894d582dafd4d2447f45
BLAKE2b-256 fad0dd5a26c3df231a4e24d850d73c929531f64e01b6e8f9776b323407332af8

See more details on using hashes here.

File details

Details for the file trigr-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: trigr-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for trigr-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8d33fe1cdc774bb0248b2277d9379c632adb0bbcee7b16abae6148266b4e5610
MD5 0351bc115cffcf28abc553bb94cd29f4
BLAKE2b-256 60e501917ca24cd418dc0c9395ea18c99b3704f502db03a0c18e468333a90eeb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page