English 한국어

scaffold-dayv0.3.1 · pre-release

Scaffold your day with AI.

A CLI-first, MCP-ready scheduler that places your TODOs into the free slots of your calendar — with AI clients (Claude Code, Cursor, Claude Desktop) as a first-class user. Same surface via CLI flags or MCP tools, so an LLM can plan your day with one tool call instead of piping CLI text.

Install

curl -fsSL https://day.scaffold.at/install.sh | sh

Tier 1: macOS Apple Silicon, Linux x64. v0.2 binaries are unsigned (Apple notarization is post-v0.2). The installer clears the macOS quarantine attribute for you.

Pin a specific version:

curl -fsSL https://day.scaffold.at/install.sh | sh -s -- --version v0.3.1

Update

Re-run the installer. It always resolves the latest release tag and replaces the binary in place. Existing data in ~/.scaffold-day/ (todos, events, policy, anchors) is preserved.

curl -fsSL https://day.scaffold.at/install.sh | sh
scaffold-day --version    # confirm the new version
scaffold-day doctor       # sanity check
Claude Desktop note: the MCP server respawns the binary on each session, but Claude Desktop caches the tool catalog. Fully quit (Cmd+Q on macOS) and reopen it after upgrading so new tools (e.g. record_morning) appear.

Quick start

$ scaffold-day init                  # ~/.scaffold-day + balanced policy
$ scaffold-day morning                # anchor today (relative time t=0)
$ scaffold-day todo add --title "Q2 OKR draft" --duration-min 60
$ scaffold-day place suggest <todo-id> --json
$ scaffold-day today --tz Asia/Seoul

Core concepts

scaffold-day separates intent from commitment. Three object types capture different stages:

TypeMeaningCreated by
todoWork to do; no time picked yettodo add
eventFixed time block (meeting, appointment) — won't moveevent add
placementA todo committed to a slot — moves with override or replanplace do

So todo add alone does not appear in today — it's a candidate. Use place suggest + place do to land it on a slot, and the day's view picks it up.

Morning anchor & the relative time modelv0.2

v0.2 introduces an anchor — the wall-clock instant a user "started today". It's the t=0 reference for three new policy fields, all opt-in. Without them, scaffold-day behaves exactly like v0.1.

Recording the anchor

$ scaffold-day morning                  # now → explicit
$ scaffold-day morning --at 07:30       # custom time → manual
$ scaffold-day morning --force          # override existing

AI clients should call the MCP record_morning tool whenever the user greets them in the morning. The first non-init command of each day also records an auto-source anchor as a fallback; an explicit call upgrades it silently.

Three layered policies (all optional)

FieldEffectDefault
sleep_budgetReject slots that push tonight's sleep below min_hours; soft penalty below target_hoursmin 6h, target 8h
cognitive_loadDecay heavy tasks (effort_min ≥ 60) past the capacity window after anchor4h window, linear -10/h
recovery_blockSoft penalty on next-day morning slots when yesterday had a forced-late event (≥ 2h past working hours)2h block, -30 penalty

Activate them

$ scaffold-day policy patch '[
  {"op":"add","path":"/context/sleep_budget","value":{"target_hours":8,"min_hours":6,"soft_penalty_per_hour":15}},
  {"op":"add","path":"/context/cognitive_load","value":{"decay":"linear","full_capacity_window_hours":4,"heavy_task_threshold_min":60,"linear_penalty_per_hour":10,"exponential_base":2}},
  {"op":"add","path":"/context/recovery_block","value":{"late_threshold_minutes_past_working_end":120,"morning_block_hours":2,"soft_penalty":30}}
]'

What you'll see in today

────────────────────────────────────────────── 2026-04-29 · Asia/Seoul ────────────────────────────────────────────── Day started 03:00 Rest break suggested · ~20 min (slept 4.0h last night) Free 09:00-12:00 [free 180m] 13:00-18:00 [free 300m] Summary: 0 events, 0 placements, 2 free slots, 0 open conflicts.

CLI command reference

Every command honors --help with a 6-section template (WHAT/WHEN/COST/INPUT/RETURN/GOTCHA). 22 commands total; 17 land real behavior in v0.2, 5 are placeholders for v0.2.x (Phase B).

CommandWhat it does
initSeed ~/.scaffold-day + balanced policy
todayToday's events / placements / free slots / anchor / rest hint
morningRecord today's anchor (or query / override)
dayMonths / overview / get / range / replan
week7-day overview
todoadd / list / get / update / archive / score
eventadd (update / delete are placeholder)
placesuggest / do / override
policyshow / patch / preset apply
conflictlist / resolve / detect
explainShow why a slot was chosen (replay)
authManage Google OAuth token (mock-mode in v0.2)
doctorHealth check (env / providers / adapters / anchor)
migrateSchema migration (preview default)
mcpRun the MCP server over stdio
docsSingle-shot AI-readable surface dump

Placeholders (print "implementation pending §S##"): feedback, self-update, telemetry, logs, rebuild-index. Real impls land in v0.2.x Phase B.

Global flags

Common recipes

# Add a TODO and place it on the best slot today
ID=$(scaffold-day todo add --title "OKR draft" --duration-min 60 --json | jq -r .id)
SLOT=$(scaffold-day place suggest $ID --json | jq -r '.candidates[0] | "\(.start)/\(.end)"')
scaffold-day place do $ID --slot $SLOT

# Move a placement to a different slot
scaffold-day place override <placement-id> --new-slot 2026-04-29T15:00:00+09:00

# Replan today (auto-shuffle unlocked placements)
scaffold-day day replan 2026-04-29 --json

# Explain why a placement landed where it did
scaffold-day explain <placement-id> --json

Use it from your AI client

