Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Deterministic whitespace/EOL/charset for the files rustfmt does NOT touch (YAML, TOML,
# Markdown). Keeps an agent's edits to ci.yml / Cargo.toml / docs from producing whitespace-only
# diffs that bury the real change. Honored by most editors + editor-integrated agents.
root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4

[*.rs]
max_line_length = 100

[*.{yml,yaml,toml}]
indent_size = 2

[*.md]
trim_trailing_whitespace = false
54 changes: 48 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ on:
env:
CARGO_TERM_COLOR: always

# Cancel a still-running CI for a branch when a newer commit is pushed. Deck's first
# git-gpui build is slow, so when an agent pushes a fix-up the stale run is killed and
# the runner starts on the latest commit immediately (faster feedback, fewer minutes).
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
macos:
runs-on: macos-latest
Expand All @@ -30,9 +37,18 @@ jobs:
# source of truth. rustup (preinstalled on GitHub runners) auto-installs the
# pinned version and its clippy/rustfmt components on the first cargo call.
- uses: Swatinem/rust-cache@v2
- run: cargo build
- run: cargo build --features tray
- run: cargo clippy --all-targets --features tray -- -D warnings
# --locked everywhere: reproducibility lives in the committed Cargo.lock (it
# pins exact git gpui commits). --locked fails CI on a stale lock; `just
# bump-gpui` rewrites+commits the lock, so this never fights the bump flow.
- run: cargo build --locked
- run: cargo build --locked --features tray
- run: cargo clippy --locked --all-targets --features tray -- -D warnings
# why: lint the DEFAULT/shipping feature config too — CI only ever linted
# the tray build, so a clippy regression on the default build slipped through.
- run: cargo clippy --locked --all-targets -- -D warnings
# why: run the test suite — the command_palette fuzzy-match tests existed but
# CI never executed them, so an agent could break scoring invisibly.
- run: cargo test --locked

linux:
runs-on: ubuntu-latest
Expand All @@ -55,6 +71,32 @@ jobs:
libfontconfig1-dev libfreetype6-dev \
libssl-dev \
libgtk-3-dev libayatana-appindicator3-dev libxdo-dev
- run: cargo build
- run: cargo build --features tray
- run: cargo clippy --all-targets --features tray -- -D warnings
# why: formatting is OS-independent, so gate `cargo fmt --check` ONCE on the
# cheaper Linux runner instead of the 10x-billed macOS one. Deck is already
# fmt-clean, so this lands green with no baseline-format commit.
- run: cargo fmt --all --check
# --locked everywhere: reproducibility lives in the committed Cargo.lock (it
# pins exact git gpui commits). --locked fails CI on a stale lock; `just
# bump-gpui` rewrites+commits the lock, so this never fights the bump flow.
- run: cargo build --locked
- run: cargo build --locked --features tray
- run: cargo clippy --locked --all-targets --features tray -- -D warnings
# why: lint the DEFAULT/shipping feature config too — CI only ever linted
# the tray build, so a clippy regression on the default build slipped through.
- run: cargo clippy --locked --all-targets -- -D warnings
# why: run the test suite — the command_palette fuzzy-match tests existed but
# CI never executed them, so an agent could break scoring invisibly.
- run: cargo test --locked

# why: supply-chain gate (advisories / bans / sources / licenses) via cargo-deny.
# deny.toml is already seeded and passes locally (`cargo deny check` is green). This lands
# NON-BLOCKING (continue-on-error) only so the first CI run can't surprise-break a PR — flip it
# to a required check (drop continue-on-error) after one green run on CI.
cargo-deny:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check advisories bans sources licenses
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rust-analyzer.check.command": "clippy",
"rust-analyzer.check.allTargets": true,
"rust-analyzer.checkOnSave": true
}
12 changes: 12 additions & 0 deletions .zed/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"lsp": {
"rust-analyzer": {
"initialization_options": {
"check": {
"command": "clippy",
"allTargets": true
}
}
}
}
}
74 changes: 74 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# AGENTS.md

Guidance for coding agents (Codex and others) working in Deck. Claude Code reads
the identical rules in `CLAUDE.md` — the two files are kept in lockstep. The
*why* behind every lint and gate lives in `docs/AGENTIC-ENGINEERING.md`.

## What Deck is

Deck is a native desktop-app **starter** built on GPUI + gpui-component in Rust
(macOS + Linux, rendered on Metal/wgpu). It is meant to be **forked, renamed,
and shipped** as your own app — there is no domain logic to preserve, just a
clean, working foundation.

It is a single crate (package `deck`, license `0BSD`, edition 2021). The git
GPUI stack is pinned in `Cargo.lock`; the toolchain is pinned in
`rust-toolchain.toml` to match Zed's gpui build — do not change either casually.

### `src/` layout

