One terminal app for tasks, calendar, and meetings. Keep work in your Backlog, sync with Google Calendar or Apple Calendar, and create Google Meet events with invitations and RSVP support.
Site: mytime.apvl.dev
From source (requires Node 20+ and pnpm):
pnpm install
pnpm build
pnpm link --global # optional: global `mytime` commandHomebrew (macOS) — slim prebuilt pack (~15MB); uses Homebrew Node 20 (installed automatically if needed):
brew tap alexapvl/mytime https://github.com/alexapvl/mytime && brew install mytime
mytime setup google # Google Calendar
# or: mytime setup apple # Apple Calendar, macOS 14+
mytime setup --agent-onboarding-prompt # copy → paste into agentThe tap is one-time; later upgrades are brew upgrade mytime. Bleeding edge from source: brew install mytime --HEAD.
Portable standalone build (includes vendored Node, ~40MB): see releases (*-standalone.tar.gz).
The TUI checks GitHub once per day for updates and shows an upgrade command when a newer main commit is available.
Dev mode (no build):
pnpm devChoose one writable calendar provider. mytime only syncs with the currently active provider, while other calendars from that provider can be fetched read-only.
mytime setup google # Google OAuth setup
mytime setup apple # Apple Calendar via EventKit, macOS 14+
mytime setup # show both provider paths
mytime doctor # check the active provider
mytime setup --links # print Google Cloud Console URLs
mytime setup --agent-prompt # Google OAuth setup prompt for your agent
mytime setup --agents # AI agent + MCP integration guide
mytime setup --agent-onboarding-prompt # paste into Cursor / Claude after installIf an agent is helping and the provider is not already known from the conversation, it must ask whether you want Google Calendar or Apple Calendar before running setup.
Apple Calendar support uses the calendars already configured in Calendar.app. It requires macOS 14 or newer and does not need Google credentials or a separate Apple CLI.
mytime setup apple
mytime syncmacOS asks you to grant Calendar access. mytime then selects or creates a dedicated calendar named for its actual backend, such as "mytime-icloud" or "mytime-google". Other visible calendars can be fetched read-only for Daily, Week, and Month views.
An agent can start setup, inspect permission status, and run sync, but you must approve the macOS Calendar permission prompt yourself. If your Apple Account or another calendar account is not yet in Calendar.app, add it in System Settings → Internet Accounts first.
Run mytime setup google for a checklist, Console links, and next steps.
Google sync needs two local files under ~/.mytime/:
| File | Created by | Purpose |
|---|---|---|
credentials.json |
You (from Google Cloud) | OAuth client ID + secret |
token.json |
mytime auth |
Your signed-in Google account |
Tasks sync to a dedicated calendar named "mytime-google". Google Meet events are created on your primary calendar so you are the organizer and invitations come from your Google account. Other Google calendars can be pulled read-only for display in Daily, Week, and Month views.
Create a Meet event in the TUI with Shift+A, or from an agent:
mytime agent event add \
--title "Sync with Sam" \
--start "2026-07-16T15:30:00+03:00" \
--end "2026-07-16T16:00:00+03:00" \
--guests sam@example.com \
--google-meetGoogle Calendar sends the invitations. In the TUI, respond to incoming invitations with yes, maybe, or no, and press o on an event to open its meeting link.
Only one provider is writable at a time. When switching, mytime stops syncing the old provider, removes its fetched external events from the local cache, preserves your local tasks and events, then fetches from the newly active provider.
Calendar names follow the backend: "mytime-google", "mytime-icloud", or "mytime-local". If EventKit accesses the same Google calendar as the Google API, mytime adopts that calendar and changes only the sync adapter. It never copies or deletes the shared calendar.
For different backends, setup asks whether you also want to delete the old dedicated calendar. The safe default is to keep it. mytime never deletes or writes to unrelated calendars.
Provider switches stay explicit and agent-safe:
mytime setup apple --keep-old-calendar
mytime setup apple --delete-old-calendar
mytime setup google --keep-old-calendar
mytime setup google --delete-old-calendarIf Calendar.app contains multiple writable accounts or dedicated calendars, Apple setup lists them and asks you to rerun with --source <source-id> --calendar <calendar-id>. It never guesses which account or calendar to use.
Duplicate cleanup always starts with a read-only preview:
mytime setup apple --cleanup-duplicates
mytime setup apple --cleanup-duplicates --apply # only after reviewing previewIf you use Cursor, Claude Code, or another agent with browser access, run mytime setup --agent-prompt and paste the output, or copy this prompt:
Help me set up Google Calendar for mytime (https://github.com/alexapvl/mytime).
Goal: mytime needs a Google Cloud OAuth Desktop client saved at ~/.mytime/credentials.json, then I will run `mytime auth` and `mytime sync` locally.
Please do the following:
1. In Google Cloud Console (https://console.cloud.google.com/):
- Create or select a project for personal mytime use.
- Enable the Google Calendar API (APIs & Services → Library → "Google Calendar API").
- Configure OAuth consent screen: External user type, app name "mytime", add my Google account as a Test user. Testing mode is fine.
- Create Credentials → OAuth client ID → Application type "Desktop app".
- Download the client JSON.
2. On my machine:
- Create ~/.mytime if it does not exist.
- Save the downloaded JSON as ~/.mytime/credentials.json (must have an "installed" key with client_id and client_secret).
- Do NOT commit credentials.json to git.
3. Tell me when credentials.json is in place. I will run `mytime auth` myself in the terminal (browser OAuth — you cannot complete this step for me). After auth succeeds, I will run `mytime sync` to verify.
If you can control a browser (e.g. chrome-devtools-axi), navigate the Console for me step by step. Otherwise, give exact click-by-click instructions and pause after each step for confirmation.
After the agent finishes step 2, run mytime auth and mytime sync as described in the manual steps below.
Prefer doing it yourself? You only do this once per machine (or per Google Cloud project).
-
Open Google Cloud Console — console.cloud.google.com
-
Create or select a project
- Top bar → project picker → New Project (e.g.
mytime-personal) or pick an existing one.
- Top bar → project picker → New Project (e.g.
-
Enable the Google Calendar API
- APIs & Services → Library (direct link)
- Search for Google Calendar API → Enable.
-
Configure the OAuth consent screen
- APIs & Services → OAuth consent screen (direct link)
- User type: External (fine for personal use) → Create.
- App information: app name (e.g.
mytime), user support email, developer contact email → Save and Continue. - Scopes: Save and Continue (mytime requests
calendarscope at sign-in; you do not need to add scopes here). - Test users: Add users → your Google account email → Save and Continue.
- Leave the app in Testing — that is enough for a single-user setup.
Note: While the app is in Testing, only test users you add can sign in. If auth fails with access blocked, add your account under OAuth consent screen → Test users.
-
Create OAuth credentials (Desktop app)
- APIs & Services → Credentials (direct link)
- Create Credentials → OAuth client ID
- Application type: Desktop app
- Name: e.g.
mytime desktop→ Create - Download JSON (or use the download icon on the new client).
-
Install the credentials file
mkdir -p ~/.mytime mv ~/Downloads/client_secret_*.json ~/.mytime/credentials.json
The JSON must contain an
installedobject withclient_idandclient_secret(the default format for Desktop app downloads). Do not commit this file. -
Authenticate
mytime auth
This starts a local server on
127.0.0.1:3847, opens your browser for Google sign-in, and saves a token to~/.mytime/token.json. Complete the flow in the browser; you can close the tab when you see mytime authenticated. -
Sync
mytime sync
mytime creates the "mytime" calendar if it does not exist and runs the first two-way sync.
-
Choose which calendars to fetch locally
mytime settings
Toggle external Google calendars on or off. Disabled calendars are not pulled during sync, and their events are removed from the local database. The dedicated mytime calendar is always enabled.
mytime does not ship shared Google OAuth credentials. You create a Desktop OAuth client in your Google Cloud project and keep credentials.json and token.json locally under ~/.mytime/.
That is intentional for a personal tool:
- Privacy — Calendar tokens stay on your machine. mytime never sends them through a maintainer's server.
- Control — You own the GCP project, API access, and test users. Revoke or rotate credentials anytime in Google Cloud Console.
- Scope - tasks write to the dedicated "mytime" calendar. Google Meet events write to your primary calendar so you remain the organizer. Other calendars are read-only and optional in
mytime settings. - No hosted OAuth — A shared OAuth app would need Google verification for public Calendar access, ongoing abuse monitoring, and trust that someone else's server (or embedded client secret) handles your Google account.
The one-time Cloud Console setup is the tradeoff for keeping mytime local-first and maintainer-free. Agent-assisted setup (above) or an AI agent with browser access can do most of the clicking; you still run mytime auth yourself in the terminal for the final browser sign-in.
mytime # interactive TUI
mytime add "review PR tomorrow 3pm @work p2 #swe"
mytime event "dentist tomorrow 2pm" # calendar event (requires date/time)
mytime today # print today's blocks
mytime setup # choose Google or Apple Calendar
mytime setup google # Google setup checklist and Console links
mytime setup apple # Apple Calendar setup, macOS 14+
mytime doctor # verify active provider configuration
mytime sync # sync the active calendar provider
mytime auth # (re)connect the active provider
mytime settings # choose which active-provider calendars to fetch
mytime agent # agent CLI for AI assistants (preferred)
mytime mcp # run the MCP server (stdio) for AI agents
mytime help # show CLI helpFive tabs — switch with number keys or click the tab bar:
| Tab | Key | What it shows |
|---|---|---|
| Backlog | 1 |
Open tasks in P0–P3 columns (scheduled and unscheduled) |
| Daily | 2 |
Hour grid + all-day row for one day |
| Week | 3 |
Seven-day grid with timed blocks |
| Month | 4 |
Month calendar grid; press enter to open a day in Daily |
| Past Due | 5 |
Open tasks that missed their scheduled time |
Global keys
| Key | Action |
|---|---|
1 / 2 / 3 / 4 / 5 |
Backlog / Daily / Week / Month / Past Due |
r |
Sync the active calendar provider |
u |
Undo last delete or done toggle |
esc |
Quit |
Mouse clicks work in supported terminals (tabs, items, calendar cells).
Backlog — ←/→ priority column · ⇧←/→ move task between priorities · ↑/↓ navigate · a add · q quick-add (NLP) · e edit · s schedule/reschedule · x done · d delete
Opens on the lowest non-empty priority column (P0 first, then P1, P2, P3).
Daily — ←/→ prev/next day · t today · ↑/↓ select · a/q add task / quick-add · ⇧a/⇧q add event / quick-event · e edit · s reschedule · ⇧↑/↓ move selected task by 1h · +/- end ±15m · ⇧+/- start ±15m · x done · d delete
Defaults to the first open (not done) item for the day, including all-day tasks.
Week — ←/→ prev/next day · ⇧←/→ prev/next week · t this week/today · ↑/↓ select · a/q add task / quick-add · ⇧a/⇧q add event / quick-event · e edit · s reschedule · ⇧↑/↓ move 1h · +/- end ±15m · ⇧+/- start ±15m · x done · d delete
Defaults to today with the first event on that day selected.
Month — ←/→ prev/next day · ↑/↓ prev/next week · ⇧←/→ prev/next month · t today · enter open focused day in Daily · a/q add task / quick-add on focused day · ⇧a/⇧q add event / quick-event on focused day
Shows a month grid with event previews per day. Navigation wraps within the visible month when changing months.
Past Due — ↑/↓ navigate · e edit · s reschedule · x done · d delete
Schedule editor (when you press s): shows existing events on the chosen day · ←/→ change day · ↑/↓ pick slot · type digits to filter times · f free slots only · +/- slot step (15–240 min) · a all-day · enter confirm · esc cancel
External calendar events from the active provider appear in Daily/Week/Month but are read-only (s/x/d only apply to your tasks).
mytime agent is the AXI-shaped interface for AI agents. Same database and provider-aware sync as the TUI, with token-efficient TOON output and contextual next-step hints. No extra setup beyond mytime on PATH and the calendar provider you choose.
Set up with your agent:
mytime setup --agents # full guide
mytime setup --agent-onboarding-prompt # copy output → paste into Cursor / ClaudeThe onboarding prompt tells your agent to run mytime agent, install the skill, and use the CLI for tasks/calendar.
mytime agent # dashboard: backlog, past due, today
mytime agent calendar # live adapter/backend state + effects
mytime agent calendar setup # explain setup commands and side effects
mytime agent calendar switch # explain keep/delete and migration effects
mytime agent calendar cleanup # explain preview/apply safety
mytime agent backlog list
mytime agent schedule list # today by default
mytime agent slots --date tomorrow
mytime agent task quick "review PR tomorrow 3pm @work p2"
mytime agent search meloDL
mytime agent syncInstall the agent skill (optional):
mytime setup --agent-skill
# or: npx skills add https://github.com/alexapvl/mytime --skill mytime -gSee skills/mytime/SKILL.md for the full command reference.
mytime mcp still runs a Model Context Protocol server over stdio for clients that only support MCP. Prefer mytime agent in Cursor and other shell-capable agents — same behavior, fewer tokens, no schema overhead.
Print ready-to-paste MCP config:
mytime setup --mcp-configOr register manually (global mytime must be on PATH for the MCP host):
{
"mcpServers": {
"mytime": { "command": "mytime", "args": ["mcp"] }
}
}| Tool | Description |
|---|---|
list_backlog |
List all open tasks (scheduled and unscheduled) |
list_schedule |
List scheduled items in a time range (defaults to today) |
list_past_due |
List open overdue tasks with an overdue label |
list_free_slots |
List free timed slots on a day (all-day events listed separately) |
get_item |
Get a single item by id |
search_tasks |
Search by title / project / tags |
add_task |
Create an unscheduled task |
quick_add |
Add from natural language (#tag @project pN, dates) |
update_task |
Update fields of a task |
schedule_task / reschedule_task |
Set/change a task's start (and end or duration) |
complete_task |
Mark done / not done (omit done to toggle) |
delete_task |
Permanently delete a task |
sync |
Full two-way sync with the active calendar provider |
Write tools sync to the active provider automatically when configured (no-ops otherwise). External calendar events (source: external) are read-only via MCP. Call list_free_slots before scheduling to find open times. If the TUI is open at the same time, it won't reflect MCP changes until you navigate or sync.
Everything is stored locally at ~/.mytime/db.sqlite. Scheduled items sync to the active Google or Apple provider; unscheduled backlog tasks stay local until you schedule them.
External calendar events are pulled into the local DB for display. Their titles are stored without emoji so terminal layout stays aligned. Tasks you create in mytime are never modified this way.
Natural language via chrono-node:
buy groceries tomorrow 5pmdentist Friday 10am-11amreview PR @work p2 #swe
Tags: #context · Projects: @name · Priority: p0–p3
