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
19 changes: 10 additions & 9 deletions .agent/context/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ status: current
version: 0.1.0
last_updated: 2026-05-24
last_verified: 2026-05-24
source_refs: ["crates/aura/src/cli/", "docs/cli.md"]
source_refs: ["crates/aura-cli/src/", "docs/cli.md"]
owner: "@rfluid"
tags: [context, cli, conventions]
---
Expand All @@ -22,7 +22,7 @@ under `aura <noun> <verb>` that prints a result or mutates state is
enough. Read commands should accept `--format text|json` from day one
so the feature works in `jq`/status-bar pipelines without scraping.

Concrete examples already in tree (`crates/aura/src/cli/`):
Concrete examples already in tree (`crates/aura-cli/src/`):

| Module | Pattern it demonstrates |
| ------------ | ----------------------------------------------------------------------- |
Expand All @@ -47,22 +47,23 @@ Concrete examples already in tree (`crates/aura/src/cli/`):
name = "setup-config")]` on a top-level variant that calls the
canonical handler. Installer scripts and old muscle memory keep
working; help output stays clean.
4. **Profile resolution goes through `cli::resolve::resolve_profile`.**
4. **Profile resolution goes through `crate::resolve::resolve_profile`.**
`--profile` flag → `state.active_profile` → first agent in config.
Don't reinvent this — `usage`, `quota`, and `plugin run` all use it.
5. **Tray dispatch lives in `main.rs`.** The CLI is the entry point;
`main.rs` only falls through to the tray when `cli.command` is
`None`. Headless subcommands must never spin up GPUI.
5. **Tray dispatch lives in `crates/aura/src/main.rs`.** The CLI is the
entry point; `main` only falls through to `aura_ui::run` when
`cli.command` is `None`. Headless subcommands must never spin up GPUI —
`aura-cli` has no UI deps, so keep it that way.

## Adding a new subcommand

1. Create `crates/aura/src/cli/<noun>.rs` with a `<Noun>Cli` struct
1. Create `crates/aura-cli/src/<noun>.rs` with a `<Noun>Cli` struct
(`#[derive(Args)]`) and a `run(self) -> Result<()>` method.
2. Wire it into `cli/mod.rs`: `mod <noun>;` plus a `Command::<Noun>`
variant.
3. If the subcommand reads data: take `--format` and route through
`cli::format::print_json` for the JSON arm.
4. If it shells out to an editor: use `cli::theme::open_in_editor`.
`crate::format::print_json` for the JSON arm.
4. If it shells out to an editor: use `crate::theme::open_in_editor`.
5. Update `docs/cli.md` and the README CLI section.
6. Add tests if the logic is non-trivial. Pure formatters can be tested
inline in the module.
Expand Down
2 changes: 1 addition & 1 deletion .agent/context/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ status: current
version: 0.1.1
last_updated: 2026-05-24
last_verified: 2026-05-24
source_refs: ["crates/aura/src/cli/"]
source_refs: ["crates/aura-cli/src/"]
owner: "@rfluid"
tags: [context]
---
Expand Down
10 changes: 5 additions & 5 deletions .agent/skills/add-or-change-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ source_refs:
- crates/aura-core/src/config.rs
- crates/aura-core/src/config_migrate.rs
- crates/aura-core/src/config_schema.rs
- crates/aura/src/runtime.rs
- crates/aura/src/cli/config.rs
- crates/aura-ui/src/runtime.rs
- crates/aura-cli/src/config.rs
- docs/configuration.md
owner: "@rfluid"
tags: [skill, config, cli]
Expand All @@ -35,9 +35,9 @@ that's by design, not an obstacle. Work *with* it.
| Typed struct | `crates/aura-core/src/config.rs` | always (the field itself) |
| Field registry | `crates/aura-core/src/config_schema.rs` | always (describe + get/set) |
| Migration registry | `crates/aura-core/src/config_migrate.rs` | you move, rename, or remove an existing key |
| Runtime mirror | `crates/aura/src/runtime.rs` | the field must reach the tray loop *and* modal |
| Consumer | `crates/aura/src/app.rs`, `main.rs`, … | the field actually does something |
| CLI handler | `crates/aura/src/cli/config.rs` | almost never — it's registry-driven |
| Runtime mirror | `crates/aura-ui/src/runtime.rs` | the field must reach the tray loop *and* modal |
| Consumer | `crates/aura-ui/src/app.rs`, `main.rs`, … | the field actually does something |
| CLI handler | `crates/aura-cli/src/config.rs` | almost never — it's registry-driven |
| Docs | `docs/configuration.md`, `docs/cli.md`, `README.md` | always |

