Skip to content

spaceshipmike/setlist

Repository files navigation

Setlist

A personal project registry and intelligence hub. Setlist is the structured memory of every project, area of life, and tool I work on — usable from agents (via MCP), from the terminal (via a CLI), from any Node.js process (via a library import), and from a native macOS app.

This is built primarily for my own workflow, but the architecture is general. The repo is public so the auto-update path can reach the running app from GitHub Releases.

Public-readiness work is tracked in docs/public-readiness-plan.md: the current direction is a local, workspace-agnostic intelligence registry for agents across multiple MCP clients, with code and non-code projects both treated as first-class.

What it does

Setlist holds a small SQLite database (~/.local/share/project-registry/registry.db) and exposes it through four interfaces. The database tracks:

  • Project identity — every project I work on, with paths, tech stack, goals, status, and free-form descriptions agents can read
  • Canonical areas — every project lives under one of seven areas (Work, Family, Home, Health, Finance, Personal, Infrastructure), with optional parent-child sub-project relationships
  • Capability declarations — what an MCP server exposes, what CLI commands a tool offers, what a library exports — so other agents can discover what's available without reading source
  • Portfolio memory — typed observations across projects (insights, decisions, contradictions, procedural knowledge) with full-text search, belief classification, temporal validity, and area-scoped inheritance
  • Per-project essence digests — short generated summaries of each project, useful for embedding, semantic matching, or dropping into another agent's context
  • Local workspace inspection — shallow code and non-code folder signals, such as manifests, scripts, dependency groups, runtime hints, document categories, folder roles, and notable filenames
  • Port allocation — conflict-free local-port assignment for development services
  • Composite project health — qualitative tier (Healthy / At risk / Stale) per project, computed from activity, profile completeness, and outcome signals

The point: an agent working on any workspace can ask Setlist "what is this, what depends on it, what have we learned about it" and get a structured, queryable answer.

Portable project intelligence demo

Agents usually start cold. A new session lands in a folder, scans files, asks what matters, rediscovers conventions, and then loses that orientation when you switch from one agent client to another. Setlist's move is simple: register a workspace once, enrich the local registry over time, and make that project intelligence portable through the CLI, MCP, the library, and the desktop app.

The same brief is available from the terminal:

setlist brief calendar-bridge --json

For a narrower local source check, use:

setlist inspect calendar-bridge --json

Or from any MCP client with:

{ "tool": "get_project_brief", "arguments": { "name": "calendar-bridge" } }

Before Setlist, a fresh agent entering a code repo might know only this:

Current directory: /Users/demo/Workspaces/calendar-bridge
Need to inspect package files, README, open ports, prior decisions, and exposed commands before making a safe change.

After Setlist, the agent can ask for one brief. Abridged output:

{
  "project": {
    "name": "calendar-bridge",
    "display_name": "Calendar Bridge",
    "status": "active",
    "workspace_kind": "code",
    "paths": ["/Users/demo/Workspaces/calendar-bridge"]
  },
  "purpose": {
    "summary": "Syncs calendar events into a local planning dashboard.",
    "goals": ["Keep planning data local", "Expose a small MCP read surface"],
    "topics": ["calendar", "mcp", "local-first"]
  },
  "profile": {
    "tech_stack": ["TypeScript", "SQLite", "MCP"],
    "patterns": ["library-first", "plan-before-apply"]
  },
  "digest": {
    "digest_kind": "essence",
    "digest_text": "Calendar Bridge is a TypeScript service that normalizes calendar data into a local SQLite store and exposes read-only planning context through MCP.",
    "producer": "manual-demo",
    "generated_at": "2026-05-09T12:00:00.000Z",
    "stale": false
  },
  "capabilities": {
    "count": 2,
    "by_type": { "cli-command": 1, "tool": 1 },
    "highlights": [
      { "name": "calendar-bridge sync", "type": "cli-command", "description": "Run a bounded local sync." }
    ]
  },
  "operations": { "ports": [{ "port": 4382, "service_label": "dev", "protocol": "tcp" }] },
  "orientation_notes": [
    "Syncs calendar events into a local planning dashboard.",
    "Essence digest is available for agent orientation.",
    "Code workspace signals: TypeScript, SQLite, MCP."
  ],
  "enrichment_gaps": []
}

