Create Custom Alert Rules From the Command Line

SecureNow 8.1 adds `securenow alerts rules create` — define your own detection rules from SQL, scope them to your apps, and ship them without leaving the terminal. Here's how, with a real magic-link brute-force example.

Jun 11, 2026·7 min read

Create Custom Alert Rules From the Command Line

SecureNow ships with a large library of built-in detection rules — brute force, credential stuffing, scanner fingerprints, injection signatures. But every app has a threat model the defaults don't quite cover: a login flow with its own quirks, a checkout endpoint worth watching, an internal API that should never see traffic from outside one ASN.

Until now, turning that knowledge into a detection rule meant opening the dashboard. As of SecureNow 8.1, you can do it from the terminal:

npm install -g securenow@latest

securenow alerts rules create \
  --name "Auth: magic-link brute force" \
  --sql @rule.sql \
  --apps <app-key> \
  --severity high \
  --nlp "single IP flooding /api/auth/signin or /api/auth/callback"

Detection-as-code, versioned in your repo, shippable from CI. No clicking.

Why this matters

Detection rules are configuration, and configuration belongs in version control. When a rule lives only in a dashboard, you lose the things you take for granted everywhere else in your stack: code review on the query, a diff when someone changes a threshold, the ability to recreate your whole security posture in a fresh environment with one script.

securenow alerts rules create closes that gap. The rule's SQL is a file in your repo. Creating the rule is a command in your deploy pipeline. Tuning it later is a reviewed change.

How it works

A SecureNow detection rule is just a SQL query that runs on a schedule against your trace telemetry in ClickHouse. The query returns the offending IPs; SecureNow aggregates them, raises a notification, and — if you have automation or rate-limit rules wired up — remediates.

Two conventions make the SQL portable:

  • __USER_APP_KEYS__ — a placeholder SecureNow replaces with the rule's scoped application keys at runtime. Always filter on it so the rule only ever sees your own traffic.
  • an ip column — select the client IP so SecureNow can group matches per IP and hand them to remediation.

That's the whole contract. Everything else is ordinary SQL.

A real example: magic-link login abuse

Passwordless (magic-link) login has a specific abuse surface: a single IP hammering the request endpoint to flood a victim's inbox, or hammering the callback endpoint to brute-force verification tokens. Here's a rule that flags any IP making 20+ requests to the auth endpoints in 15 minutes.

Save the query as rule.sql:

SELECT
  coalesce(
    nullIf(attributes_string['http.client_ip'], ''),
    nullIf(attributes_string['net.peer.ip'], ''),
    nullIf(attributes_string['network.peer.address'], ''),
    nullIf(attributes_string['client.address'], '')
  ) AS ip,
  count() AS request_count,
  countDistinct(attributes_string['http.target']) AS distinct_targets
FROM signoz_traces.distributed_signoz_index_v3
WHERE resource_string_service$$name IN (__USER_APP_KEYS__)
  AND timestamp >= now() - INTERVAL 15 MINUTE
  AND (
    attributes_string['http.target'] LIKE '/api/auth/signin%'
    OR attributes_string['http.target'] LIKE '/api/auth/callback%'
  )
GROUP BY ip
HAVING ip != '' AND request_count >= 20
ORDER BY request_count DESC
LIMIT 100

Then create the rule:

securenow alerts rules create \
  --name "Email login abuse - magic-link flood & token brute-force (single IP)" \
  --description "Single IP making excessive magic-link signin or token-callback requests" \
  --nlp "Detect a single IP sending too many /api/auth/signin or /api/auth/callback requests in 15 minutes" \
  --category auth \
  --severity high \
  --apps <your-app-key> \
  --sql @rule.sql

SecureNow validates the SQL, stores the query, creates the rule on a 15-minute schedule, and routes matches to your in-app channel. Confirm it runs cleanly before trusting it:

securenow alerts rules test <rule-id> --app <your-app-key> --mode dry_run --wait

A complete status with no error means the query is valid against your live data — even if it returns zero rows today, which is exactly what you want from a preventive rule.

The flags

FlagPurpose
--nameRule name (required)
--sql <sql|@file|->Detection SQL — inline, from a file with @, or - for stdin
--apps k1,k2 / --applications-allScope to specific apps, or all current & future apps
--severitycritical, high, medium, or low
--scheduleCron expression (default */15 * * * *)
--nlpPlain-English intent stored with the query
--throttle-minutes N / --no-throttleNotification throttle window
--execution-modescheduled, instant, or hybrid
--channel id1,id2Override the alert channel (defaults to your in-app SecureNow channel)
--query-mapping-idReuse a saved query instead of --sql

Reusing an existing saved query? Pass --query-mapping-id instead of --sql. Want to keep the rule and its query side by side with the rest of your infrastructure? Commit rule.sql and the create command into your deploy scripts.

From detection to response

A detection rule is one half of the loop. Pair it with SecureNow's remediation primitives, all of which are also scriptable from the CLI:

# Soft: rate-limit the abused route inline at the firewall
securenow ratelimit add --app <key> --route /api/auth/signin \
  --mode prefix --method POST --limit 10 --window 15m

# Hard: auto-block IPs your detection flags as high risk
securenow automation create --name "Block high-risk auth abusers" \
  --conditions '[{"field":"riskScore","operator":"gte","value":90}]' \
  --actions '[{"type":"addToBlocklist","config":{"ttlHours":72,"method":"ALL"}}]'

Detection in SQL, response in policy, both in version control. That's the workflow securenow alerts rules create was built for.

Get it

npm install -g securenow@latest    # 8.1.0 or newer
securenow login                    # authenticate the CLI
securenow alerts rules create --help

Full reference lives in the bundled CLI skill (securenow help alerts rules) and the SecureNow docs. If you describe your threat model in --nlp and keep the SQL in your repo, your detection logic stays as reviewable as the rest of your code.

Frequently Asked Questions

Do I still need the dashboard to create detection rules?

No. As of SecureNow 8.1 you can create a full custom detection rule with `securenow alerts rules create` straight from the terminal or CI. The dashboard remains available for browsing, tuning, and reviewing — but rule creation is now scriptable.

What does the detection SQL run against?

Your trace telemetry in ClickHouse. Scope the query to your apps with the `__USER_APP_KEYS__` placeholder and select an `ip` column so SecureNow can aggregate matches per IP and hand them to remediation (block, rate-limit, or notify).

What permissions does it need?

An API key with the `alerts:write` scope, or an authenticated admin CLI session via `securenow login`.

Recommended reading

Secure a Next.js App with SecureNow Using This AI Onboarding Prompt

A copy-paste prompt that lets an AI coding agent install SecureNow, wire Next.js instrumentation, verify traces and logs, deploy to AWS, simulate attacks, and prove firewall blocking with human approval gates.

May 18
nextjs securenow ai onboarding prompt
Adding Backend Tracing to a Sentry Stack with OpenTelemetry

If your team uses Sentry for frontend errors and needs backend distributed tracing without doubling the Sentry bill, here's the OpenTelemetry path that doesn't make you choose.

May 9
How to Block Bot Traffic in Express With No Extra Infra

Five approaches to bot blocking in Express, ranked by effort vs. effectiveness. From a 5-line allowlist to a full IP-reputation firewall — all without Cloudflare, AWS WAF, or any new infrastructure.

May 9