Guide

Detect Calendar Conflicts from the CLI

Spot double-booked meetings and overlapping events from the terminal. AI conflict detection and jq scripts catch calendar conflicts before they derail your day.

Written by Prem Keshari Senior SRE

VerifiedCLI 3.1.16 · Google Calendar · last tested June 9, 2026

According to Atlassian’s workplace productivity research, the average knowledge worker loses 31 hours per month to unproductive meetings — and double-bookings are among the most disruptive contributors. You show up to one meeting, miss another, and spend 20 minutes apologizing to both sides. The problem compounds on distributed teams where time zone math disguises a 10 AM slot in London as a 6 AM slot that is also blocked by an early standup in New York.

Two commands surface calendar conflicts from your terminal without opening a browser. The built-in AI detector catches hard conflicts, back-to-back gaps, and travel-time risks in one scan. The jq approach gives you a scriptable overlap checker you can schedule as a daily health check.

How does the built-in conflict detector work?

The nylas calendar ai conflicts command scans your connected calendar and classifies every conflict into one of three severity levels. Hard conflicts are simultaneous events — two meetings that overlap by any amount of time. Soft conflicts are back-to-back blocks with less than 15 minutes between them, which leaves no time for notes or a bio break. Travel-time risks flag consecutive events in different physical locations. The default look-ahead window is 7 days.

The command reads events from your connected grant, so you need to be authenticated first. If you haven’t connected a calendar account yet, run nylas auth login and follow the OAuth prompt. The command works with Google Calendar, Outlook, Exchange, Yahoo, iCloud, and IMAP providers.

# Scan the next 7 days (default)
nylas calendar ai conflicts

# Extend the look-ahead window to 14 days
nylas calendar ai conflicts --days 14

# Output as JSON for piping into scripts
nylas calendar ai conflicts --days 7 --json

JSON output groups conflicts by severity and includes the event IDs, titles, start times, end times, and the reason each item was flagged. Use this output to drive a notification or a rescheduling script — pair it with reschedule a meeting from the terminal to move conflicted events without leaving the terminal.

How do you write a jq overlap checker?

A jq overlap check is a deterministic alternative to the AI detector. It works purely on timestamps: two events overlap when one starts before the other ends. This makes the script predictable and auditable — you can read every condition and trace exactly which pair triggered the flag. The approach is reliable for CI jobs and daily cron reports where you want the same logic to produce the same output every run.

The script below fetches the next 14 days of events, extracts each event’s start and end as epoch integers, and then checks every pair for overlap. Events with identical IDs are skipped so an event doesn’t flag itself. The output is a list of overlapping pairs with their titles and times.

nylas calendar events list --days 14 --json | jq '
  # Build a flat list with integer timestamps for comparison
  [.[] | {
    id: .id,
    title: .title,
    start: (.when.start_time | tonumber),
    end:   (.when.end_time   | tonumber)
  }] as $events
  |
  # Compare every pair once (i < j to avoid duplicate pairs)
  [ range($events | length) as $i
  | range($events | length) as $j
  | select($i < $j)
  | $events[$i] as $a
  | $events[$j] as $b
  | select($a.start < $b.end and $b.start < $a.end)
  | {
      conflict: "overlap",
      event_a: { id: $a.id, title: $a.title, start: $a.start, end: $a.end },
      event_b: { id: $b.id, title: $b.title, start: $b.start, end: $b.end }
    }
  ]'

An empty array means no overlaps in the next 14 days. A non-empty array means at least one pair of events shares a time window. Pipe the result to jq length for a quick count or jq -e ". == []" to exit non-zero when conflicts exist — useful as a CI gate.

How do you run a daily conflict check?

A daily conflict check that emails you the results is a straightforward cron pattern. The script below combines both detection methods: the AI scanner for severity-classified output and the jq overlap check for raw overlap count. It runs at 7 AM every weekday and sends a summary to your inbox using nylas email send. Setting this up takes about 5 minutes and replaces manual morning calendar review.

Save the script, make it executable, then add a crontab entry. The script writes output to a temp file so the email body can capture both the AI report and the overlap count. Authentication uses environment variables so no interactive prompt appears during the cron run — see the getting started guide for headless auth setup with NYLAS_API_KEY and NYLAS_GRANT_ID.

#!/usr/bin/env bash
# conflict-check.sh — daily calendar conflict report
set -euo pipefail

REPORT=$(mktemp)

echo "=== AI Conflict Scan ===" >> "$REPORT"
nylas calendar ai conflicts --days 7 >> "$REPORT" 2>&1