- `main.rs` — entry point; opens the window and wires up the app.
- `shell.rs` — the single root view; owns persisted `Settings` and routing.
- `command_palette.rs` — the ⌘K (Ctrl K) launcher, with fuzzy-match tests.
- `welcome.rs` — the Welcome page (a centered card).
- `settings.rs` — typed preferences persisted to the platform config dir.
- `settings_view.rs` — the Settings page rendered by `Shell`.
- `theme.rs` — dark/light palette with a selectable brand accent.
- `tray.rs` — optional menu-bar tray icon + dock hiding (`--features tray`).

## The loop (verify and self-correct without a CI round-trip)

- Type-check fast with `cargo check`. The full app build pulls GPUI from git, so
the **first** build is slow; it is cached after that. Run with `just run`
(`just run-tray` for the menu-bar variant).
- **`just ci`** runs the entire Definition of Done in one command (fmt-check +
clippy on both feature configs + tests) — the same gate as CI, so green here
means green there. Run it before declaring a change done.
- **`just fix`** auto-applies clippy's machine-fixable suggestions and formats.
Loop `just fix` → `just ci` to self-correct.
- For self-correction, prefer machine-readable diagnostics:
`cargo clippy --message-format=short` (one line each) or `--message-format=json`
(structured spans + applicable fixes). The default human format is for people.
- Editor == CI: `.vscode/` and `.zed/` set rust-analyzer to check with **clippy**,
so in-editor warnings match the CI lint set (rust-analyzer otherwise runs plain
`cargo check` and would miss the `[lints.clippy]` rules).

## Definition of Done

All four must hold before you call a change done — `just ci` checks them at once.
**Paste the command output as evidence; never claim done while anything is red.**

1. `cargo fmt --all --check` is clean.
2. clippy `-D warnings` is green on **both** the default build **and**
`--features tray` (`just check`).
3. `cargo test` is green (the `command_palette` fuzzy-match tests live here).
4. No new or changed deps in `Cargo.toml` / `Cargo.lock` unless explicitly
approved. The git GPUI stack is bumped **only** via `just bump-gpui` —
never hand-edit those pins.

## Code constraints

These mirror the manifest lints; internalize them before writing code:

- No `todo!()` and no `dbg!()` — both are denied.
- Never ignore a `Result` — `unused_must_use` is denied (a dropped fallible
IO/serde result is a silent bug). Propagate with `?` or handle it.
- `unsafe_code` is denied crate-wide. A genuinely necessary `unsafe` block needs
a reviewed `// SAFETY:` comment plus a scoped `#[allow(unsafe_code)]`.
- Deck is an app, so `.expect()` on genuinely-infallible GPUI handles is fine
(see `main.rs` and `tray.rs`). Prefer `Result`/`?` everywhere else.

## Design work

Ground UI changes in `README.md` and `docs/LEARNINGS.md` (real screenshots and
hard-won GPUI lessons) — not remembered descriptions of how things look.
74 changes: 74 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# CLAUDE.md

Guidance for Claude Code (and any agent reading this file) working in Deck.
Keep this in lockstep with `AGENTS.md` — they are the same rules. The *why*
behind every lint and gate lives in `docs/AGENTIC-ENGINEERING.md`.

## What Deck is

Deck is a native desktop-app **starter** built on GPUI + gpui-component in Rust
(macOS + Linux, rendered on Metal/wgpu). It is meant to be **forked, renamed,
and shipped** as your own app — there is no domain logic to preserve, just a
clean, working foundation.

It is a single crate (package `deck`, license `0BSD`, edition 2021). The git
GPUI stack is pinned in `Cargo.lock`; the toolchain is pinned in
`rust-toolchain.toml` to match Zed's gpui build — do not change either casually.

### `src/` layout

- `main.rs` — entry point; opens the window and wires up the app.
- `shell.rs` — the single root view; owns persisted `Settings` and routing.
- `command_palette.rs` — the ⌘K (Ctrl K) launcher, with fuzzy-match tests.
- `welcome.rs` — the Welcome page (a centered card).
- `settings.rs` — typed preferences persisted to the platform config dir.
- `settings_view.rs` — the Settings page rendered by `Shell`.
- `theme.rs` — dark/light palette with a selectable brand accent.
- `tray.rs` — optional menu-bar tray icon + dock hiding (`--features tray`).

## The loop (verify and self-correct without a CI round-trip)

