Skip to content

vamoose

Providers

vamoose talks to a calendar backend through one Provider interface. Four ship today: Microsoft Graph, Google Calendar, Apple iCloud, and any standard CalDAV host. Select one with --provider or VAMOOSE_PROVIDER (default graph). They run the same commands.

Microsoft Graph (Outlook, Microsoft 365, Teams)

vamoose acts as you through the OAuth device-code flow.

  1. Register an application in the Microsoft Entra admin center. Enable Allow public client flows so device code works.
  2. Grant these delegated permissions with admin consent: User.Read, User.Read.All, Calendars.ReadWrite, MailboxSettings.ReadWrite, offline_access.
  3. Export the settings:
export VAMOOSE_CLIENT_ID=<application-client-id>
export VAMOOSE_TENANT=<tenant-id-or-organizations>
export VAMOOSE_TIMEZONE=America/Chicago

The first command opens a device-code prompt. Tokens cache under your config directory and refresh automatically.

Google Calendar

Use --provider google. Google Calendar needs an OAuth client of your own. vamoose does not ship one, so this is a ten-minute setup you do once, in the Google Cloud console, with no cost and no approval from anyone.

Why you create your own client

Google classifies the calendar scopes vamoose needs as sensitive. An app that requests them and has not passed Google's OAuth verification is limited to a fixed list of test users its owner adds by hand. A built-in client shipped in the binary would not remove this setup. It would replace it with "ask the maintainer to add your address to a list," which is slower and puts someone else between you and your first command. Your own client has no such limit for you, and it works inside a Google Workspace that allowlists apps, where a third-party client would not.

Create the client

  1. Open the Google Cloud console and create a project, or select an existing one. Any name works, and nobody else sees it.
  2. Enable the Calendar API: APIs & Services then Library, search for Google Calendar API, and click Enable.
  3. Go to Google Auth Platform then Branding. Give the app a name (vamoose is fine), a user support email, and a developer contact email. Save.
  4. Go to Audience. If you are on a Google Workspace and everyone who will use this client is in your organization, choose Internal and skip to step 6. Otherwise choose External, then scroll to Test users, click Add users, and add the Google account you will sign in with. Consent is denied until you do this.
  5. Note the Publishing status on that page. Leave it as Testing unless you have read the refresh-token note below.
  6. Go to Clients then Create client. Set Application type to Desktop app, name it, and click Create. Copy the client ID and client secret.

Sign in

export VAMOOSE_PROVIDER=google
export VAMOOSE_GOOGLE_CLIENT_ID=<oauth-desktop-client-id>
export VAMOOSE_GOOGLE_CLIENT_SECRET=<oauth-desktop-client-secret>
vamoose login

login opens your browser, serves the consent redirect on a loopback address on your own machine, and caches the token under your config directory. Later commands refresh it without asking again. Run vamoose doctor first if you want to confirm the setup before it touches a calendar.

Because the client is unverified, the consent screen shows a Google hasn't verified this app warning. It is your own client, so this is expected: choose Advanced and then Go to vamoose.

What vamoose asks for

Two delegated scopes, and nothing else:

Scope Why  
https://www.googleapis.com/auth/calendar.events Create, update, and cancel the holds a workflow manages.
https://www.googleapis.com/auth/calendar.readonly Read attendee responses, which is how approval is detected.

The exchange uses PKCE. Desktop-client credentials are not confidential, and Google issues them to installed apps that cannot keep a secret, so the protection is PKCE and the consent screen rather than the values themselves. That is why it is safe to keep them in your shell profile, though a secret manager is still tidier.

Refresh tokens expire after seven days in Testing

This applies to an External app only. If you chose Internal in step 4, skip this section.

While an external app's publishing status is Testing, Google expires its refresh tokens after seven days. Commands then fail and vamoose login signs you back in. If you run vamoose daemon, this is the reason it will stop advancing holds about a week after setup. The daemon reports the refresh failure rather than silently prompting for a sign-in nobody is there to complete.

Moving the app to In production removes the seven-day expiry. Google asks apps in production that use sensitive scopes to complete verification, so for a client only you use, staying in Testing and signing in weekly is usually the simpler trade. Google's OAuth verification docs are the current authority on which of these applies to you.

Directory

Google Calendar exposes no organizational directory, so vamoose cannot look up your manager or your peers. Pass your approver with --manager and set your team once with vamoose team set.

Troubleshooting

Symptom Cause and fix  
no Google OAuth client configured Neither variable is set, or only one is. The override is all or nothing: export both.
Consent denied with access_denied The signing-in account is not on the test-user list. Add it under Audience then Test users.
redirect_uri_mismatch The client is not a Desktop app. Web clients reject loopback redirects. Create a desktop client.
invalid_client The ID and secret do not match, or they come from different projects. Copy both from the same client.
Google Calendar API has not been used in project ... Step 2 was skipped. Enable the Google Calendar API.
Worked for a week, now every command asks you to sign in again The seven-day refresh expiry above. Run vamoose login.
Approval is never detected The approver must accept the calendar invite from the address you passed to --manager. Check with vamoose check.

Apple iCloud (CalDAV)

Use --provider icloud. iCloud speaks CalDAV. Create an app-specific password at appleid.apple.com (your Apple ID must have two-factor auth on), then export:

export VAMOOSE_PROVIDER=icloud
export VAMOOSE_ICLOUD_USERNAME=you@icloud.com
export VAMOOSE_ICLOUD_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx

Set a target calendar with VAMOOSE_ICLOUD_CALENDAR="Home". The default is the first calendar that accepts events. Like Google, iCloud has no directory, so pass your approver with --manager and set your team with vamoose team set.

Approval on iCloud. iCloud creates the hold and emails the manager the invite, but it does not report the manager's accept or decline back over CalDAV. Two ways still get you approval:

  • macOS EventKit. Build the helper with make eventkit. vamoose then reads the manager's accept or decline from your local Calendar.app, so check and the daemon detect approval on iCloud too. Grant calendar access on the first run.
  • Slack. Approve or decline with a button in Slack, which works regardless of backend. See Slack.

Without either, promote by hand once you know the manager accepted.

Any CalDAV host (Fastmail, Nextcloud, and more)

Use --provider caldav for any standard CalDAV server. Point it at the server URL and pass your account credentials, using an app-specific password where the host offers one:

export VAMOOSE_PROVIDER=caldav
export VAMOOSE_CALDAV_URL=https://caldav.fastmail.com
export VAMOOSE_CALDAV_USERNAME=you@fastmail.com
export VAMOOSE_CALDAV_PASSWORD=xxxx-xxxx-xxxx-xxxx

Set a target calendar with VAMOOSE_CALDAV_CALENDAR="Work". The default is the first calendar that accepts events. Like Google and iCloud, a CalDAV host has no directory, so pass your approver with --manager and set your team with vamoose team set.

Unlike iCloud, a standard CalDAV host reports the manager's accept or decline over CalDAV, so check and the daemon detect approval with no extra setup.

Tokens

Tokens are cached per provider under your user config directory and refreshed on use. Run vamoose login to sign in and cache a token, then vamoose whoami to confirm auth and directory access before creating holds.