schd-client
v1.1.0
Published
API client, CLI, and MCP server for PlanOnToday
Maintainers
Readme
schd-client
API client library, schd CLI, and schd-mcp MCP server for
PlanOnToday — lets 3rd-party tools and AI
assistants read and change your schedule through the server's /api/v1
(see GET /api/v1/openapi.json for the full API description).
Three ways to connect an AI agent:
- MCP (recommended) — point any MCP host (Claude Desktop/Code, or
your own agent) at the
schd-mcpstdio server. See MCP. - Raw HTTP / OpenAPI — for agents that don't speak MCP, call
/api/v1directly from the served OpenAPI spec. See HTTP / OpenAPI. - Library / CLI — embed the typed client or script the
schdCLI.
Install
Requires Node >= 18. Install from npm — no clone or build step needed:
npm install -g schd-client # puts `schd` and `schd-mcp` on your PATHOr run on demand without installing: npx -y -p schd-client schd-mcp
(and npx -y -p schd-client schd for the CLI).
From source
npm install
npm run build # tsc -> lib/
npm testAuthentication
Everything runs on personal access tokens (pot_...):
- Email/password accounts:
schd login --email [email protected]logs in, mints a token namedcli@<hostname>, and stores it in~/.config/schd/config.json(0600). The login session itself is revoked immediately — only the token is kept. - Google accounts: create a token in the web app (Account panel →
API tokens), then
schd login --token pot_.... - Environment overrides:
SCHD_SERVER_URL,SCHD_TOKEN,SCHD_CONFIG_DIR.
Tokens can be scoped read-only (--read-only / the web checkbox).
CLI
Prompt for 3rd-party AI agents
Copy this entire prompt into an AI agent that can run terminal commands:
Install and use the PlanOnToday CLI (`schd`) to help me manage my schedule.
1. Check `node --version` and confirm Node.js 18 or newer is installed. If it
is missing or older, stop and tell me what must be installed or upgraded.
2. Run `npm install -g schd-client`, then verify the installation with
`schd --version`. If global installation is unavailable, use
`npx -y -p schd-client schd` for every CLI command instead.
3. Authenticate against the default production service,
`https://planfor.day`. Ask me whether I want to provide an existing
personal access token (`pot_...`) or complete the interactive
email/password flow. Use `schd login --token <token>` for an existing token
or `schd login --email <email>` for email/password authentication. Let me
enter secrets through the appropriate prompt when possible. Never repeat,
display, log, commit, or save my password or token outside the CLI's own
protected configuration. Do not invent credentials.
4. Run `schd whoami` and confirm that authentication succeeded before reading
or changing my schedule.
5. Use the CLI to fulfill my scheduling requests. Available operations include
`schd show`, `schd range`, `schd suggestions`, `schd add`, `schd edit`, `schd rm`, `schd mv`,
`schd day set`, and `schd day clear`. Use `--json` when structured output
will make your work safer or more reliable. Run `schd --help` or the
relevant command's `--help` before acting whenever you are uncertain about
syntax; do not guess flags or arguments.
Build ordinary plans by ordering items and assigning each a duration; each
item then starts after the previous one. Use a fixed start only when I say
an item cannot be rescheduled. Never convert a computed or preferred start
time into a fixed start automatically.
6. Ask for confirmation immediately before destructive actions such as
removing an item or clearing or replacing a day, and before broad changes
affecting multiple schedule entries. After each operation, report the
result concisely without exposing secrets.schd login [--server URL] [--email E | --token pot_...] [--read-only] [--register]
schd logout | schd whoami
schd show [today|tomorrow|yesterday|YYYY-MM-DD] [--json]
schd range <from> <to> [--json]
schd suggestions <time> [--date D] [--json]
schd add "Lunch" --duration 60 [--fixed-start 13:00] [--date D] [--before ID|--after ID|--start|--end]
schd edit <id> [--date D] [--title T] [--duration M] [--fixed-start 09:30|--make-flexible]
schd rm <id> [--date D]
schd mv <id> [--date D] [--before ID|--after ID|--start|--end|--to-date D2]
schd day set <date> [--file plan.json] [--day-start 09:00]
schd day start <date> <time>
schd day clear <date>
schd token create <name> [--read-only] | schd token list | schd token revoke <id>Dates default to today. In schd show output, * marks an immovable
fixed start and #123... is the item id used by
edit/rm/mv. token subcommands ask for email/password because a
token is deliberately not allowed to manage other tokens.
MCP
lib/mcp/index.js is a stdio MCP server exposing the schedule as
tools including get_context, get_day, get_days, add_item,
get_suggestions,
add_fixed_item, update_item, set_fixed_start, make_flexible,
set_day_start, remove_item, move_item, set_day, and clear_day. With a read-only
token only the get_* tools are registered.
Add it to any MCP host (Claude Desktop / Claude Code, or your own
agent). Pass the token via env — no schd login needed:
{
"mcpServers": {
"schd": {
"command": "npx",
"args": ["-y", "-p", "schd-client", "schd-mcp"],
"env": {
"SCHD_SERVER_URL": "https://planfor.day",
"SCHD_TOKEN": "pot_..."
}
}
}
}If you installed globally (npm install -g schd-client), use
"command": "schd-mcp" with no args. If instead you ran schd login,
the token in ~/.config/schd/config.json is picked up automatically and
the env block can be omitted.
The tool layer (src/mcp/tools.ts) is transport-agnostic — a future
remote (Streamable HTTP) endpoint on the server can reuse it unchanged.
HTTP / OpenAPI (for non-MCP agents)
If your agent can't run a stdio MCP server, call /api/v1 directly —
the same operations the MCP tools wrap, with no client install at all.
- Base URL:
https://planfor.day/api/v1 - Spec:
GET https://planfor.day/api/v1/openapi.json— a complete OpenAPI 3 document. Many agent frameworks can auto-generate tools from this URL. - Auth:
Authorization: Bearer pot_...on every request. Writes (POST/PUT/PATCH/DELETEwith a body) must also sendContent-Type: application/json(a deliberate CSRF guard — non-JSON bodies are rejected with415). No other headers or query params are required. There is currently no rate limiting.
Data model the agent should know:
- A day (
YYYY-MM-DD) has a wall-clockdayStartand an ordered list of items. Each item requires atitleanddurationin minutes (0–1440). - Ordinary items are sequential: their computed
startTimeis the end of the preceding item. Order and duration are the normal planning controls. fixedStart: "HH:MM"is exceptional and should be set only for a commitment that cannot be rescheduled. A preferred or approximate time is not fixed.- All public times are timezone-independent
"HH:MM"strings. GET /api/v1/suggestions?date=YYYY-MM-DD&time=HH:MMreturns historical titles ranked for that schedule position, with context-weighted duration and a relative relevance score.PUT /api/v1/days/:datewith{ "dayStart": "09:00", "items": [...] }replaces a whole day at once — the most reliable way to build a full plan (an empty list clears the day).
Quick check:
curl -s https://planfor.day/api/v1/openapi.json | head
curl -s -H "Authorization: Bearer pot_..." https://planfor.day/api/v1/meLibrary
import { createClient } from "schd-client";
const client = createClient({
serverUrl: `https://planfor.day`,
token: process.env.SCHD_TOKEN,
});
const day = await client.getDay(`2026-07-12`);Days expose dayStart; items expose computed startTime and nullable
fixedStart, all as "HH:MM". Normal items omit fixedStart and follow the
preceding item's duration.