- Type-check fast with `cargo check`. The full app build pulls GPUI from git, so
the **first** build is slow; it is cached after that. Run with `just run`
(`just run-tray` for the menu-bar variant).
- **`just ci`** runs the entire Definition of Done in one command (fmt-check +
clippy on both feature configs + tests) — the same gate as CI, so green here
means green there. Run it before declaring a change done.
- **`just fix`** auto-applies clippy's machine-fixable suggestions and formats.
Loop `just fix` → `just ci` to self-correct.
- For self-correction, prefer machine-readable diagnostics:
`cargo clippy --message-format=short` (one line each) or `--message-format=json`
(structured spans + applicable fixes). The default human format is for people.
- Editor == CI: `.vscode/` and `.zed/` set rust-analyzer to check with **clippy**,
so in-editor warnings match the CI lint set (rust-analyzer otherwise runs plain
`cargo check` and would miss the `[lints.clippy]` rules).

## Definition of Done

All four must hold before you call a change done — `just ci` checks them at once.
**Paste the command output as evidence; never claim done while anything is red.**

1. `cargo fmt --all --check` is clean.
2. clippy `-D warnings` is green on **both** the default build **and**
`--features tray` (`just check`).
3. `cargo test` is green (the `command_palette` fuzzy-match tests live here).
4. No new or changed deps in `Cargo.toml` / `Cargo.lock` unless explicitly
approved. The git GPUI stack is bumped **only** via `just bump-gpui` —
never hand-edit those pins.

## Code constraints

These mirror the manifest lints; internalize them before writing code:

- No `todo!()` and no `dbg!()` — both are denied.
- Never ignore a `Result` — `unused_must_use` is denied (a dropped fallible
IO/serde result is a silent bug). Propagate with `?` or handle it.
- `unsafe_code` is denied crate-wide. A genuinely necessary `unsafe` block needs
a reviewed `// SAFETY:` comment plus a scoped `#[allow(unsafe_code)]`.
- Deck is an app, so `.expect()` on genuinely-infallible GPUI handles is fine
(see `main.rs` and `tray.rs`). Prefer `Result`/`?` everywhere else.

## Design work

Ground UI changes in `README.md` and `docs/LEARNINGS.md` (real screenshots and
hard-won GPUI lessons) — not remembered descriptions of how things look.
20 changes: 20 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,26 @@ default-run = "deck"
name = "deck"
path = "src/main.rs"

# Lint policy lives in the manifest (not just CI flags) so rust-analyzer and `cargo check` surface
# the same rules CI enforces — zero feedback latency for an agent. Deck is a SINGLE crate (no
# [workspace]), so these go directly under the package as [lints.rust] / [lints.clippy] — NOT
# [workspace.lints] and NOT `[lints] workspace = true` (that indirection is only for multi-crate
# workspaces). Rationale + the deliberately-rejected lints: docs/AGENTIC-ENGINEERING.md.
[lints.rust]
unused_must_use = "deny" # an ignored Result from a fallible IO/serde call is a silent bug
# deny, NOT forbid: Deck has zero unsafe today; deny still compiles and leaves a reviewed escape
# hatch (// SAFETY: + scoped #[allow(unsafe_code)]) if a future objc2 bump needs raw unsafe in the
# tray path. forbid cannot be locally overridden, so it would brick that build with no way out.
unsafe_code = "deny"

[lints.clippy]
# priority = -1 is REQUIRED on a lint *group* so the individual lints below can still override it.
# warn here (not deny) + `-D warnings` in CI is the reth/alloy convention: a toolchain bump that
# adds new clippy lints then can't brick local `cargo build` — only CI goes red.
all = { level = "warn", priority = -1 }
todo = "deny" # a stray todo!() left on a code path panics in production
dbg_macro = "deny" # dbg! debug noise left behind by an agent

[dependencies]
# Fresh GPUI, straight from Zed's git — the DEFAULT channel (Metal on macOS, wgpu on
# Linux). `gpui-component` is developed against Zed's gpui HEAD, so the only way to pair
Expand Down
20 changes: 20 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# clippy knobs for Deck. why these (and why the wallet stuff is omitted): docs/AGENTIC-ENGINEERING.md

msrv = "1.95.0" # match rust-toolchain.toml

# Deck is an APP, and the command_palette tests unwrap/expect/panic freely — keep them legal.
allow-unwrap-in-tests = true
allow-expect-in-tests = true
allow-panic-in-tests = true

# doc-valid-idents: only matters once you turn on clippy::pedantic (doc_markdown). Deck enables
# only clippy::all, which does NOT include doc_markdown, so this key is unnecessary today.
# uncomment + add YOUR domain idents (proper nouns clippy would otherwise flag) if you go pedantic:
# doc-valid-idents = ["GPUI", "macOS", "WebGPU", ".."]

# disallowed-methods is the highest-signal clippy tool: a compile error WITH a printed reason.
# Deck has no footguns to ban out of the box (the wallet originals — mem::forget / thread_rng —
# are key-zeroize concerns, irrelevant here). ban your own once you find one:
# disallowed-methods = [
# { path = "std::env::set_var", reason = "mutates global env; pass config explicitly" },
# ]
Loading
Loading