Setlist is not only for code. A research, household, client, or planning folder can be registered as a workspace without pretending it has a software stack:

setlist brief community-grant-archive --json

Before Setlist:

Current directory: /Users/demo/Workspaces/community-grant-archive
Need to infer purpose from filenames and ask which documents, deadlines, and decisions matter.

After Setlist. Abridged output:

{
  "project": {
    "name": "community-grant-archive",
    "display_name": "Community Grant Archive",
    "status": "active",
    "workspace_kind": "workspace",
    "paths": ["/Users/demo/Workspaces/community-grant-archive"]
  },
  "purpose": {
    "summary": "Tracks grant requirements, submitted materials, reviewer notes, and follow-up decisions.",
    "goals": ["Keep application history findable", "Preserve decision rationale across yearly cycles"],
    "topics": ["grants", "documents", "planning"]
  },
  "profile": {
    "short_description": "Grant document archive and decision log.",
    "medium_description": "A non-code workspace for grant materials, requirements, notes, and yearly follow-up planning.",
    "tech_stack": [],
    "patterns": []
  },
  "digest": null,
  "capabilities": { "count": 0, "by_type": {}, "highlights": [] },
  "operations": { "ports": [] },
  "orientation_notes": [
    "Grant document archive and decision log.",
    "No essence digest has been stored yet.",
    "Treat this as a general workspace unless code-specific fields are added."
  ],
  "enrichment_gaps": ["digest"]
}

That empty tech_stack is intentional. Non-code workspaces remain first-class; Setlist does not require code metadata just to orient an agent.

Local-first trust note: Setlist writes local registry data to ~/.local/share/project-registry/registry.db. The registry, brief, and inspect commands do not upload workspace contents. Local inspection uses shallow folder structure and small known metadata files, redacts credential-looking manifest and remote values, and keeps findings as read-time context; any external digest generator is an explicit separate action.

MCP client setup demo

Setlist can install its MCP server entry into supported local clients, but the flow is deliberately staged: detect the real client, preview the exact config change, then install only after review. Config-file presence alone is not detection; Setlist looks for real client artifacts such as the Claude Desktop app bundle, the Codex app bundle, or a codex binary on PATH.

Example output below is synthetic, shortened, and shaped like the current CLI output.

First, detect supported clients:

$ setlist mcp-clients detect
Claude Desktop: detected
  Config: /Users/demo/Library/Application Support/Claude/claude_desktop_config.json
  Found by: app: /Applications/Claude.app
Codex: detected
  Config: /Users/demo/.codex/config.toml
  Found by: binary: codex

Then preview the install plan. This is a dry run; no files are changed:

$ setlist mcp-clients plan --client all
Dry run only. No files were changed.

Claude Desktop: would-add-server
  Config: /Users/demo/Library/Application Support/Claude/claude_desktop_config.json
  - Claude Desktop: would back up config before writing.
  - Claude Desktop: would add managed 'setlist' MCP server.
  - Claude Desktop: would preserve unmanaged 'filesystem'.
  Backup before install: /Users/demo/Library/Application Support/Claude/claude_desktop_config.json.setlist-backup
  Recovery guidance:
  - Claude Desktop config would be written. A backup will be created first. 1 unmanaged server(s) will be preserved.
  - Config file: /Users/demo/Library/Application Support/Claude/claude_desktop_config.json
  - Backup before write: /Users/demo/Library/Application Support/Claude/claude_desktop_config.json.setlist-backup
  - Unmanaged entries preserved: filesystem
  - If installed, Setlist will create a backup at /Users/demo/Library/Application Support/Claude/claude_desktop_config.json.setlist-backup before writing /Users/demo/Library/Application Support/Claude/claude_desktop_config.json.
  - Unmanaged MCP servers preserved in place: filesystem.
  - Setlist will not delete MCP client config files automatically. Setlist will not overwrite, adopt, or remove unmanaged MCP server entries automatically. Setlist will not restore backups automatically; backup restoration stays a manual recovery step.

