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
69 changes: 69 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Bug report
description: Something in the Deck starter doesn't work as expected.
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for filing a bug. Deck is a starter — if the issue is in your
own app code after forking, this tracker probably can't help. For
security issues, do **not** file here; see SECURITY.md.
- type: textarea
id: what-happened
attributes:
label: What happened?
description: What did you expect, and what happened instead?
placeholder: A clear description of the bug.
validations:
required: true
- type: textarea
id: repro
attributes:
label: Steps to reproduce
description: Minimal steps. A small diff or snippet helps a lot.
placeholder: |
1. `cargo run --features overlay`
2. Click ...
3. See ...
validations:
required: true
- type: dropdown
id: os
attributes:
label: Operating system
options:
- macOS (Apple Silicon)
- macOS (Intel)
- Linux (X11)
- Linux (Wayland)
- Other (note in description)
validations:
required: true
- type: dropdown
id: features
attributes:
label: Feature flags
description: Which build were you running?
options:
- default
- tray
- overlay
- tray,overlay
validations:
required: true
- type: input
id: gpui-commit
attributes:
label: GPUI commit
description: The `gpui` commit from Cargo.lock (`grep -A2 'name = "gpui"' Cargo.lock`).
placeholder: "86effffd..."
validations:
required: false
- type: textarea
id: logs
attributes:
label: Logs / backtrace
description: Any terminal output or `RUST_BACKTRACE=1` trace.
render: shell
validations:
required: false
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/hellno/deck/security/advisories/new
about: Report security issues privately — do not open a public issue. See SECURITY.md.
- name: Question or idea
url: https://github.com/hellno/deck/discussions
about: For open-ended questions and "how do I fork this?" — use Discussions (if enabled).
35 changes: 35 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Feature request
description: Suggest an improvement to the Deck starter.
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Deck is kept deliberately small (~700 lines). The best additions make it
a better foundation for everyone who forks it — not your app's domain
logic. When in doubt, open this first before a PR.
- type: textarea
id: problem
attributes:
label: What problem does this solve?
description: The friction or gap you're hitting in the starter.
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed change
description: What you'd like to see. Keep "kept small" in mind.
validations:
required: true
- type: dropdown
id: scope
attributes:
label: Platform scope
options:
- Both macOS and Linux
- macOS only
- Linux only
- Docs / tooling only
validations:
required: false
26 changes: 26 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!-- Thanks for contributing to Deck! Keep PRs small and focused. -->

## What & why

<!-- One or two sentences: what does this change, and why? Link any issue. -->

## Definition of Done

<!-- Run `just ci` and paste the output (or confirm it's green). See CONTRIBUTING.md. -->

- [ ] `just ci` is green (fmt + clippy on default / `tray` / `overlay` / `tray,overlay` + tests).
- [ ] No new or changed dependencies in `Cargo.toml` / `Cargo.lock` (or maintainer approval is linked).
- [ ] GPUI pins changed only via `just bump-gpui` (not hand-edited), if applicable.
- [ ] Docs updated if behavior or setup changed (`README.md` / `docs/`).

## Platforms tested

<!-- The author daily-drives macOS; Linux is kept honest by CI. Tell us what you ran on. -->

- [ ] macOS
- [ ] Linux (note X11 / Wayland)
- Features exercised: <!-- default / tray / overlay / tray,overlay -->

## Notes for reviewers

<!-- Anything tricky, follow-ups, or screenshots/GIFs for UI changes. -->
25 changes: 25 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Dependabot configuration for Deck.
#
# NOTE: the GPUI stack (gpui / gpui_platform / gpui-component / gpui-component-assets)
# is pinned to exact GIT commits and is bumped ONLY via `just bump-gpui`. Dependabot's
# `cargo` ecosystem proposes updates for registry (crates.io) deps and the lockfile;
# it does NOT touch git dependencies, so those pins stay under `just bump-gpui` control.
version: 2
updates:
# crates.io dependencies (serde, serde_json, directories, tray-icon, objc2*, raw-window-handle).
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
commit-message:
prefix: "deps"

# GitHub Actions (keeps the SHA-pinned actions in ci.yml current).
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
commit-message:
prefix: "ci"
152 changes: 79 additions & 73 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
name: CI

# Builds the Deck on macOS *and* Linux so cross-platform stays honest.
# (GPUI renders with Metal on macOS and Vulkan via wgpu on Linux.)
# Deck is a cargo-generate TEMPLATE: its tracked source contains {{ }} Liquid tokens
# (see cargo-generate.toml `include`) and so does NOT build directly. Every job below
# therefore GENERATES a throwaway project from the template first, then builds / lints /
# tests THAT. Editing the template? Read the "cargo-generate template" note in CLAUDE.md.
#
# COST: free. Standard GitHub-hosted runners (macos-latest, ubuntu-latest) are
# free + unlimited on PUBLIC repos — the macOS 10x multiplier only burns quota
# on PRIVATE repos. If you ever make this repo private, gate the `macos` job to
# tags to avoid eating your minutes, e.g. add to that job:
# COST: free. Standard GitHub-hosted runners (macos-latest, ubuntu-latest) are free +
# unlimited on PUBLIC repos — the macOS 10x multiplier only burns quota on PRIVATE repos.
# If you ever make this repo private, gate the `macos` job to tags to avoid eating minutes:
# if: github.event_name == 'pull_request' || startsWith(github.ref, 'refs/tags/v')
# (Don't switch to "*-large" runners — those are billed even on public repos.)

Expand All @@ -21,9 +22,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).
# Least-privilege GITHUB_TOKEN: this workflow only checks out, generates, builds, lints,
# tests, and runs cargo-deny — it needs read access to repo contents and nothing else.
permissions:
contents: read

