Guide

Block Focus Time on Your Calendar (CLI)

Create busy blocks from the terminal to protect deep-work windows before meetings can fill them. Find open mornings with availability check, then lock them with events create.

Written by Qasim Muhammad Staff SRE

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

According to Asana's research on context-switching, a single interruption costs 23 minutes of recovery time before a developer returns to full focus. Most engineers lose 2 hours a day to meeting fragmentation alone. The fix isn't better discipline — it's blocking time before the invites arrive.

Nylas CLI gives you two commands to automate this. First, find open windows with nylas calendar availability check. Second, lock those windows with nylas calendar events create --busy. Combine them in a shell script and run it on a cron schedule each evening.

Why automate focus blocks instead of adding them manually?

Manual focus blocks work until you forget to add one, or a recurring meeting moves and leaves a gap. Automated blocking runs every night and fills open windows before your colleagues can. It also removes the guilt of declining a meeting — your calendar already shows you busy. Harvard Business Review's 2017 survey found that executives waste an average of 23 hours per week in unproductive meetings — and that the majority of those meetings could be eliminated without loss.

A typical developer calendar has 3 to 4 meetings before 10 AM on any given Monday. That fragmentation makes deep work nearly impossible before noon. Running a blocking script the night before creates a first-mover advantage: your focus window is reserved before anyone books a 9 AM status call.

Automation also makes the behavior consistent across vacations, holidays, and schedule changes. You write the script once, and it runs for months without manual intervention. If your schedule changes — say, you move to a later morning window — you update one variable in the script rather than rebooking dozens of calendar entries.

How do you find open windows on your calendar?

Finding open windows means calling nylas calendar availability check against your own grant ID with a start and end window. The command returns free/busy data as JSON in under 2 seconds. You pass it a time range for the upcoming morning and parse the result to decide whether the window is still open.

The command below checks whether your calendar is free between 9 AM and 11 AM tomorrow morning. Pass your own email as the only participant to check your personal availability, not a group.

# Check if tomorrow 9-11 AM is free
TOMORROW=$(date -v+1d "+%Y-%m-%dT09:00:00Z" 2>/dev/null || date -d "tomorrow" "+%Y-%m-%dT09:00:00Z")
END=$(date -v+1d "+%Y-%m-%dT11:00:00Z" 2>/dev/null || date -d "tomorrow" "+%Y-%m-%dT11:00:00Z")

nylas calendar availability check "$NYLAS_GRANT_ID" \
  --emails "$YOUR_EMAIL" \
  --start "$TOMORROW" \
  --end "$END" \
  --json

Use UTC timestamps in scripts. That keeps cron jobs and local developer machines from disagreeing on timezone math — especially across daylight saving time transitions. Convert to display time only at the output step.

How do you find the best open morning slot across several days?

When you want the best available morning across an entire week, use nylas calendar find-time. This command scores candidate slots against working hours, timezones, and holidays, returning a ranked list rather than a raw free/busy answer. It's more useful when you want to pick the earliest available 2-hour slot across the next 5 days.

The command below searches for a 120-minute open window across the next 5 days and returns results sorted by quality. Pipe the output to jq to extract the first suggested slot before passing it to the blocking step.

nylas calendar find-time \
  --participants "$YOUR_EMAIL" \
  --timezones America/Toronto \
  --duration 120m \
  --days 5 \
  --json | jq '.[0]'

How do you create a busy block that prevents bookings?

A busy block is a calendar event with the --busy flag. This tells the provider — Google Calendar in this case — to show you as unavailable during that window so scheduling tools and colleagues can't book over it. An event created without --busy appears as free time and won't block incoming invites.

The nylas calendar events create command requires three flags: --title, --start, and --end. Adding --busy marks the window as unavailable. The command completes in under 1 second and the block appears on your calendar immediately.

nylas calendar events create "$NYLAS_GRANT_ID" \
  --title "Focus Time" \
  --start "2026-06-10T09:00:00Z" \
  --end "2026-06-10T11:00:00Z" \
  --description "Deep work block. No meetings." \
  --busy

Give the block a consistent title across all your scripts, like "Focus Time" or "Deep Work". That way you can grep your calendar with nylas calendar events list to audit existing blocks before creating duplicates.

How do you wire availability check and event creation into one script?

The full automation connects three steps: check tomorrow's availability window, skip the block if the window is already busy, then create the block if it's open. This script is safe to run nightly — it won't stack duplicate focus blocks because it checks first and exits early if the window is occupied.

