https://github.com/francopocatino/decks
Notes organized by context for macOS — a SwiftUI app and Rust CLI
https://github.com/francopocatino/decks
cli macos notes productivity rust swift swiftui
Last synced: 5 days ago
JSON representation
Notes organized by context for macOS — a SwiftUI app and Rust CLI
- Host: GitHub
- URL: https://github.com/francopocatino/decks
- Owner: francopocatino
- License: mit
- Created: 2026-06-08T19:36:58.000Z (27 days ago)
- Default Branch: main
- Last Pushed: 2026-06-08T21:18:04.000Z (27 days ago)
- Last Synced: 2026-06-08T21:22:54.216Z (27 days ago)
- Topics: cli, macos, notes, productivity, rust, swift, swiftui
- Language: Swift
- Size: 325 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Decks
Notes for macOS, organized by context — built so the things you switch between never bleed into each other, with deep Claude integration.
Each project or context you switch between is a *deck*. A deck holds four sections:
- **Daily** — a dated log for standups and things to bring up.
- **To-dos** — what to do or review, with a checkbox.
- **Notes** — a free markdown scratchpad: decisions, people, context.
- **Links** — quick access to repos, dashboards and docs.
Open the app, pick the deck, and you are back where you left off — instead of digging through one giant notes file. Daily and Notes render markdown with an edit/preview toggle.
## Install
```
git clone https://github.com/francopocatino/decks
cd decks
./scripts/install.sh # builds Decks.app and installs it to /Applications
```
That builds a native `Decks.app`, installs it, and launches it. Right-click the Dock icon and choose Options > Keep in Dock. To run from source instead: `swift run --package-path app`.
## What it does
- Native macOS app (SwiftUI), no Electron.
- One deck per project or context, with rename / archive / delete, drag-to-reorder, and a sidebar that shows open to-do counts.
- Sub-decks: nest projects under a parent (one level). A sub-deck inherits the parent's connector, commit email, git provider and instructions when its own are empty, and sees the parent's links — to-dos and dailies stay per sub-deck.
- Split the deck into panes (two columns, or a stacked pair beside a third) so you can keep, say, the daily and notes side by side with your to-dos.
- Live sync: edits from the CLI or an agent show up in the open app within a second or two.
- Per-deck identity: git provider and commit email, project folders, which connector the deck uses, and AI instructions (language, daily format, tone). Secrets live in the macOS Keychain.
- Connectors: Claude or OpenAI power Ask; GitHub/GitLab tokens for the worklog. Configured in Settings, separated into AI and Git, secrets in the Keychain.
- Ask this deck: an in-app chat scoped to one deck, with persistent memory.
- A Rust CLI and an MCP server so Claude can read and write your decks.
- Worklog: turn a day's git commits into a daily entry.
- In-app update check; releases published on `v*` tags.
## Claude integration (MCP)
`decks-mcp` is an MCP server that exposes every deck operation as a tool, addressed by deck id. Register one global server:
```
cargo install --path cli # puts decks + decks-mcp on PATH
claude mcp add decks -- ~/.cargo/bin/decks-mcp
```
Then ask Claude — in Claude Code or Claude Desktop — to operate any deck by name:
- "add a to-do to acme: review the deploy"
- "fill the daily of nexus with what we did this session"
- "archive invicto"
`decks mcp-config` prints the ready-to-paste config. To keep an account isolated, register a server **scoped** to one deck in that account's client only: `decks-mcp --deck ` — it can never see another deck. The account boundary is which client/login you register the server in.
## Ask this deck (in-app AI)
Each deck has an Ask panel (the sparkles button) — a chat scoped to that deck. It answers only from that deck's own to-dos, daily, notes and links, keeps a persistent history, and uses that deck's connector. A deck's chat never sees another deck's content or connector. In-app chat needs an API-key connector — Claude or OpenAI (set in Settings, Cmd+,); Claude login-mode decks use Claude Code through the MCP server instead.
Each deck also carries free-form AI instructions (in deck settings) — language, daily format, tone. Ask prepends them to its system prompt, and Claude reads them from `show_deck` over the MCP server, so a daily drafted in one deck comes out in English bullets while another comes out in Spanish prose, per deck.
## CLI
The CLI reads and writes the same files as the app, and is the surface meant for automation.
```
cd cli
cargo run -- list # decks with open to-do counts
cargo run -- new "Acme" # create a deck
cargo run -- add acme "review PR 214" # add a to-do
cargo run -- done acme 0 # toggle a to-do
cargo run -- note acme "use sqlite" # append a note
cargo run -- daily acme "shipped auth" # add a dated daily entry
cargo run -- show acme --json # machine-readable output
```
Also: `link`/`unlink`, `remove`/`edit` (to-do), `reorder`/`set-parent`/`rename`/`archive`/`unarchive`/`delete` (deck), `worklog`, `which`. Every action is exposed as an MCP tool too.
## Worklog
`decks worklog ` scans the deck's folders for git repositories, collects today's commits filtered to the deck's commit email, and prepends them to the daily log. A repo whose `origin` remote doesn't match the deck's git provider is skipped, so one context's commits never land in another's worklog. If the deck points at a GitHub or GitLab connector, it also adds today's pull/merge requests you authored — the token is read from the macOS Keychain. `decks which ` resolves a path to the deck whose folder contains it — together they make a Claude Code SessionEnd hook so each coding session captures itself into the right deck. Install it with:
```
decks hook install # adds the SessionEnd hook to ~/.claude/settings.json (decks hook uninstall removes it)
```
It runs `deck=$(decks which "$CLAUDE_PROJECT_DIR"); [ -n "$deck" ] && decks worklog "$deck"` — a no-op in projects that don't belong to a deck.
## How it stores data
Everything is plain files under `~/.decks` (override with `DECKS_DIR`): JSON for structured data, markdown for free text. The on-disk format is the only contract between the app and the CLI — see [docs/format.md](docs/format.md).
## Automation
Shortcuts (including Focus automations) and SSH from the iPhone or Watch can drive Decks through the CLI — recipes in [docs/automation.md](docs/automation.md).
## Development
```
swift build --package-path app # app
cargo build --manifest-path cli/Cargo.toml # cli + mcp
cargo test --manifest-path cli/Cargo.toml
cargo fmt --manifest-path cli/Cargo.toml --check
cargo clippy --manifest-path cli/Cargo.toml --all-targets -- -D warnings
```
CI runs all of the above on every pull request. Changes go through a branch and a pull request; commits are atomic; English only.
## License
MIT — see [LICENSE](LICENSE).