The CLI (`describe` / `get` / `set` / `wizard` / `init` / `document`) and the
Expand Down
6 changes: 3 additions & 3 deletions .agent/skills/diagnose-and-publish-issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ before composing a public issue.
| Report area | Sources to check |
| --- | --- |
| Install/update/uninstall | `README.md` installation/update sections, `install.sh`, `uninstall.sh`, `scripts/install.ps1`, `scripts/uninstall.ps1`, `justfile` |
| Tray icon/click behavior | `README.md` "Making the tray icon always visible" and "Compatibility", `docs/platform-tray-icon.md`, `crates/aura/src/tray.rs`, `crates/aura/src/tray_status.rs`, `crates/aura/src/main.rs` |
| Modal placement/resize/focus | `README.md` "Modal placement on Wayland", `docs/configuration.md` modal/backend sections, `docs/platform-tray-icon.md`, `docs/troubleshooting/modal-stretches-on-resize-kde.md`, `crates/aura/src/app.rs`, `crates/aura/src/placement.rs`, `crates/aura/src/platform.rs` |
| Tray icon/click behavior | `README.md` "Making the tray icon always visible" and "Compatibility", `docs/platform-tray-icon.md`, `crates/aura-ui/src/tray.rs`, `crates/aura-ui/src/tray_status.rs`, `crates/aura-ui/src/lib.rs` |
| Modal placement/resize/focus | `README.md` "Modal placement on Wayland", `docs/configuration.md` modal/backend sections, `docs/platform-tray-icon.md`, `docs/troubleshooting/modal-stretches-on-resize-kde.md`, `crates/aura-ui/src/app.rs`, `crates/aura-ui/src/placement.rs`, `crates/aura-ui/src/platform.rs` |
| Config/theme/state | `docs/configuration.md`, `docs/cli.md`, `crates/aura-core/src/config*.rs`, `crates/aura-core/src/state.rs`, `.agent/skills/add-or-change-config.md` |
| Usage/quota/agent data | `README.md`, `docs/cli.md`, `.agent/context/stack.md`, relevant `crates/aura-core` and `crates/aura/src/cli` sources |
| Usage/quota/agent data | `README.md`, `docs/cli.md`, `.agent/context/stack.md`, relevant `crates/aura-core` and `crates/aura-ui/src/cli` sources |
| Plugins | `README.md` plugin section, `docs/plugin-system.md`, `docs/plugin-authoring.md`, `plugins/*/README.md`, relevant plugin/core sources |
| Issue publishing | `.github/ISSUE_TEMPLATE/bug_report.yml`, `.github/ISSUE_TEMPLATE/config.yml`, `CONTRIBUTING.md` |

Expand Down
6 changes: 3 additions & 3 deletions .agent/workflows/customizable-themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ source_refs:
- .design/customization.md
- .design/tokens.md
- .design/agents.md
- crates/aura/src/app.rs
- crates/aura-ui/src/app.rs
- crates/aura-core/src/config.rs
owner: "@rfluid"
tags: [theming, customization, plan]
Expand All @@ -22,7 +22,7 @@ source of truth for schema / precedence; this file is the work order.
## Scope

Land `~/.config/aura/theme.toml` as an override layer on top of the
hard-coded `COLOR_*` constants in `crates/aura/src/app.rs:19-31`.
hard-coded `COLOR_*` constants in `crates/aura-ui/src/app.rs:19-31`.
Defaults preserved; missing file → current look. Per-agent overrides
reuse the existing `AgentConfig.color` plumbing (already implemented at
`crates/aura-core/src/config.rs:29`), so this phase focuses on global
Expand Down Expand Up @@ -71,7 +71,7 @@ spaces.

## Step 2 — Wire `Theme` into `AuraView`

`crates/aura/src/app.rs`:
`crates/aura-ui/src/app.rs`:

1. Add `theme: Theme` field to `AuraView` (after `config_path`),
default-loaded in `new`.
Expand Down
6 changes: 3 additions & 3 deletions .design/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ profile is the active one — active pills, progress-bar fills, the tab underlin
— though that wiring is not yet built (it is the next step after the
luminance-fallback below lands).

Source: `crates/aura/src/app.rs:25-27` and `app.rs:848-862`.
Source: `crates/aura-ui/src/app.rs:25-27` and `app.rs:848-862`.

## Canonical brand colors

