research

A Deadline Board for Mission Control (local board vs Linear sync)

Jul 14, 2026

Written 2026-07-06. Grounded in (a) Twitter power-user pain pulled live via agent-reach/OpenCLI, (b) the official Linear GraphQL + MCP docs, and (c) the actual state of this machine — where deadlines for slack-hackathon, rally, foreman, multihopper, aztec, etc. already live in ~/.claude/projects/-Users-thescoho/memory/MEMORY.md and per-project AGENT_STATE.md files, but nothing surfaces them.


TL;DR — the three answers

(a) Recommendation: BUILD THE LOCAL BOARD. Make Linear an optional one-way push, not the core. A native, local-first deadline board is the correct wedge for a ~/.claude command center. Linear sync is a nice export lane for the subset of users who already live in Linear — it should never be the thing the feature depends on. Ship "both," but in strict priority order: local board is v1 and must stand alone; Linear push is v1.5 and strictly additive.

(b) Linear feasibility: YES, one-way sync is fully feasible today; two-way is possible but not worth it for v1. Two clean paths exist — the GraphQL API ([api.linear.app/graphql,](https://api.linear.app/graphql`,) personal API key in an Authorization: header) and the **official Linear MCP server** ([mcp.linear.app/mcp,](https://mcp.linear.app/mcp`,) built by Linear + Cloudflare + Anthropic, OAuth 2.1). Both can create/update issues, projects, and comments; Linear Projects carry a native targetDate + lifecycle state, which maps 1:1 onto a hackathon-with-a-deadline. Pushing "last touched 2h ago · $14 spent · deadline in 3d" into a Linear project update or issue description is a handful of issueUpdate/projectUpdate mutations.

(c) Top 3 design implications: (1) The deadline source already exists — parse it from MEMORY.md + AGENT_STATE.md, don't make the user re-enter it; (2) the board's unique value is the JOIN of deadline (which the user knows) × activity/cost/staleness (which only ~/.claude knows) — that combination exists in no other tool; (3) treat Linear as a render target behind an adapter, so the board's data model is local and Linear is one optional exporter among possible others.


1. The pain — how deadline-driven builders track many projects (Twitter, cited)

The signal is consistent: solo/indie builders run too many parallel projects, lose track of which are stale, and scatter their hard deadlines across Devpost / DoraHacks / Superteam with no unified "what's due and what's rotting" view. AI made starting projects free, which made the tracking problem worse, not better.

1.1 The exact feature, already being hand-rolled by a peer

@anulagarwal (solo iOS/game dev) — 21 likes, 1 RT, tweet:

"I have too many projects i work on — I created this tracker for myself. If any project is WIP for more than 7 days, I will get an email... to track their hit rates, pending WIP projects (so they can move on fast), success projects and learnings. Like a leaderboard on who procrastinates the most and who has most open side projects."

This is the feature, validated by peers in-thread: @TerekhinIvan (indie, $3.5k/mo apps) replied "HMMM, need to do something like that probably!" and the author said he "might launch" it as a SaaS. Note what he tracks: staleness (WIP > N days), open-project count, hit rate — activity signals, not task lists. That is precisely the axis ~/.claude already measures and Linear does not.

1.2 "AI does not buy consistency" — the follow-through gap

@_alejandroao (HuggingFace DevRel) — tweet:

"side projects are as difficult as they've always been. AI does not buy consistency"

quote-tweeting @awesomekling (Andreas Kling / Ladybird, SerenityOS) on hobby projects piling up half-finished. The bottleneck moved from building to finishing the right one before its deadline — which is exactly the judgment a deadline board provides and a code assistant does not. @TulioSousapro frames the sprawl the same way: "opening side projects like side quests."

1.3 Deadline anxiety is live and topical

@annamacmillan — 14 likes, tweet:

"Deadline pressure hitting different 😅 With the Fable 5 window closing fast, everyone's in full 'vibe coding' mode, shipping fast, checking nothing twice."

The whole timeline this week is deadline energy (the Fable-5 metering cutover), and the hackathon world the user lives in is a firehose of hard cutoffs with no aggregation:

Each lives on a different platform (Devpost, DoraHacks, MLH, Reddit, Superteam). The builder holds all the dates in their head or a note. That is the gap.

1.4 "CLI for personal, MCP for team (with OAuth)" — the tradeoff, stated by the source

@ericzakariasson (Cursor) — 531 likes, tweet:

"cli for stuff the model already knows... mcp for most integrations. slack, notion, linear, twitter... cli for personal, mcp for team (with oauth)."

This is the single most load-bearing quote for the architecture decision below: a widely-shared mental model that personal/solo work stays local, and Linear (over MCP + OAuth) is the team lane. A one-person fleet is the "personal" case → local-first is the native fit, Linear is the escape hatch for when the work becomes team-shaped. @stretchcloud independently names "Linear for project management" as the canonical MCP integration and notes MCP "converts a previously click-heavy workflow into something an agent can drive."

Pain summary — what they wish existed: one screen that shows every in-flight project, flags the stale ones ("WIP > 7 days"), and counts down each hard deadline — without manual data entry, because the builder is already too busy shipping to maintain a second tracker.


2. Linear integration feasibility (GraphQL + official MCP, cited)

Verdict: one-way local → Linear sync is fully feasible today. Two independent, documented paths.

2.1 Path A — GraphQL API (best for a native macOS app doing background pushes)

  • Endpoint: [api.linear.app/graphql,](https://api.linear.app/graphql`,) introspectable, explorable via Apollo Studio. [Linear: Getting started]
  • Auth — personal API key (the right choice for a single-user local app): created in Settings → Account → Security & Access; sent as header Authorization: <API_KEY> (note: no Bearer prefix for personal keys). Keys are static, user-scoped, and do not expire — ideal for a background daemon. OAuth 2.0 (Authorization: Bearer <token>) exists but is for multi-user apps and adds a whole flow you don't need for one user. [Linear API & Webhooks]
  • Write mutations that matter:
    • issueCreatetitle, description, teamId, priority, stateId, projectId, cycleId, labels. Returns success + the issue.
    • issueUpdate(id, input) — change stateId (status), priority, description, etc. id accepts the UUID or the shorthand (BLA-123).
    • projectCreate / projectUpdate — Linear Projects natively carry targetDate, startDate, and a lifecycle state (planned / started / paused / completed / canceled). This is the money field: a hackathon = a Linear Project with a targetDate = its submission deadline, and the board pushes progress into the project's description / a project update.
    • Cycles = time-boxed sprints; issues can be added to a cycle (cycleId). A hackathon week maps to a cycle if you want burndown.
    • Gotcha worth encoding: "Changes made to an issue's properties in the first 3 minutes are considered part of issue creation and won't be added to the activity log" — so a create-then-set pattern won't spam the timeline. [Linear: Getting started]
  • Rate limits — a non-issue at this scale: API-key auth = ~1,500 req/hr (some tiers 5,000) + 3,000,000 complexity points/hr, single-query cap 10,000 points (properties 0.1 pt, objects 1 pt, connections × page size). A board syncing a dozen projects every few minutes is nowhere near this. [Linear: Rate limiting]
  • Webhooks (only needed for two-way): Linear emits change events for Issues, Projects, Project updates, Cycles, Labels, etc. — this is the hook you'd add later if you ever wanted Linear → local. [Linear API & Webhooks]

2.2 Path B — the official Linear MCP server (best if the agent, not the app, does the push)

  • Endpoint: [mcp.linear.app/mcp](https://mcp.linear.app/mcp`) (also /sse). Built and maintained by Linear, in partnership with Cloudflare and Anthropic — i.e. first-party, not a community bridge. [Linear: MCP server]
  • Auth: OAuth 2.1 with dynamic client registration (primary); also accepts an API key /token directly via Authorization: Bearer <token>. [Linear: MCP server]
  • Tools exposed: "finding, creating, and updating objects in Linear like issues, projects, and comments — with more functionality on the way." The Feb 2026 update added initiatives, milestones, and project updates; cycles are supported (view sprints, add issues to a cycle). Third- party catalogs (Speakeasy) enumerate ~31 tools on the server. [Linear: MCP server] · [Speakeasy catalog]
  • Why an app might still prefer Path A: the MCP server is designed to be driven by an LLM client (Claude Code, Cursor). A native Swift app doing deterministic background sync wants the GraphQL API directly (no model in the loop, no OAuth dance). Use MCP when you want a Claude session to push ("update my Linear from Mission Control's state"), use GraphQL when the app pushes on a timer.

2.3 One-way vs two-way — what's realistic

Direction Feasible? Mechanism Verdict for v1
Local → Linear (one-way) ✅ Yes, cleanly projectCreate/Update (targetDate + state) + issueUpdate (status), or MCP create/update tools Ship this. Idempotent: keep a local projectId map, upsert on each sync.
Linear → Local (read-back) ✅ Possible GraphQL polling or webhooks Skip for v1. Only matters if the user edits deadlines in Linear.
True two-way merge ⚠️ Possible, costly webhooks + conflict resolution + local write-back Don't. Conflict handling is a tar pit for a v1 side-feature.

Sync payload that makes sense: for each tracked project, upsert one Linear Project whose targetDate = the deadline and whose latest project update carries the live telemetry only ~/.claude knows: "last touched 2h ago · $14.20 spent · 6 sessions · deadline in 3d · status: WIP." That is a single projectUpdate (or MCP create_project_update) per project per sync — trivial.


3. The deadline SOURCE problem — and why it's already 80% solved here

Transcripts contain activity, cost, last-touch, sessions — never deadlines. So a deadline board needs a deadline source. Three candidate sources, in order of how little the user has to do:

  1. Parse what already exists (BEST — near-zero user effort). This machine already stores every deadline in structured-enough prose:
    • ~/.claude/projects/-Users-thescoho/memory/MEMORY.md — the Active Projects section literally reads: "Slack Agent Builder Challenge — deadline Jul 13 2026", "submission Jul 19, finale Jul 30" (rally), "Submit before Jul 17" (foreman), "gates Jul 12 / Aug 11 / Sep 10" (crypto), "deadline Jul 13 2026", etc.
    • Per-project AGENT_STATE.md / README.md (e.g. ~/Developer/rally/AGENT_STATE.md, this repo's own AGENT_STATE.md) hold the same dates. A lightweight extractor (regex + a cheap Opus/Sonnet pass for the fuzzy ones) turns "deadline Jul 13 2026" / "Submit before Jul 17" / "finale Jul 30" into structured {project, deadline, kind}. The board is pre-populated on first launch with zero data entry — a killer first-run experience.
  2. A tiny opt-in config the user maintains — a .claude/deadline.toml (or frontmatter block) per project: deadline = 2026-07-13, kind = "hackathon-submission", prize = "...". Authoritative, trivial to parse, but requires the user to write it. Use as the override/confirm layer on top of #1, not the primary source.
  3. In-app entry — a date picker in the board. Always needed as the manual fallback, but should be the exception, because a command center that makes you type in data you already wrote down feels broken.

Design consequence: the board's deadline pipeline is parse (MEMORY.md + AGENT_STATE.md) → confirm in-app → optional .toml override. The parse step is the differentiator; it's why this board can only be built well inside ~/.claude, and it's why a generic Linear board can't replicate it.


4. Local board vs Linear sync — the tradeoff, decided

Dimension Local ~/.claude board Linear sync
Deadline source Parses MEMORY.md/AGENT_STATE.md → auto-populated User must enter every project + date in Linear manually
Activity / cost / staleness Native — it's the one tool that has this Linear has none of it; you'd push it from here anyway
Setup cost Zero (reads files already on disk) Linear account + API key/OAuth + project scaffolding
Works offline / instant ❌ network + rate limits
Fits "one-person fleet" ✅ (the "personal/CLI" lane, per @ericzakariasson) ⚠️ Linear is the "team" lane; overkill solo
Leverage if user already uses Linear ✅ real value: unifies with day-job PM
Maintenance surface Local model only Auth refresh, schema drift, idempotency, conflict handling

Decision: local board is the product; Linear is a feature of the board. The board must be fully useful with Linear switched off — because its unique data (deadline × activity × cost × staleness) is generated here, and pushing it to Linear is a one-directional export. "Both" is correct, but only in the sense of local core + optional Linear exporter behind an adapter, never "a Linear client." If you build a Linear client, you've built a worse Linear; if you build the local board, you've built the only tool that knows a project is 3 days from its deadline and hasn't been touched in 5 days and has already burned $40.


5. Existing tools & the gap a ~/.claude-native board fills

  • Linear cycles / projects / initiatives — excellent for teams with defined work, and Projects even have targetDate. But: no concept of "last touched by an agent," no cost, no staleness; every project and date is entered by hand. Built for planned work, not for a solo operator's chaotic hackathon sprawl.
  • Git ↔ Linear bots (Linear's GitHub/GitLab integration, auto-linking ENG-123 in branches/PRs) — move issue status off commits/PRs. Useful, but keyed to issues and repos, and still needs the deadlines and projects to be set up in Linear first. No deadline countdown, no fleet view.
  • Deadline widgets / countdown apps / Notion dashboards — show dates, know nothing about your work. Pure manual entry; go stale immediately.
  • Devpost / DoraHacks / Superteam — each holds one platform's deadlines; the builder still aggregates across them by hand (see the listicle in §1.3).
  • @anulagarwal's hand-rolled WIP tracker — closest thing in spirit (staleness + open-project count + email nudges), but it's a bespoke one-off, not wired to where the work actually happens.

The gap (and the wedge): no tool joins the deadline (which the human knows) with the live work signal (which only ~/.claude knows). Mission Control is the only place both facts exist. A board that renders deadline − now next to last-touched, $ spent, session count, and a BLOCKED/STALE flag, auto-populated from files already on disk, is a feature that literally cannot be built anywhere else. It slots directly under Pillar 4 — ORCHESTRATE ("the fleet as one controllable thing: cross-session board") in VISION.md, and reuses Pillar-1 machinery (last-touch/isActive, cost math, the SessionIndex scan).


6. Design implications — the top 3 (plus the recommended shape)

1. Never make the user enter data you already have. The deadline source is parse-first (MEMORY.md + AGENT_STATE.md → structured deadlines), confirm-in-app second, .toml-override third. First launch should show the board already populated with slack-hackathon (Jul 13), rally (Jul 19 / 30), foreman (Jul 17), the crypto gates (Jul 12 / Aug 11 / Sep 10), etc., because those strings are already on disk. Auto-population is the whole first-run "wow."

2. The board's value is the JOIN, so lead with it visually. The unit of the board is not "a task" and not "a date" — it's a project card that fuses deadline + activity: ⏳ 3d left · 🕑 last touched 2h ago · 💸 $14.20 · 6 sessions · 🟡 WIP. Sort by urgency × staleness (closest deadline that hasn't been touched floats to the top — the "@anulagarwal WIP>7d" signal, but deadline-weighted). Reuse the existing last-touch/cost/isActive machinery from Pillar 1; do not rebuild a task manager.

3. Linear is a render target behind an adapter, not a dependency. Keep the canonical data model local. Define a thin DeadlineExporter protocol; ship a LinearExporter that does one-way upsert (map each project → a Linear Project with targetDate + a projectUpdate carrying the telemetry; personal API key in Authorization: header; keep a local {project → linearProjectId} map for idempotency). Gate it behind an opt-in toggle. This honors "cli/local for personal, Linear for team": the solo user gets the board with zero Linear; the user who also lives in Linear flips one switch and their fleet's deadlines appear alongside their day-job work. Prefer GraphQL (Path A) for the app's own background timer; offer MCP (Path B) only as the "let a Claude session sync it" path.

Recommended shape: a local-first Deadline Board (Pillar 4 surface) that auto-parses deadlines from files on disk, joins them with ~/.claude activity/cost/staleness, sorts by urgency×staleness, badges anything BLOCKED or STALE-near-deadline (with a menu-bar/dock countdown for the nearest one), and offers one optional toggle to push that state one-way into Linear projects. Local board is v1; Linear push is v1.5 and strictly additive.


Appendix — Sources

Twitter (agent-reach / OpenCLI, live 2026-07-06)

Linear API / MCP (official docs)

Local (this machine)

  • ~/.claude/projects/-Users-thescoho/memory/MEMORY.md — Active Projects section already encodes deadlines (slack Jul 13, rally Jul 19/30, foreman Jul 17, crypto gates Jul 12/Aug 11/Sep 10, …)
  • Per-project AGENT_STATE.md / README.md (e.g. ~/Developer/rally/AGENT_STATE.md, this repo's AGENT_STATE.md) — same deadlines, project-local
  • docs/VISION.md — Pillar 4 (ORCHESTRATE: "cross-session board") is where this feature lives; reuses Pillar 1 last-touch/cost/isActive machinery