SOLWYN
Commands

alerts

Project history, activity across the account, pending deliveries, last firing, and the account spend alert.

An alert is an event that already fired — a budget rule, threshold, or the account spend alert crossed its condition, and Solwyn tried to deliver it. alerts list, show, and export read that history, each event carrying a delivery receipt per channel leg. Rules themselves are configured elsewhere: project rules under budget rule, and the single account-wide spend threshold under alerts account, documented on this page.

Project history accepts either credential. Anything account-scoped — --account history and every alerts account subcommand — requires a user login; a project key exits 3 before any request with jwt_required.

alerts activity and pending

Terminal
solwyn --json alerts activity --range 7d --event-type fired --all
solwyn alerts activity --cursor CURSOR
solwyn --json alerts pending --all --fail-if-open

Both require JWT at any account role and no selected project. activity reads all projects plus account scope, unlike alerts list --account, which reads account-scope history only. It accepts --range 7d|30d|90d (default 30d), --event-type fired|snoozed|unsnoozed|paused|resumed, --cursor, and --all; it does not accept paired custom-window flags.

pending lists operationally open pending/retrying deliveries, regardless of normal event retention, with per-channel attempts and next_attempt_at. It accepts --cursor, --all, and --fail-if-open; it has no range filter. Default listing exits 0. With --fail-if-open, data prints first, then nonempty listed open deliveries produce open_alert_deliveries and exit 1. Use --all for a complete health check.

Both use 25-event cursor pages. Outputs are solwyn.alerts.activity.v1 and solwyn.alerts.pending.v1; exits are 0 success, 1 API/invalid response (also open-delivery gate), 2 usage, 3 auth. CLI all-page aggregation fails without partial success stdout if a later page fails. MCP list_alert_activity and list_open_alert_deliveries retain bounded pagination and first unread cursors on errors.

Choosing a window

list, show, and export share one set of window flags. All validation happens locally, before a credential is resolved or a request is sent; a bad value exits 2 with invalid_alert_query.

OptionTypeDefaultPurpose
--accountbooleanfalseRead account-scope history instead of the project's. Requires JWT.
--range7d | 30d | 90d30dLook-back window.
--from, --toISO 8601, timezone-awarenoneAn explicit window. Both must be supplied together, and --to must be later than --from. Replaces --range.
--rule-typestringnoneFilter by rule type, for example scoped_budget or budget_threshold. Not on export.
--scopestringnoneFilter by the rule's scope in metadata, for example tag. Not on export.

Retention is tier-bound. When the API narrows the window you asked for, the CLI says so on stderr — Retention clamped window: … (requested …) — and the JSON window object reports both the requested and effective bounds with retention_clamped: true.

alerts list

Terminal
solwyn --project <project_id> alerts list [window flags] [--failed-only] [--cursor <c>] [--all]
OptionTypeDefaultPurpose
--failed-onlybooleanfalseKeep only events whose delivery rollup is partial or failed. Applied locally after fetching.
--cursorstringnoneStart from a page cursor printed by a previous run.
--allbooleanfalseWalk every page. The API returns at most 25 events per page.
Contract
Authany; --account requires JWT
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.alerts.v1
Terminal
$ solwyn --project proj_0123456789abcdef01234567 alerts list --range 7d
id         emitted at                 rule type      event      delivery
evt_9c1e   2026-09-01T00:00:00+00:00  scoped_budget  triggered  partial

The delivery column is the worst leg across every channel the event was routed to: pending, retrying, processed, delivered, partial, or failed. Without --all, one page is fetched; when more remain, the table view prints the next cursor to stderr so you can continue with --cursor.

The JSON payload carries every leg:

{
  "schema": "solwyn.alerts.v1",
  "events": [
    {
      "id": "evt_9c1e",
      "project_id": "proj_0123456789abcdef01234567",
      "scope": "project",
      "rule_key": "rule-one",
      "emitted_at": "2026-09-01T00:00:00Z",
      "event_type": "triggered",
      "rule_type": "scoped_budget",
      "value_at_event": 12.5,
      "threshold_at_event": 10.0,
      "period_key": null,
      "metadata_json": {"scope": "tag"},
      "delivery": {
        "status": "partial",
        "attempt_count": 3,
        "legs": [
          {"leg_key": "slack:one", "channel_type": "slack", "channel_name": "Operations",
           "status": "failed", "attempt_count": 3, "delivered_at": null, "error": "Channel unavailable"}
        ]
      }
    }
  ],
  "next_cursor": null,
  "window": {"requested_from": "…", "requested_to": "…", "effective_from": "…", "effective_to": "…", "retention_clamped": false}
}