Expand Down Expand Up @@ -45,7 +45,7 @@ saturated-but-dim brand greens.

## Helper signature

Add to `crates/aura/src/app.rs` (or a new `crates/aura/src/theme.rs` once the
Add to `crates/aura-ui/src/app.rs` (or a new `crates/aura-ui/src/theme.rs` once the
file grows past comfort):

```rust
Expand Down Expand Up @@ -100,7 +100,7 @@ agent is selected (e.g. error state, no profiles configured).
When you add a variant to `AgentKind`:

1. Add a `COLOR_<NAME>` constant near `app.rs:26`.
2. Add the icon SVG to `crates/aura/icons/<name>.svg`.
2. Add the icon SVG to `assets/icons/<name>.svg`.
3. Extend the match in `agent_icon` (`app.rs:853`).
4. Update the **canonical brand colors** table above.
5. If the brand color trips the `> 0.85` luminance threshold, no extra work —
Expand Down
4 changes: 2 additions & 2 deletions .design/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Status**: implemented. The schema below is the source of truth; the runtime
loader lives at `crates/aura-core/src/theme.rs`, with the AuraView wiring in
`crates/aura/src/app.rs`. Built-in defaults are baked into
`crates/aura-ui/src/app.rs`. Built-in defaults are baked into
`Theme::default()` and the seed file `crates/aura-core/src/theme_default.toml`.

The goal: let users override **any** token from `tokens.md` and any agent's
Expand Down Expand Up @@ -110,7 +110,7 @@ with no extra UI work.

## Implementation notes

- Add `crates/aura/src/theme.rs` exporting a `Theme` struct mirroring the TOML
- Add `crates/aura-ui/src/theme.rs` exporting a `Theme` struct mirroring the TOML
schema, with `Theme::default()` returning the current `COLOR_*` constants.
- Replace direct `COLOR_*` references in `app.rs` with reads from
`self.theme.colors.bg`, etc. (`u32` values, same `rgb(...)` wrapping).
Expand Down
4 changes: 2 additions & 2 deletions .design/tokens.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Tokens

Canonical design tokens for Aura. These mirror the `const COLOR_*` declarations
in `crates/aura/src/app.rs:16-23` and the GPUI utilities used throughout the
in `crates/aura-ui/src/app.rs:16-23` and the GPUI utilities used throughout the
render code. Do not invent new tokens without adding them here first.

## Colors

All colors are stored as `u32` literals (RGB, no alpha) and wrapped at the
call-site with `gpui::rgb(...)`. Source of truth: `crates/aura/src/app.rs:16-27`.
call-site with `gpui::rgb(...)`. Source of truth: `crates/aura-ui/src/app.rs:16-27`.

### Neutrals (surface stack)

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ body:
attributes:
label: Possible cause / hypothesis
description: |
Optional. Only include if you have *evidence* — a stack trace pointing at a function, a `git bisect` result, a code path you read. Reference paths like `crates/aura/src/app.rs:274`. Speculation without evidence is fine to leave blank; the maintainers prefer "I don't know" over guesses.
Optional. Only include if you have *evidence* — a stack trace pointing at a function, a `git bisect` result, a code path you read. Reference paths like `crates/aura-ui/src/app.rs:274`. Speculation without evidence is fine to leave blank; the maintainers prefer "I don't know" over guesses.
validations:
required: false

Expand Down
8 changes: 5 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ A first build pulls a lot of GPUI dependencies — give it a few minutes.
```
aura/
├── crates/
│ ├── aura/ # Binary crate — GPUI app, tray, modal UI
│ └── aura-core/ # Library — config, readers, plugin runner, quota logic
│ ├── aura/ # Master binary crate — `aura` entry point, routes to cli or ui
│ ├── aura-cli/ # Library — headless `aura <subcommand>` surface (clap)
│ ├── aura-core/ # Library — config, readers, plugin runner, quota logic
│ └── aura-ui/ # Library — GPUI app, tray, modal UI
├── plugins/
│ └── rtk-gains/ # First-party plugin: RTK token savings panel
├── docs/ # User & architecture docs (see "Documentation index" below)
Expand Down Expand Up @@ -131,7 +133,7 @@ cargo test --workspace
- Add the dep to `[workspace.dependencies]` in the root `Cargo.toml` if it is
used by more than one crate, then reference it as `foo = { workspace = true }`
in each member's `Cargo.toml`.
- Keep internal crate versions (`aura-core`, `aura-plugin-rtk`) in sync — they
- Keep internal crate versions (`aura-cli`, `aura-core`, `aura-ui`, `aura-plugin-rtk`) in sync — they
are managed by `scripts/prepare-release.sh`.

### Working on the UI
Expand Down
52 changes: 36 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
[workspace]
members = [
"crates/aura",
"crates/aura-cli",
"crates/aura-core",
"crates/aura-ui",
"plugins/hello",
"plugins/rtk-gains",
]
Expand All @@ -21,7 +23,9 @@ license = "MIT"

[workspace.dependencies]
# Internal crates — versions kept in sync by scripts/prepare-release.sh
aura-cli = { path = "crates/aura-cli", version = "0.1.0" }
aura-core = { path = "crates/aura-core", version = "0.1.21" }
aura-ui = { path = "crates/aura-ui", version = "0.1.0" }
aura-plugin-rtk = { path = "plugins/rtk-gains", version = "0.1.2" }

# External
Expand Down
1 change: 1 addition & 0 deletions PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
## Phase 1 — Cargo workspace & CI ✓

- [x] Create `Cargo.toml` workspace at repo root with members: `crates/aura`, `crates/aura-core`, `plugins/rtk-gains`
- Later split: `crates/aura` is now a thin master binary over `crates/aura-cli` (headless subcommands) and `crates/aura-ui` (GPUI app)
- [x] `crates/aura-core` — library crate (data layer, plugin runner, config, state); no UI deps
- [x] `crates/aura` — binary crate (GPUI app, tray icon, modal); depends on `aura-core`
- [x] `plugins/rtk-gains` — standalone binary crate (the RTK Gains plugin)
Expand Down
20 changes: 20 additions & 0 deletions crates/aura-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "aura-cli"
version = "0.1.0"
edition.workspace = true
license.workspace = true

# Headless `aura <subcommand>` surface. No UI deps: every subcommand runs
# without spinning up GPUI.
[dependencies]
aura-core.workspace = true
anyhow.workspace = true
clap.workspace = true
clap_complete.workspace = true
serde.workspace = true
serde_json.workspace = true
toml.workspace = true

[target.'cfg(unix)'.dependencies]
# SIGPIPE reset in `dispatch`, SIGTERM handling in `aura update`.
libc = "0.2"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
24 changes: 22 additions & 2 deletions crates/aura/src/cli/mod.rs → crates/aura-cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Clap-driven CLI surface for `aura`.
//!
//! With no subcommand `aura` falls through to the tray entry point in
//! `main.rs`. Every other invocation is headless: each subcommand variant
//! `aura-ui`. Every other invocation is headless: each subcommand variant
//! routes to a `run()` on its argument struct and exits without spinning
//! up GPUI.
//!
Expand All @@ -25,7 +25,7 @@ mod update;
mod usage;

use anyhow::Result;
use clap::{Parser, Subcommand};
use clap::{CommandFactory, FromArgMatches, Parser, Subcommand};

#[derive(Debug, Parser)]
#[command(
Expand Down Expand Up @@ -91,7 +91,27 @@ pub enum Command {
SetupConfig,
}

impl Cli {
/// Parse `std::env::args`, reporting `version` for `--version`. The
/// `aura` binary passes its own `CARGO_PKG_VERSION` so the flag tracks
/// the release tag rather than this library crate's version.
pub fn parse_with_version(version: &'static str) -> Self {
let matches = Self::command().version(version).get_matches();
Self::from_arg_matches(&matches).unwrap_or_else(|e| e.exit())
}
}

pub fn dispatch(command: Command) -> Result<()> {
// Rust ignores SIGPIPE, which turns `aura keys describe | head` into
// a "failed printing to stdout" panic. A CLI should just stop quietly
// when its reader goes away, as every Unix tool does.
#[cfg(unix)]
// SAFETY: restoring the default disposition of a signal, before any
// other thread exists.
unsafe {
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
}

match command {
Command::Config(args) => args.run(),
Command::State(args) => args.run(),
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion crates/aura-core/src/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ mod tests {
fn default_matches_legacy_constants() {
let t = Theme::default();
// These are the exact values the binary used to hard-code in
// `crates/aura/src/app.rs` (see `.design/customization.md`).
// `crates/aura-ui/src/app.rs` (see `.design/customization.md`).
assert_eq!(t.colors.bg, 0x0e0e10);
assert_eq!(t.colors.surface, 0x1a1a1f);
assert_eq!(t.colors.surface_hi, 0x252530);
Expand Down
Loading
Loading