# Cancel a still-running CI for a branch when a newer commit is pushed (faster feedback,
# fewer minutes — the generated project's first git-gpui build is slow).
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
Expand All @@ -32,86 +37,87 @@ jobs:
macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
# No toolchain version here on purpose: rust-toolchain.toml is the single
# 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
# --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
# Overlay feature (macOS: real transparent PopUp window + objc2 panel harden).
- run: cargo build --locked --features overlay
- run: cargo clippy --locked --all-targets --features overlay -- -D warnings
- run: cargo clippy --locked --all-targets --features tray,overlay -- -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: the overlay unit tests (OverlayState/anchor math, JobStatus + HudState
# reducers) are gated behind --features overlay, so run them explicitly or they
# never execute. The reducers/anchor math are platform-independent — runs on Linux too.
- run: cargo test --locked --features overlay
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
# Prebuilt cargo-generate (fast, deterministic — no compile). SHA-pinned;
# Dependabot (github-actions) keeps it current.
- uses: taiki-e/install-action@7a79fe8c3a13344501c80d99cae481c1c9085912 # v2.81.10
with:
tool: cargo-generate
# Render the template into a sibling dir (NOT inside the repo — a nested cargo
# project confuses cargo, see rust-lang/cargo#9922). --silent uses the placeholder
# defaults (bundle_qualifier=com, bundle_org=example).
- name: Generate a project from the template
run: cargo generate --path . --name deck-ci --silent --vcs none --destination "$RUNNER_TEMP/gen"
# No toolchain pin here: rust-toolchain.toml (copied into the generated project) is
# the single source of truth; rustup auto-installs it on the first cargo call.
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
workspaces: ${{ runner.temp }}/gen/deck-ci
# No --locked: the generated Cargo.lock's root entry is renamed at generate time, so
# cargo refreshes just that on first build (the git-gpui deps stay pinned).
- name: Build, lint, and test the generated project
working-directory: ${{ runner.temp }}/gen/deck-ci
run: |
cargo build
cargo build --features tray
cargo clippy --all-targets -- -D warnings
cargo clippy --all-targets --features tray -- -D warnings
cargo clippy --all-targets --features overlay -- -D warnings
cargo clippy --all-targets --features tray,overlay -- -D warnings
cargo test
cargo test --features overlay

linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# No toolchain version here on purpose: rust-toolchain.toml is the single
# 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
# System libraries GPUI needs on Linux (X11 + Wayland + Vulkan + fonts),
# plus GTK/appindicator for the optional tray feature.
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
# System libraries GPUI needs on Linux (X11 + Wayland + Vulkan + fonts), plus
# GTK/appindicator for the optional tray feature.
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential pkg-config \
libxcb1-dev libxkbcommon-dev libxkbcommon-x11-dev \
libwayland-dev libxkbcommon-dev \
libwayland-dev \
libvulkan-dev \
libfontconfig1-dev libfreetype6-dev \
libssl-dev \
libgtk-3-dev libayatana-appindicator3-dev libxdo-dev
# 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
# Overlay feature (Linux: compile-only no-op path — no LayerShell in v1).
- run: cargo build --locked --features overlay
- run: cargo clippy --locked --all-targets --features overlay -- -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: the overlay unit tests (OverlayState/anchor math, JobStatus + HudState
# reducers) are gated behind --features overlay, so run them explicitly or they
# never execute. The reducers/anchor math are platform-independent — runs on Linux too.
- run: cargo test --locked --features overlay
- uses: taiki-e/install-action@7a79fe8c3a13344501c80d99cae481c1c9085912 # v2.81.10
with:
tool: cargo-generate
- name: Generate a project from the template
run: cargo generate --path . --name deck-ci --silent --vcs none --destination "$RUNNER_TEMP/gen"
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
workspaces: ${{ runner.temp }}/gen/deck-ci
# Formatting is OS-independent, so gate `cargo fmt --check` once on the cheaper
# Linux runner. The overlay feature is a compile-only no-op on Linux (no LayerShell).
- name: Format-check, build, lint, and test the generated project
working-directory: ${{ runner.temp }}/gen/deck-ci
run: |
cargo fmt --all --check
cargo build
cargo build --features tray
cargo clippy --all-targets -- -D warnings
cargo clippy --all-targets --features tray -- -D warnings
cargo clippy --all-targets --features overlay -- -D warnings
cargo test
cargo test --features overlay

# 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.
# Supply-chain gate (advisories / bans / sources / licenses) via cargo-deny, run against
# the GENERATED project (the raw template Cargo.toml has tokens and won't parse). REQUIRED:
# a deny.toml violation fails the build.
cargo-deny:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v2
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: taiki-e/install-action@7a79fe8c3a13344501c80d99cae481c1c9085912 # v2.81.10
with:
command: check advisories bans sources licenses
tool: cargo-generate,cargo-deny
- name: Generate a project from the template
run: cargo generate --path . --name deck-ci --silent --vcs none --destination "$RUNNER_TEMP/gen"
- name: cargo-deny check
working-directory: ${{ runner.temp }}/gen/deck-ci
run: cargo deny check advisories bans sources licenses
22 changes: 20 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,25 @@ GPUI stack is pinned in `Cargo.lock`; the toolchain is pinned in
- `theme.rs` — dark/light palette with a selectable brand accent.
- `tray.rs` — optional menu-bar tray icon + dock hiding (`--features tray`).

## This repo is a cargo-generate template — don't break it

Deck ships via `cargo generate gh:hellno/deck`. The files in `cargo-generate.toml`'s
`include` list (`Cargo.toml`, `Cargo.lock`, `src/main.rs`, `src/settings.rs`,
`src/overlay/mod.rs`, `scripts/make-app-icon.py`, `LICENSE`) hold `{{ }}` Liquid tokens,
so **the raw repo does not `cargo run` / `cargo build`** — render it first.

- Verify template changes with **`just check-template`** (renders a project, then clippy +
test). `just run` / `just ci` only work *inside a generated fork*.
- Renaming a new literal? Add its file to `include` **and** add the `{{ }}` token — a literal
in a non-included file ships as "deck" to every fork.
- **Never** put a literal `{{` or `{%` in an included file (Liquid will try to parse it).
- CI renders a throwaway project and builds THAT (`.github/workflows/ci.yml`).

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

> In this template repo, the commands below run inside a **generated** project (or via
> `just check-template`); the raw repo doesn't build. See the template note above.

- 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).
Expand All @@ -49,8 +66,9 @@ All four must hold before you call a change done — `just ci` checks them at on
**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`).
2. clippy `-D warnings` is green on **all** feature permutations — the default
build, `--features tray`, `--features overlay`, and `--features tray,overlay`
(`just check` runs all four).
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` —
Expand Down
Loading
Loading