Install the NeetoCal CLI
macOS with Homebrew:
brew install neetozone/tap/neetocal
macOS or Linux:
curl -fsSL https://neeto-downloads.s3.amazonaws.com/cli/NeetoCal/latest/install.sh | sh
Windows (PowerShell):
irm https://neeto-downloads.s3.amazonaws.com/cli/NeetoCal/latest/install.ps1 | iex
Then sign in. This opens your browser, and there's no API key to manage:
neetocal login --subdomain your-workspace
To teach your AI coding assistant how to use the CLI, run one of these from your project folder:
neetocal setup claude # Claude Code
neetocal setup cursor # Cursor
neetocal setup codex # Codex
neetocal setup copilot # GitHub Copilot
neetocal setup gemini # Antigravity CLI and Gemini CLI
neetocal setup windsurf # Devin (formerly Windsurf)
Every command supports --json for scripts and --toon, a compact format that uses fewer tokens when an AI assistant reads the output. See the NeetoCal CLI reference for every command.
Automate with the CLI
Why use a CLI when MCP already exists? Because some tasks don't need AI at all. You can run them on a schedule using the NeetoCal CLI and familiar tools like jq, curl, and your cloud CLI. No AI account, no model usage costs, and consistent results every time.
Generate your daily agenda
Save this as ~/agenda.sh and make it executable:
#!/bin/sh
neetocal bookings list --host-email sam@example.com --type upcoming \
--sorting-key starts_at --sorting-order asc --json \
| jq -r '.data[] | "\(.starts_at) \(.name) \(.meeting.name)"' \
> ~/agenda.txt
Then add it to your crontab to run every weekday at 8am:
0 8 * * 1-5 ~/agenda.sh
Back up every booking nightly
Export all bookings as JSON and save them to your cloud storage bucket every night.
for type in upcoming past cancelled; do
page=1
while :; do
out=$(neetocal bookings list --type "$type" \
--page "$page" --page-size 100 --json) || exit 1
echo "$out" | jq -c '.data[]'
total=$(echo "$out" | jq '.pagination.total_pages')
[ "$total" -le "$page" ] && break
page=$((page + 1))
done
done > bookings.jsonl
aws s3 cp bookings.jsonl \
"s3://your-backup-bucket/neetocal/$(date +%F).jsonl"
Send today's meetings to your CRM
Every night, push today's completed bookings into your internal CRM.
neetocal bookings list --type past \
--sorting-key starts_at --sorting-order desc \
--page-size 100 --json \
| jq -c --arg today "$(date -u +%F)" \
'.data[] | select(.starts_at | startswith($today))' \
| while read -r booking; do
curl -s -X POST -H "Content-Type: application/json" \
-d "$booking" https://crm.example.com/api/meetings
done
Watch for cancellations
Every hour, post new cancellations to your operations channel.
touch cancelled-seen.txt
neetocal bookings list --type cancelled --page-size 100 --json \
| jq -r '.data[].sid' | sort > cancelled-now.txt
comm -13 cancelled-seen.txt cancelled-now.txt | while read -r sid; do
curl -s -X POST -H "Content-Type: application/json" \
-d "{\"text\": \"NeetoCal booking $sid was canceled\"}" \
"$SLACK_WEBHOOK_URL"
done
mv cancelled-now.txt cancelled-seen.txt
Weekly utilization report
Every Monday, total the hours each host spent in meetings last week and write a CSV.
start=$(date -v-7d +%F) # on Linux: date -d "7 days ago" +%F
today=$(date +%F)
neetocal bookings list --type past \
--sorting-key starts_at --sorting-order desc \
--page-size 100 --json \
| jq -r --arg start "$start" --arg today "$today" '
def ts: sub("\\.[0-9]+Z$"; "Z") | fromdate;
[.data[]
| select(.starts_at >= $start and .starts_at < $today)]
| group_by(.host_email)[]
| [.[0].host_email,
(map((.ends_at | ts) - (.starts_at | ts)) | add / 3600)]
| @csv' > "utilization-$start.csv"
For teams with more than 100 meetings a week, add the paging loop from the backup example.
Export all past bookings to a spreadsheet
page=1
while :; do
out=$(neetocal bookings list --type past \
--page "$page" --page-size 100 --json) || exit 1
echo "$out" | jq -r '.data[]
| [.starts_at, .name, .email, .meeting.name, .status] | @csv'
total=$(echo "$out" | jq '.pagination.total_pages')
[ "$total" -le "$page" ] && break
page=$((page + 1))
done > past-bookings.csv
Cancel a batch of bookings in one go
A client pauses their engagement and every upcoming session with them has to go.
neetocal bookings list --client-email jane@acme.com \
--type upcoming --json \
| jq -r '.data[].sid' \
| while read -r sid; do
neetocal bookings update "$sid" --status cancelled \
--cancel-reason "Engagement paused"
done
Set up a new employee
When someone joins, add them to NeetoCal and give them a standard intro call, straight from your onboarding script.
neetocal team-members create --emails oliver@example.com \
--organization-role Standard
neetocal meetings create \
--name "Intro call with Oliver" --slug oliver-intro \
--hosts oliver@example.com --kind one_on_one \
--spot jitsi --duration 30
Let a coding agent build it for you
You don't have to write these scripts yourself. Claude Code, Codex, or another coding agent can write the automation and use the open-source NeetoCal CLI to work with your account. Run neetocal setup claude (or setup codex, setup cursor) once, then ask:
Every weekday at 5 PM, use the NeetoCal CLI to get tomorrow's bookings and create a Markdown agenda. Write the script, test it, and set up the cron job.
Using the NeetoCal CLI, find every booking from acme.com in the last quarter and write a script that exports them to CSV every Monday.
You get the convenience of a chat, and the result is a script you can read, run, and commit.