scaffold-day mcp speaks the Model Context Protocol over stdio. v0.2 ships 27 tools covering day reads, todo CRUD, placement, policy, and anchors. Drop one of the snippets below into your client config, then fully restart the client.

~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "scaffold-day": {
      "command": "scaffold-day",
      "args": ["mcp"]
    }
  }
}

If scaffold-day is not on Claude Desktop's PATH, replace "scaffold-day" with the absolute path printed by which scaffold-day.

One command (writes / merges ~/.config/claude-code/mcp.json)

claude mcp add scaffold-day -- scaffold-day mcp

Cursor → Settings → MCP → Add

{
  "mcpServers": {
    "scaffold-day": {
      "command": "scaffold-day",
      "args": ["mcp"]
    }
  }
}

Tip: paste AGENTS.md into the system prompt

AGENTS.md carries JTBD recipes ("a meeting moved → replan", "add a TODO and place it") plus the full tool surface. One paste at session start saves the LLM from re-deriving call sequences. Token budget is small (~10k chars); well within any modern context.

v0.2 morning anchor flow via MCP

  1. User greets the AI ("Good morning!") → AI emits record_morning
  2. User asks "what's on my plate today?" → AI calls get_day
  3. User adds tasks ("OKR draft, 1 hour") → AI calls create_todo + compute_task_importance + suggest_placement + place_todo in sequence
  4. User asks "how am I doing?" → AI calls get_rest_suggestion for sleep-debt awareness

Policy reference

~/.scaffold-day/policy/current.yaml is the single source of truth for scheduling decisions. The YAML codec preserves comments, so hand-editing is safe.

Modify with JSON Patch (RFC 6902, comments preserved)

# Move lunch protection from 12:00-13:00 to 12:30-13:30
scaffold-day policy patch '[
  {"op":"replace","path":"/context/protected_ranges/0/start","value":"12:30"},
  {"op":"replace","path":"/context/protected_ranges/0/end","value":"13:30"}
]'

Or just edit the file

Comments survive. scaffold-day today picks up changes on the next call.

$EDITOR ~/.scaffold-day/policy/current.yaml

Field overview

PathMeaning
context.tzIANA timezone for all relative-time math
context.working_hours[]Per-weekday placement window (outside is blocked)
context.protected_ranges[]Always-blocked windows (sleep, lunch)
context.energy_peaks[]Soft hint for tag-aware preferences
context.sleep_budgetv0.2Hard reject + soft penalty on tonight's sleep
context.cognitive_loadv0.2Decay heavy tasks past capacity window
context.recovery_blockv0.2Soft block on tomorrow morning after late events
hard_rules[]Non-negotiable placement constraints
soft_preferences[]Tag/time-aware score nudges
importance_weightsHow urgency/impact/effort/etc combine into score

Test changes safelyv0.2

Every write command supports --dry-run. Disk is untouched; stdout shows what would have happened.

$ scaffold-day --dry-run todo add --title "test" --duration-min 30 --json
{
  "dry_run": true,
  "would": {
    "command": "todo add",
    "writes": [
      { "path": "todos/active/index.json", "op": "update" },
      { "path": "todos/active/detail/<new-id>.json", "op": "create" }
    ],
    "result": { "title": "test", "status": "open", ... }
  }
}

Read commands ignore the flag (no-op). MCP tools intentionally do not have a dry-run mode — the suggest_placement / compute_task_importance read tools already serve as the preview path before place_todo / create_todo.

Where your data lives

~/.scaffold-day/
├── .scaffold-day/schema-version.json   # migration tracking
├── .secrets/                            # 0700, OAuth tokens go here
├── policy/current.yaml                  # the single source of truth
├── policy-snapshots/                    # per-placement snapshot (replay)
├── todos/active/{index.json, detail/}   # 2-tier TODO storage
├── todos/archive/                       # archived todos
├── days/YYYY-MM/{manifest.json, *.json} # events + placements per day
├── sync/                                # Google Cal sync state (mock in v0.2)
├── conflicts/                           # conflict partitions
└── logs/
    ├── heartbeats.jsonl                 # morning anchor records (v0.2)
    ├── placement.jsonl                  # placement decisions (replay)
    └── conflict.jsonl                   # conflict actions

Override the location with SCAFFOLD_DAY_HOME=/path/to/dir.

Troubleshooting

SymptomFix
Claude Desktop doesn't show new MCP tools after upgrade Cmd+Q, then reopen. Tool catalog is fetched on session start.
scaffold-day --version still shows the old version Check which scaffold-day. The installer writes to ~/.local/bin if /usr/local/bin is not writable; older binaries on PATH may shadow it.
scaffold-day mcp errors out under bun-darwin-arm64 Known: bun stdin needs an explicit resume on macOS. v0.2 already wires this; if you see the issue, file an issue with doctor output.
Today's anchor is wrong Override with scaffold-day morning --at 07:30 --force. Future-you can also pass an ISO datetime if you need a specific instant.
Want to dogfood the relative time model risk-free Pair every command with --dry-run until happy. Or use a sandbox home: SCAFFOLD_DAY_HOME=$(mktemp -d) scaffold-day init.

Why

Most calendar tools optimise for displaying time. scaffold-day optimises for placing time: take a list of TODOs, score their importance, and slot them into the calendar's actual free space — under a transparent, replayable policy you can edit by hand.

v0.2's relative time model goes one step further: instead of pinning sleep to fixed clock times, you declare a budget, and the placement engine refuses to push you below it. Heavy tasks decay as the day stretches. Late nights surface a recovery block tomorrow. The math is deterministic and replayable; the policy is one YAML file.

AGPL-3.0-or-later · part of the scaffold.at products line ·