The script below uses set -euo pipefail to fail loud on any error and parses the availability JSON with jq. Adjust FOCUS_START_HOUR and FOCUS_END_HOUR to match your preferred deep-work window — most engineers find 9 AM to 11 AM or 8 AM to 10 AM most effective before standup interrupts the morning.

#!/usr/bin/env bash
set -euo pipefail

# Configure these for your schedule
YOUR_EMAIL="you@example.com"
FOCUS_START_HOUR="09"
FOCUS_END_HOUR="11"
TITLE="Focus Time"

# Build tomorrow's window in UTC
# macOS uses -v+1d; Linux uses --date="tomorrow"
FMT_START="+%Y-%m-%dT$FOCUS_START_HOUR:00:00Z"
FMT_END="+%Y-%m-%dT$FOCUS_END_HOUR:00:00Z"
TOMORROW_START=$(date -v+1d "$FMT_START" 2>/dev/null || date -d "tomorrow" "$FMT_START")
TOMORROW_END=$(date -v+1d "$FMT_END" 2>/dev/null || date -d "tomorrow" "$FMT_END")

echo "Checking availability: $TOMORROW_START -> $TOMORROW_END"

# Step 1: Check if the window is free
availability=$(nylas calendar availability check "$NYLAS_GRANT_ID" \
  --emails "$YOUR_EMAIL" \
  --start "$TOMORROW_START" \
  --end "$TOMORROW_END" \
  --json)

# Step 2: Exit if the window is already busy
busy=$(echo "$availability" | jq -r '.busy // false')
if [ "$busy" = "true" ]; then
  echo "Window is already busy — skipping focus block."
  exit 0
fi

# Step 3: Create the busy block
nylas calendar events create "$NYLAS_GRANT_ID" \
  --title "$TITLE" \
  --start "$TOMORROW_START" \
  --end "$TOMORROW_END" \
  --description "Deep work block. No meetings." \
  --busy

echo "Focus block created: $TOMORROW_START -> $TOMORROW_END"

How do you run the blocking script every night automatically?

A cron job that runs at 8 PM each evening ensures your focus block is on the calendar before your colleagues start their morning planning sessions. Most calendar invite senders check your availability as they compose — a block that exists by 8 PM is protected for the next day.

Add the cron entry with crontab -e. The example below runs the script at 8 PM in your local timezone. Set NYLAS_GRANT_ID and NYLAS_API_KEY as environment variables in your shell profile or pass them directly in the crontab line.

# Edit your crontab
crontab -e

# Add this line to run the blocking script at 8 PM every weekday
0 20 * * 1-5 NYLAS_GRANT_ID=your_grant_id NYLAS_API_KEY=your_key /path/to/block-focus.sh >> /tmp/focus-block.log 2>&1

The script writes output to /tmp/focus-block.log so you can review yesterday's run with tail /tmp/focus-block.log. On macOS, you can also use a launchd plist; on Linux servers, systemd timers are a reliable alternative to cron for long-running pipelines.

How do you check which focus blocks are already on your calendar?

Before creating new blocks, it helps to audit existing ones. Running nylas calendar events list with --json and piping to jq filters for events matching your focus block title. This confirms which mornings already have protection and avoids creating duplicate events across the same window.

The command below lists the next 20 calendar events and filters for any titled "Focus Time". If you use a different block title in your script, update thejq filter to match.

nylas calendar events list "$NYLAS_GRANT_ID" \
  --limit 20 \
  --json | jq '[.[] | select(.title == "Focus Time")]'

Verify

Tested on Nylas CLI 3.1.16 against Google Calendar. To confirm the full flow works end-to-end, run the availability check, create one focus block manually, then list events and verify the block appears with status busy. Provider-side availability behavior for Outlook and other calendars is described from documented provider behavior — verify locally before deploying to non-Google accounts.

# 1. Check availability for a test window
nylas calendar availability check "$NYLAS_GRANT_ID" \
  --emails "$YOUR_EMAIL" \
  --start "2026-06-10T09:00:00Z" \
  --end "2026-06-10T11:00:00Z" \
  --json

# 2. Create the test focus block
nylas calendar events create "$NYLAS_GRANT_ID" \
  --title "Focus Time" \
  --start "2026-06-10T09:00:00Z" \
  --end "2026-06-10T11:00:00Z" \
  --busy

# 3. Confirm the block is on your calendar
nylas calendar events list "$NYLAS_GRANT_ID" --json | jq '[.[] | select(.title == "Focus Time")]'

References

Next steps