When to use the CLI and when to use MCP
Both reach the same meetings, bookings, and availability. Neither can do more than the other. Pick based on how the work reaches NeetoCal.
Use MCP when:
- The details are in your chat. An email, a message, or a pasted note becomes a booking with no retyping.
- You haven't decided the steps yet. "Someone double-booked me on Thursday, sort it out" means looking at what's there and choosing.
- You're asking a question. "Why can't anyone book me next week?" needs someone to look around and explain.
- You don't use a terminal. NeetoCal hosts the server. There's nothing to install.
Use the CLI when:
- No AI should be in the loop. A cron job or CI step runs the CLI with nothing but the binary. No model account, no cost per run.
- The output feeds another program. The CLI prints raw JSON or a bare ID for
jq, a spreadsheet, or your own script. - You're working through thousands of records. The CLI pages through everything unattended.
- The run has to be repeatable. A command records exactly what ran and does the same thing every time.
You can also have both. With neetocal setup claude, your AI assistant drives the CLI for you, so a plain-language request still ends in a command you can read and reuse.
Open source
The NeetoCal CLI is open source and available on GitHub. You can inspect its code, see exactly what it sends to NeetoCal, and customize it for your workflows. Written in Go, it runs on macOS, Linux, and Windows.
The NeetoCal CLI is built on neeto-cli-commons, the shared foundation for all Neeto CLI tools. This means the commands and conventions you learn in one Neeto CLI will feel familiar across the others.
Found a bug or have an idea for a new command? Open an issue or submit a pull request on GitHub.
Frequently asked questions
Can I automate NeetoCal without using AI?
Yes. The NeetoCal CLI works directly from your terminal, shell scripts, cron jobs, and CI workflows. You don't need Claude, ChatGPT, or any other AI service to automate tasks.
Is the NeetoCal CLI open source?
Yes. The NeetoCal CLI is open source and available on GitHub. You can inspect the code, modify it, and contribute improvements.