echo "" >> "$REPORT"
echo "=== Overlap Count (next 14 days) ===" >> "$REPORT"
OVERLAP_COUNT=$(nylas calendar events list --days 14 --json | jq '
  [.[] | { id: .id, start: (.when.start_time | tonumber), end: (.when.end_time | tonumber) }] as $e
  | [range($e|length) as $i | range($e|length) as $j | select($i < $j)
     | $e[$i] as $a | $e[$j] as $b
     | select($a.start < $b.end and $b.start < $a.end)] | length')
echo "Overlapping event pairs: $OVERLAP_COUNT" >> "$REPORT"

nylas email send \
  --to "${NOTIFY_EMAIL}" \
  --subject "Calendar conflict report: $(date +%Y-%m-%d)" \
  --body "$(cat "$REPORT")"

rm -f "$REPORT"
# Add to crontab: 7 AM on weekdays
# crontab -e, then add:
0 7 * * 1-5 NYLAS_API_KEY=your_key NYLAS_GRANT_ID=your_grant NOTIFY_EMAIL=you@example.com /path/to/conflict-check.sh

Replace the inline environment variables with references to a secrets file (e.g. source ~/.config/nylas/env) if your cron daemon doesn’t inherit your shell environment. Never hard-code API keys in scripts checked into version control.

How do you investigate a flagged conflict?

Once a conflict is flagged, you need the full event details to decide whether to reschedule, decline, or send a note. The nylas calendar events show command returns the complete event record including title, attendees, conferencing links, and recurrence rules. Reviewing this takes about 10 seconds per conflict, versus 2-3 minutes of clicking through a calendar UI to find and compare two overlapping events.

Pipe the output through jq to extract only the fields you care about. The example below pulls title, start, end, and attendee emails for a quick triage view.

# Inspect a specific event by ID (get IDs from the overlap script output)
nylas calendar events show --id EVENT_ID_HERE --json | jq '{
  title: .title,
  start: .when.start_time,
  end:   .when.end_time,
  attendees: [.participants[].email]
}'

If the conflict involves a recurring event, the recurrence field in the output tells you the RRULE. Modifying only the conflicted instance without touching the series requires the event’s master ID and instance ID — both appear in the --json output from calendar events show.

How do you use conflict detection as a CI gate?

A conflict detection CI gate is a job step that blocks a deployment or release process when the calendar shows a hard conflict in the next 2 hours. Many engineering teams have a policy of not releasing during a scheduled incident review, all-hands, or known maintenance window — this check enforces that policy automatically. It adds under 5 seconds to a pipeline and requires no external scheduling service.

The gate below exits with code 1 if nylas calendar ai conflicts returns any hard-severity event in the next 2 days. Add it as a step before your deployment step in GitHub Actions, CircleCI, or any CI system that respects exit codes. According to Nylas Calendar API docs, the AI conflicts command returns structured JSON with a severity field per flagged event, making programmatic filtering straightforward.

#!/usr/bin/env bash
# ci-calendar-gate.sh — block deploy during a hard calendar conflict
set -euo pipefail

CONFLICTS=$(nylas calendar ai conflicts --days 2 --json)

HARD=$(echo "$CONFLICTS" | jq '[.[] | select(.severity == "hard")] | length')

if [ "$HARD" -gt 0 ]; then
  echo "Deployment blocked: $HARD hard calendar conflict(s) in the next 2 days."
  echo "$CONFLICTS" | jq '.[] | select(.severity == "hard") | {title: .title, start: .start}'
  exit 1
fi

echo "No hard conflicts. Safe to deploy."
exit 0

Use severity == "soft" if you want to warn (but not block) on back-to-back meetings. A soft check can write to a Slack channel without failing the pipeline step.

What if the conflict detector returns no results?

An empty result from nylas calendar ai conflicts means either there are no conflicts or the command is reading the wrong calendar. The first thing to verify is which grant is active. Run nylas calendar events list --days 1 and confirm the events listed match what you expect to see. If events are missing, the connected grant may be pointing at a secondary calendar rather than the primary one that holds your meetings.

A second cause is the look-ahead window. The default is 7 days. If your double-booking is on day 8 or later, use --days 14 or --days 30 to extend the scan. The jq overlap script accepts --days N on the events list call, so the same adjustment applies there.

If events are present but no conflicts appear despite a visible overlap, verify the event timestamps. All-day events use a date field instead of start_time and end_time. The jq overlap script above reads when.start_time and when.end_time, which are only set on timed events. All-day events are excluded from the jq check by design — the AI detector handles them separately and classifies them as soft conflicts when they coincide with timed events.

Tested on Nylas CLI 3.1.16 with Google Calendar. Provider-side behavior for Outlook, Exchange, Yahoo, iCloud, and IMAP is documented by Nylas but not verified end-to-end against each backend — test locally before deploying provider-specific rules.

References

Next steps