# About Daily

Daily is a personal schedule and life planner that your AI agents can run. You tell an assistant (Claude, or any app that speaks MCP) what your life looks like and what you want from it; it builds and keeps your schedule here, and you see and adjust everything in the app, on your laptop or phone.

- **App:** https://carpeday.app
- **For agents:** MCP at `https://carpeday.app/api/mcp`, this document as Markdown at [https://carpeday.app/about.md](https://carpeday.app/about.md), a short guide at [https://carpeday.app/llms.txt](https://carpeday.app/llms.txt), and the HTTP API spec at [https://carpeday.app/api/v1/openapi.json](https://carpeday.app/api/v1/openapi.json).

## Contents

1. [What you can do](#what-you-can-do)
2. [Connect your agent](#connect-your-agent)
3. [How Daily thinks about your time](#how-daily-thinks-about-your-time)
4. [Working with agents: conventions](#working-with-agents-conventions)
5. [Accounts, sharing and privacy](#accounts-sharing-and-privacy)
6. [Running your own Daily](#running-your-own-daily)
7. [Questions](#questions)
8. [Tool reference](#tool-reference)

## What you can do

Daily is split into sections. Each one is a page in the app, and everything on it can also be done by an agent.

| Section | What's there |
| --- | --- |
| 📅 Calendar | Your days and weeks: drag to move, drag the bottom edge to resize, tap to edit. Travel time shows as striped blocks before events. |
| ✅ Activities | Your to-dos at the top, then everything you do grouped by kind (work, fitness, people, reading, meals, errands, getting around), with how it repeats and when it's next. |
| 🏋️ Fitness | This week's workouts with exercises, weights and reps; how each day's meals add up against your calorie and protein targets; your goals. |
| 🍽️ Food | The week's meal plan and a shopping list for the meals you cook, grouped by store section with rough prices. |
| 💵 Money | A weekly budget from your plan (groceries, eating out, gas, rideshares, your bills' share) and the same plan per month; your bills. |
| 🎧 Content | Your lists: books, audiobooks, podcasts, movies. Each event that plays from a list knows what's up next. |
| 👥 People | Contacts, who to call on drives (in turn), accounts and calendars you share, RSVP links. |
| ⚙️ Settings | Sign-in and keys, syncing with Google or Apple Calendar, connecting agents, Strava and Apple Health, the raw JSON. |

## Connect your agent

**Claude (claude.ai, desktop, mobile).** Settings → Connectors → Add custom connector. Name it Daily and paste `https://carpeday.app/api/mcp`. Claude sends you to Daily to sign in with your passkey, shows what it will be able to do, and you tap Allow. The connection then appears under Settings → Access, where you can revoke it.

**Claude Code.** Run `claude mcp add --transport http daily https://carpeday.app/api/mcp`, then `/mcp` to sign in.

**Any other MCP client.** Point it at `https://carpeday.app/api/mcp`. It discovers the sign-in on its own (OAuth 2.1 with dynamic client registration and PKCE; discovery at `https://carpeday.app/.well-known/oauth-protected-resource`).

**Scripts and servers.** Create an API key under Settings → Access with only the access it needs, and send it as `Authorization: Bearer dly_…`. The same tools are plain HTTP: `POST https://carpeday.app/api/v1/<tool>` with a JSON body (read-only tools also accept `GET` with query parameters). Responses are `{"result": …}` or `{"error": "…"}`.

Then just ask: "Set up my routine in Daily", "Plan my week around three workouts and dinner with Sam on Thursday", "Add renew passport by Friday to my to-dos and find time for it", "What's on tomorrow and when do I need to leave?"

## How Daily thinks about your time

Each idea below is what the app shows and what the tools read and write. Field names are in `code`.

**Events.** Anything with a time: a meeting, a gym session, dinner. An event has a `title`, a `start` and `end`, a `category` (work, meeting, commute, workout, meal, date, movie, social, reading, personal, errand, sleep, other) and a `calendar` (personal, work, relationship, health… you can add more). Optional: a place (`locationId`), `travel`, people (`attendees`, and `optionalAttendees` for maybes), a `workout`, `meals`, `media`, `notes` and `costs`.

**Times are local.** Every time is written `YYYY-MM-DDTHH:mm` in your own time zone (set in settings), with no offset: `2026-11-02T07:00` means 7am wherever you live.

**Repeating events.** `recurrence` turns an event into a routine: `{ "freq": "weekly", "byDay": ["MO", "WE", "FR"] }`, with `interval` (every 2 weeks), `until` or `count`. Change a single day without touching the rest; each day of a routine is addressed as `eventId::YYYY-MM-DD`.

**Seasons.** Named stretches of the year (ski season, summer). A routine can run only during some seasons (`onlyIn`) or pause for them (`notIn`), so a winter Saturday can be a ski day and a summer one disc golf.

**Places and travel.** Places (`locations`) have an address and coordinates. Set your home in settings and Daily estimates travel between places by your usual way of getting around, or uses the minutes you give (`travel: { "minutes": 20, "mode": "drive" }`). If you can't make it in time, it warns you.

**Workouts and meals.** A workout lists exercises with sets, reps, weight and equipment. Meals list what you eat with calories and protein; Daily adds them up per day against your targets. A meal can be someone else's (`for`), so it goes on the grocery list without counting toward your totals. Meals eaten out carry a `cost` for the budget.

**Lists.** Ordered lists of books, podcasts, movies (`queues`). A list either gives a new item each time (movies), stays on one until you finish it (books), or takes turns (podcasts). An event that plays from a list shows what's next.

**People.** Contacts you invite to events and call. A call list rotates: each drive calls the next people in line.

**To-dos.** One-off things to get done, with an optional due date and list. Ones due on a day show up when an agent reads that day.

**Money.** Bills (rent, insurance) count toward each week by their share. Gas is figured from miles with your car's mpg and the gas price. Rideshares, eating out and groceries come from the plan.

**Your profile.** Goals, nutrition targets, age, height and weight, and your car. Agents read these to tune plans.

**History.** Every change records who made it: you in the app (`ui`), an agent (`agent:<name>`), a guest RSVP or an import. `recent_changes` shows the latest.

## Working with agents: conventions

These are for agents, and for anyone curious how they should behave.

1. **Start with `get_started`.** It says what's set up, what's missing (home location, goals, people) and how to build.
2. **Read before writing.** Look at the week with `get_agenda` and the to-dos with `list_tasks`.
3. **Make changes in one plan.** `apply_plan` takes many operations and applies all of them or none. Run it with `"dryRun": true` first; it returns what each operation would make and `check_schedule`'s findings. Fix those, then run it for real.
4. **Name what you create.** Give new things your own short ids (`"gym-mon"`, `"home"`) so later operations in the same plan can point at them.
5. **Change one day, not the routine,** with `update_event` and `"scope": "occurrence"` plus the date.
6. **Check your work** with `check_schedule`: overlaps, not enough travel time, references to people, places or lists that don't exist, and days whose meals are far off target. `find_free_time` finds open slots.
7. **Ask before deleting** things the person made, and explain what you changed in plain words.

A plan looks like this:

```json
{
  "dryRun": true,
  "operations": [
    { "op": "upsert_item", "collection": "locations", "item": { "id": "gym", "name": "Gym", "address": "123 Main St" } },
    { "op": "create_event", "event": { "id": "lift", "title": "Lift", "category": "workout", "calendar": "health",
      "start": "2026-11-02T07:00", "durationMin": 60, "locationId": "gym",
      "recurrence": { "freq": "weekly", "byDay": ["MO", "WE", "FR"] } } },
    { "op": "add_task", "title": "Buy lifting shoes", "due": "2026-11-03" },
    { "op": "update_profile", "patch": { "goals": ["Lift 3x a week"] } }
  ]
}
```

The collections `upsert_item` and `remove_item` work on: locations, people, callLists, media, queues, groceries, workoutTemplates, calendars, subscriptions, seasons, bills, tasks.

## Accounts, sharing and privacy

- **Signing in.** You sign in with a passkey (Face ID, Touch ID, your phone or a security key): no passwords. Each person has their own account and their own schedule; nobody else can see it unless you share.
- **Joining.** People join with an invite link from the owner (People → Accounts), or by signing up if the owner has turned that on.
- **Agents get only what you allow.** Each agent or app has its own key with a set of permissions: read (`schedule:read`), change (`schedule:write`), make share links (`share`), import workouts (`import`), calendar feed only (`feed`), or everything (`admin`, never given to connected apps). Revoke any of them under Settings → Access.
- **Sharing a calendar** with someone who has an account lets them see it, or also edit it. Your meals never count toward their totals.
- **RSVP links** let anyone see one event or one day and reply, without an account. They never show phone numbers or call lists.
- **Calendar feeds** for Google or Apple Calendar carry a read-only token: they can show your calendar but never change it.

## Running your own Daily

Daily is open to run yourself: a Next.js app with a SQLite database (a local file, or Turso when hosted). On your computer: `npm install`, `npm run dev`, and open http://localhost:3000; with no secrets set, it's open to you alone on your machine. To put it online (Vercel + Turso), set `DAILY_DB_URL`, `DAILY_DB_AUTH_TOKEN`, `DAILY_SECRET`, `DAILY_API_TOKEN` and `DAILY_PUBLIC_URL`, deploy, and set up your passkey with the admin token. `DAILY_OPEN_SIGNUP=true` lets anyone create an account.

## Questions

**Does Daily replace Google or Apple Calendar?** It can sit beside them: export your Daily calendars as feeds they subscribe to, and show their calendars inside Daily (read-only).

**What happens if an agent makes a mess?** Every change is logged with who made it (`recent_changes`), `apply_plan` is all-or-nothing, and you can revoke an agent's key at any time.

**Can my partner and I share?** Yes: each of you has an account, and you share a calendar (say, "relationship") with each other to view or edit.

**Is it on my phone?** Open the site and use Share → Add to Home Screen (iPhone) or Install app (Android).

## Tool reference

Every tool is available over MCP and as `POST https://carpeday.app/api/v1/<tool>`. Access names the permission a key needs.

### Start and read

Begin with get_started; read a week with get_agenda.

#### get_started

START HERE. Who this schedule belongs to, what's already set up (calendars, places, people, routines, lists, to-dos, goals) and what's missing, plus how to build a schedule with these tools. Call it first in a new conversation.

- Access: `schedule:read` (read-only)
- Inputs: No inputs.

#### get_agenda

Concrete schedule between two dates (inclusive), with recurring events expanded, travel/leave-by times, who to call on commutes, workouts, meals and media. Each line has a `key` (eventId::date) used by move_event/log_occurrence/share. format=text (default, for reading) or json.

- Access: `schedule:read` (read-only)
- Inputs: `from` (string): YYYY-MM-DD, default today; `to` (string): YYYY-MM-DD, default from+6; `format` (text | json)

#### check_schedule

Find problems between two dates (default: the next two weeks): overlapping events, not enough time to travel between places, events pointing at people/places/lists that don't exist, and days whose meals are far from the calorie target.

- Access: `schedule:read` (read-only)
- Inputs: `from` (string); `to` (string)

#### find_free_time

Open slots between two dates: gaps of at least minMinutes (default 30) between dayStart and dayEnd (default 08:00–21:00), optionally only on some weekdays (days: [MO, TU…]). Travel time to events counts as busy.

- Access: `schedule:read` (read-only)
- Inputs: `from` (string); `to` (string); `minMinutes` (integer); `dayStart` (string); `dayEnd` (string); `days` (list of MO | TU | WE | TH | FR | SA | SU)

#### get_schedule

Raw schedule JSON (the source of truth). Optionally only some top-level sections, e.g. ['events','people'].

- Access: `schedule:read` (read-only)
- Inputs: `sections` (list of string)

#### recent_changes

Most recent writes, newest first: when, which actor (ui, mcp:<client>, api:<name>, guest, import:<source>), and which item changed.

- Access: `schedule:read` (read-only)
- Inputs: `limit` (integer)

### Build and change

apply_plan does many changes at once; the single-purpose tools are there for small edits.

#### apply_plan

Make many changes in one go, all or nothing: operations [{op: create_event, event} | {op: update_event, id, patch, scope?, date?} | {op: move_event, key, start, end?} | {op: delete_event, key, scope?} | {op: upsert_item, collection, item} | {op: remove_item, collection, id} | {op: add_task, title, due?, list?} | {op: complete_task, id} | {op: update_profile, patch} | {op: update_settings, patch}]. dryRun: true tries it without saving. Either way it returns what each operation made and check_schedule's findings for checkFrom..checkTo (default: the next two weeks).

- Access: `schedule:write`
- Inputs: `operations` (list of items, required); `dryRun` (boolean); `checkFrom` (string); `checkTo` (string)

#### create_event

Create an event. Times are local 'YYYY-MM-DDTHH:mm'. Give `end` or `durationMin`. Optional: category (work|meeting|commute|workout|meal|date|movie|personal|errand|sleep|other), calendar (personal|work|relationship|…), locationId, travel {minutes, mode}, recurrence {freq: daily|weekly|monthly, interval, byDay:[MO..SU], until, count}, callListId, workout {kind, exercises:[{name, equipment, sets, reps, weight, unit}]}, meals [{slot, items:[{name, calories, protein, buy:[{grocery, qty}]}], source: home|out, servings, cost, for: personId when it's someone else's portion (shopping only, not your totals)}], media [{mediaId, note}], costs [{label, amount, kind: food|drinks|gas|rideshare|activity|gear|other, miles (gas only: priced with profile.car)}], notes.

- Access: `schedule:write`
- Inputs: `event` (object, required)

#### update_event

Patch an event's fields. For a recurring event, scope='occurrence' + date changes just that day (stored as an override); default scope is the whole series.

- Access: `schedule:write`
- Inputs: `id` (string, required); `patch` (object, required); `scope` (occurrence | series); `date` (string)

#### move_event

Reschedule (like drag-and-drop) by occurrence key from get_agenda. scope 'occurrence' (default) moves one day; 'series' shifts every occurrence.

- Access: `schedule:write`
- Inputs: `key` (string, required); `start` (string, required); `end` (string); `scope` (occurrence | series)

#### delete_event

Delete an event (scope 'series', default) or cancel one occurrence of a recurring event (scope 'occurrence' with a key).

- Access: `schedule:write`
- Inputs: `key` (string, required): event id or occurrence key; `scope` (occurrence | series)

#### log_occurrence

Log what actually happened for an occurrence: status (done|skipped), notes, people actually called, actual workout sets/weights, meals eaten, media consumed. Marking a queue-driven event (e.g. movie night) done ticks off its up-next item so the next occurrence moves on.

- Access: `schedule:write`
- Inputs: `status` (planned | done | skipped); `log` (string); `called` (list of string); `workout` (object); `meals` (list of object); `media` (list of object); `key` (string, required)

#### upsert_item

Create or update a library item. collection: locations {id,name,address,lat,lng} | people {id,name,phone,email} | callLists {id,name,people:[personId],perSession} | media {id,kind: audiobook|podcast|youtube|playlist|music|movie|series,title,creator,url,progress,done} | queues {id,name,mode: each (one item per session, e.g. movies) | untilDone (stay on the current item until marked done, e.g. books) | rotate (cycle, e.g. podcasts),items:[mediaId]} (set an event's queueId to play from it) | workoutTemplates {id,name,kind,exercises} | calendars {key,name,color} | subscriptions {id,name,url (secret ICS URL),calendar} | groceries {id,name,section,unit,pack:{size,label,price},pricePerUnit,staple} | seasons {id,name,ranges:[{from,to}]} (recurring events can set recurrence.onlyIn / notIn to season ids) | bills {id,name,amount,every: month|year,day,kind: rent|insurance|utilities|subscription|other,notes} (counted in weekly_budget).

- Access: `schedule:write`
- Inputs: `collection` (locations | people | callLists | media | queues | groceries | workoutTemplates | calendars | subscriptions | seasons | bills | tasks, required); `item` (object, required)

#### remove_item

Remove a library item by id (calendars by key).

- Access: `schedule:write`
- Inputs: `collection` (locations | people | callLists | media | queues | groceries | workoutTemplates | calendars | subscriptions | seasons | bills | tasks, required); `id` (string, required)

#### update_profile

Patch the profile: ageYears, heightIn, weightLb, goals [string], nutrition {calories, proteinG, carbsG, fatG, notes}, car {name, mpg, gasPrice (USD/gal), owned}. Daily meal totals in get_agenda are compared against nutrition targets; gas costs given in miles are priced with the car.

- Access: `schedule:write`
- Inputs: `patch` (object, required)

#### update_settings

Change settings: timezone (IANA, e.g. America/New_York), homeLocationId (a location id; travel is estimated from it), weekStartsOn (0 Sun – 6 Sat), dayStartHour / dayEndHour (the calendar's visible hours), defaultTravelMode (drive, transit, walk, bike, rideshare).

- Access: `schedule:write`
- Inputs: `patch` (object, required)

#### replace_schedule

Replace the ENTIRE schedule JSON (validated). Prefer the targeted methods; use this for bulk restructuring. Read with get_schedule first.

- Access: `admin`
- Inputs: `schedule` (object, required)

### To-dos

#### list_tasks

To-dos: open ones (overdue and undated first, with due dates and lists) and ones checked off in the last week. Use add_task / complete_task to change them.

- Access: `schedule:read` (read-only)
- Inputs: No inputs.

#### add_task

Add a one-off to-do. Optional: due (YYYY-MM-DD), list (e.g. Home, Paigy, Errands), notes.

- Access: `schedule:write`
- Inputs: `title` (string, required); `due` (string); `list` (string); `notes` (string)

#### complete_task

Check a to-do off by id (done: false puts it back).

- Access: `schedule:write`
- Inputs: `id` (string, required); `done` (boolean)

### Food and money

#### shopping_list

Groceries for the home meals in a week, grouped by store section with quantities, whole packs and an estimated cost; pantry staples listed separately. Default: 7 days from the next grocery run. format=text (default) or json.

- Access: `schedule:read` (read-only)
- Inputs: `from` (string): YYYY-MM-DD; `days` (integer); `format` (text | json)

#### weekly_budget

Planned spending for a week: groceries (from the shopping list), eating out (meals with source 'out': office café, restaurants, bars, with what to order and cost), gas (event.costs kind gas, in dollars or miles priced with profile.car), rideshares, other event costs (tickets, gear…) and each bill's share of the week (rent, insurance), plus the same plan per month. Default: 7 days from the next grocery run.

- Access: `schedule:read` (read-only)
- Inputs: `from` (string): YYYY-MM-DD; `days` (integer)

### Sharing and calendars

#### share

Create a public link someone can open and RSVP to. scope: 'event' (whole series), 'occurrence' (eventId + date), or 'day' (date).

- Access: `share`
- Inputs: `scope` (event | occurrence | day, required); `eventId` (string); `date` (string); `invitee` (string)

#### list_shares

All share links with their RSVPs.

- Access: `schedule:read` (read-only)
- Inputs: No inputs.

#### calendar_feed_urls

Subscription URLs for Google Calendar / Apple Calendar (all events, or one calendar such as 'work').

- Access: `schedule:read` (read-only)
- Inputs: No inputs.

### Imports

#### import_activities

Import completed activities (e.g. from Strava or Apple Health) as done workout events; dedupes by externalId per source.

- Access: `import`
- Inputs: `source` (string, required); `activities` (list of object, required)

### Keys

Only with the admin scope.

#### list_api_keys

API keys for agents and integrations: name, scopes, when created and last used, and whether revoked. Secrets are never shown again.

- Access: `admin` (read-only)
- Inputs: No inputs.

#### create_api_key

Create a key for one agent or integration. scopes: schedule:read, schedule:write, share, import, feed, admin. Returns the token once (dly_…); the agent sends it as `Authorization: Bearer <token>` and its writes are logged as agent:<name>.

- Access: `admin`
- Inputs: `name` (string, required); `scopes` (list of schedule:read | schedule:write | share | import | feed | admin, required)

#### revoke_api_key

Revoke an API key by id; it stops working at once.

- Access: `admin`
- Inputs: `id` (string, required)