Codex: conflict-unmanaged-server
  Config: /Users/demo/.codex/config.toml
  - Codex: leave existing unmanaged 'setlist' MCP server untouched.
  Recovery guidance:
  - Codex was not changed because an unmanaged 'setlist' MCP server already exists.
  - Config file: /Users/demo/.codex/config.toml
  - Backup: not required for this state
  - Unmanaged entries preserved: github, setlist
  - Review the existing unmanaged 'setlist' MCP server in /Users/demo/.codex/config.toml; rename or remove it manually before asking Setlist to install its managed entry.
  - Unmanaged MCP servers preserved in place: github, setlist.
  - Setlist will not delete MCP client config files automatically. Setlist will not overwrite, adopt, or remove unmanaged MCP server entries automatically. Setlist will not restore backups automatically; backup restoration stays a manual recovery step.

Only after the plan looks right, apply one client at a time:

$ setlist mcp-clients install --client claude-desktop --yes
Claude Desktop: detected, backed_up, written
  Config: /Users/demo/Library/Application Support/Claude/claude_desktop_config.json
  - Claude Desktop: backed up config to /Users/demo/Library/Application Support/Claude/claude_desktop_config.json.setlist-backup-20260509T160000Z.
  - Claude Desktop: wrote managed 'setlist' MCP server.
  Backup: /Users/demo/Library/Application Support/Claude/claude_desktop_config.json.setlist-backup-20260509T160000Z
  Recovery guidance:
  - Claude Desktop config was written. A backup was created first.
  - Config file: /Users/demo/Library/Application Support/Claude/claude_desktop_config.json
  - Backup created: /Users/demo/Library/Application Support/Claude/claude_desktop_config.json.setlist-backup-20260509T160000Z
  - Unmanaged entries preserved: filesystem
  - To roll back, quit Claude Desktop, replace /Users/demo/Library/Application Support/Claude/claude_desktop_config.json with /Users/demo/Library/Application Support/Claude/claude_desktop_config.json.setlist-backup-20260509T160000Z, then reopen the client.
  - Unmanaged MCP servers preserved in place: filesystem.
  - Setlist will not delete MCP client config files automatically. Setlist will not overwrite, adopt, or remove unmanaged MCP server entries automatically. Setlist will not restore backups automatically; backup restoration stays a manual recovery step.

Setlist writes only its managed setlist entry. Existing configs are backed up before writes, unmanaged MCP servers are preserved, and unmanaged setlist conflicts are refused instead of adopted. Backup restoration stays manual: quit the client, restore the backup, then reopen the client. Setlist does not install Claude Desktop or Codex, restart those apps, validate that @setlist/mcp launches inside them, delete config files, or clean up unmanaged entries.

To uninstall Setlist from a supported client, use the guarded remove flow. Without --yes, it previews the exact managed entry removal and names the backup path:

setlist mcp-clients remove --client claude-desktop
setlist mcp-clients remove --client claude-desktop --yes

Remove deletes only a Setlist-managed setlist entry, preserves unrelated MCP servers, backs up an existing config before writing, and refuses unmanaged setlist entries.

See docs/mcp-client-compatibility.md for the current Claude Desktop and Codex compatibility matrix, including detection signals, config paths, install behavior, backup behavior, conflicts, recovery guidance, and known limits.

How to use it

Desktop first run

Open the signed macOS app, then register an existing local folder. Setlist asks what kind of project or workspace it is, previews shallow local metadata from that folder, and keeps non-code workspaces first-class. The preview is local on your Mac; it does not upload contents, call an LLM, or index deeply.

From Settings, you can preview installing or removing the managed Setlist MCP entry for Claude Desktop or Codex. Setlist shows the config change first, preserves unmanaged MCP entries, refuses unmanaged setlist conflicts, and backs up existing config files before writing. Restore is manual from that backup; Setlist does not restart clients or verify the MCP server inside them.

After registration, ask an agent for the Setlist project brief with the MCP get_project_brief tool, or use setlist brief <workspace> --json from the CLI.

Download the desktop app from Releases.dmg for macOS Apple Silicon. Signed, notarized, with in-app auto-update over a stable channel.