Pretty-printed and abridged here; the CLI emits one line. value_at_event and threshold_at_event are the quantity the rule measured and the limit it crossed — dollars for a budget rule, never content.

alerts show

Find one event by id within the window and list its delivery legs.

Terminal
solwyn --project <project_id> alerts show <event_id> [window flags]
Contract
Authany; --account requires JWT
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found in window
JSON schemasolwyn.alerts.v1
Terminal
$ solwyn --project proj_0123456789abcdef01234567 alerts show evt_9c1e
channel  name        status  attempts  delivered at  error
slack    Operations  failed  3         —             Channel unavailable

The table has one row per leg, not per event, and a summary line — Event evt_9c1e; delivery: partial. — goes to stderr. The CLI walks list pages inside the window and matches the id locally, so an event outside the window exits 5 with the hint to widen --range or check --account. The JSON payload is the single event object.

alerts export

Stream history as CSV or newline-delimited JSON to stdout. Production and above.

Terminal
solwyn --project <project_id> alerts export [--format csv|json] [--account] [--range …] [--from … --to …]
OptionTypeDefaultPurpose
--formatcsv | jsoncsvjson is NDJSON, one event per line. Anything else is a usage error.
Contract
Authany; --account requires JWT
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemastream (CSV or NDJSON), not an envelope
Terminal
$ solwyn --project proj_0123456789abcdef01234567 alerts export --range 90d > alerts.csv
Alert exports exclude delivery receipts.

The stream is copied byte-for-byte to stdout — redirect it to a file. Window headers the API returns (X-Solwyn-Effective-From, X-Solwyn-Retention-Clamped, X-Solwyn-Truncated, and their siblings) are echoed on stderr. --rule-type and --scope do not apply to export.

alerts account

The account spend alert is one account-wide dollar threshold, at most one per account, that fires an alert when the account's combined spend crosses it. It is a notification, not a cap: it never blocks a call. Production and above; set, delete, snooze, and unsnooze require the account owner, while show and preview are open to any member.

Contract
AuthJWT; owner for mutations
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.alerts.account.v1
SubcommandPurpose
alerts account showShow the configured alert. Exits 5 when none is configured.
alerts account set --spend <usd> [--channel <id>]... [--enabled|--disabled]Create or update it. --spend must be a positive amount. Repeating --channel replaces the channel list; omitting it preserves the existing one.
alerts account deleteDelete it. Succeeds when already absent. No confirmation prompt.
alerts account snooze --until <when>Silence it until an absolute timezone-aware timestamp, or a relative +30m, +2h, +7d.
alerts account unsnoozeClear the snooze.
alerts account preview [--channel <id>]...Dry-run the routing for a channel list without saving anything.
Terminal
$ solwyn alerts account set --spend 500 --channel ch_one
field                value
account_id           acct_one
spend_threshold_usd  500.0
enabled              True
channel_ids          ["ch_one"]
snoozed_until        —
routing              {"will_send": true, "email": "ops@example.com", "channels": [{"id": "ch_one", "name": "Ops"}], "source": "override", "muted": null}
created_at           2026-09-01T00:00:00Z
updated_at           2026-09-01T00:00:00Z

The routing object answers "will this actually reach anyone?": will_send, the resolved email, the resolved channels, where the routing came from (override, project_default, or account_default), and — when it would be silenced — muted.reason of severity_floor, event_filter, or email_off. preview returns that object alone, which makes it the first thing to run when an alert never arrived. An unknown channel id in set exits 2 and names the offending ids.

A naive timestamp in --until is a usage error; +2h-style durations are always safe.

Last fired on account alerts

Terminal
solwyn --json alerts account show --with-last-fired

JWT reads can opt into --with-last-fired. The read-only latest-events POST returns the last firing and latest lifecycle event, merging current-account-ID and legacy account-spend history by timestamp and event ID. Core's default 30-day window and plan retention apply; null means no matching retained history. Without the flag, no extra request is made. MCP get_account_alert(with_last_fired=true) exposes the same read in both profiles; project rules support the same option.

On this page