As an MCP server, point Claude Desktop or Codex at @setlist/mcp. The CLI can check supported clients and preview the managed Setlist entry before writing:

setlist mcp-clients detect
setlist mcp-clients plan --client all
setlist mcp-clients install --client claude-desktop --yes
setlist mcp-clients remove --client claude-desktop

Run the plan command before install. Run remove without --yes before uninstall. Install and remove both preserve unmanaged MCP servers, refuse unmanaged setlist conflicts, and create a timestamped backup before writing an existing config.

See the setup demo above and docs/mcp-client-compatibility.md for the current Claude Desktop and Codex compatibility matrix, including detection signals, config paths, install behavior, backup behavior, conflict handling, recovery guidance, and known limits.

As a Node.js library, npm install @setlist/core and import directly — Chorus, Ensemble, and other tools in my ecosystem use this path rather than going through the MCP protocol.

As a CLI, setlist exposes registry maintenance, migration, digest refresh, bootstrap, recipe, primitive, worker, MCP-client install/remove commands, and setlist brief <project> [--json] from the terminal. Run a command without the required arguments to see its usage.

How it's built

Four npm workspace packages:

packages/
├── core/    @setlist/core  — library: SQLite + all registry logic
├── mcp/     @setlist/mcp   — MCP server (stdio transport)
├── cli/     @setlist/cli   — CLI commands + async worker
└── app/     @setlist/app   — Electron desktop control panel

Stack: TypeScript, better-sqlite3 (synchronous native bindings), the official @modelcontextprotocol/sdk, Electron 35 + React 19 + Tailwind CSS 4 + Radix UI for the desktop app. ESM-only, no CJS. The SQLite schema is migration-backed, uses WAL mode, and includes FTS5 for memory search.

Architecture decisions worth knowing:

  • @setlist/core is the primary interface; MCP, CLI, and the desktop app are thin wrappers over it. The Electron main process imports @setlist/core directly via an IPC bridge — no API server sits between the UI and the database.
  • The desktop app and the MCP server need different native ABIs for better-sqlite3 (Electron's Node vs. standalone Node). A wrapper script swaps binaries between dev/build/start steps and a session-start hook checks ABI integrity.
  • The desktop app shares a design system (chorus-ui) with another personal app (Chorus) — same surfaces, accents, typography, status colors. The information architecture is Setlist's own.

Spec-driven, not test-driven. Setlist is built using a personal workflow I call fctry (factory). The complete behavioral contract is described in plain English in .fctry/spec.md (NLSpec v2 format) and validated by 118 end-to-end scenarios in .fctry/scenarios.md. The scenarios are evaluated by an LLM-as-judge — they're the holdout set, not test fixtures shown to the coding agent during builds. Vitest runs alongside as a fast local canary, but it's not the truth signal.

What this means in practice:

  • I describe behavior in user-facing language; the coding agent picks the implementation
  • Every change starts with a spec evolution, then code follows
  • Pull requests don't pass because tests pass — they pass because the relevant scenarios still satisfy under LLM evaluation

The full contract: .fctry/spec.md (describing every surface, dimension, and invariant) and .fctry/scenarios.md (the end-to-end scenario set).

Develop

git clone https://github.com/spaceshipmike/setlist.git
cd setlist
npm install
npm run typecheck
npm test
npm run build       # builds core → cli → mcp (dependency order)

For the desktop app:

cd packages/app
npm run dev         # electron-vite live reload
npm run build       # production build
npm start           # launch the built app

Release

Tagging vX.Y.Z triggers the GitHub Actions workflow in .github/workflows/release.yml. It signs with a Developer ID certificate, notarizes via Apple's notary service, staples the ticket, and publishes a GitHub Release containing the .dmg + .zip + latest-mac.yml update metadata. The running app's electron-updater reads latest-mac.yml to detect updates.

See packages/app/README.md for credential setup and signing details.

Status

External version 0.6.0, spec version 0.29. The project is actively developed against my own usage; APIs and schema may shift between minor versions until 1.0.

License

No formal license yet — this is personal infrastructure published openly. If you want to use any of the code beyond reading it, open an issue and we'll figure something out.

About

Project registry + intelligence + bootstrap

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors