Aether — macOS desktop app (Tauri v2 + SolidJS) that manages a bundled Go sidecar (CLIProxyAPI) as an AI proxy. GUI for configuring AI agent presets, provider accounts, and proxy routing.
Full architecture docs with Mermaid diagrams: ARCHITECTURE.md
pnpm install
./scripts/download-sidecar.sh # REQUIRED before any Rust build — fetches CLIProxyAPI binaryThe sidecar version is pinned in .cliproxyapi-version. The script places it at src-tauri/binaries/cliproxyapi-{target-triple}. build.rs will panic if the binary is missing or is a placeholder (<1024 bytes) in release mode.
| Task | Command |
|---|---|
| Dev (full app) | pnpm tauri dev |
| Dev (frontend only) | pnpm dev (Vite on port 1420) |
| Typecheck | tsc -b |
| Production build | pnpm tauri build (requires real sidecar) |
| Bump version | ./scripts/version-bump.sh <version> (syncs package.json, tauri.conf.json, Cargo.toml) |
No tests, linter, formatter, or CI exist in this repo.
- SolidJS (not React) — uses
createSignal,createEffect,<For>,<Show>, etc. JSX pragma issolid-js. - Entry:
index.tsx→App.tsx(routes defined there) - Pages in
src/pages/, components insrc/components/— both have barrelindex.tsexports - Stores in
src/stores/—proxyStore,accountStore,presetStore,requestStore,configWatcher - Styling: Tailwind CSS v4 via
@tailwindcss/vite— custom dark glassmorphism tokens insrc/styles/app.css - Two windows:
main(1200×800, overlay titlebar) andpopup(320×400, transparent tray popup)
- Entry:
main.rs→lib.rs(app_lib::run()) - Modules:
commands/(incl.agents.rs),config/,proxy/,keychain/,watcher.rs - Tauri commands cover: preset CRUD, proxy lifecycle, event streaming, provider accounts, settings, agent detection, file I/O, version info
CLIProxyAPIGo binary fromrouter-for-me/CLIProxyAPI- Managed via Tauri shell plugin (spawn, stdin-write, kill)
- Version exposed at compile time as
BUNDLED_SIDECAR_VERSIONenv var
Each store owns a specific domain. Know which store a page/component depends on before editing.
| Store | Domain | Consumed by (pages) | Consumed by (components) |
|---|---|---|---|
proxyStore |
Proxy lifecycle, status, port | Dashboard, CliproxyOverview, ControlPanel, Settings, Popup | App.tsx |
presetStore |
Preset CRUD, model/provider parsing | Dashboard, Presets, Popup | EditPresetForm, PresetCard, CreatePresetModal, configWatcher |
accountStore |
Provider accounts, API key status | Dashboard, Accounts | AddAccountModal, ProviderCard |
requestStore |
Live request monitoring | Monitor | RequestTable, RequestDetailPanel |
configWatcher |
External config hot-reload | — | App.tsx → triggers presetStore.refresh |
- SolidJS, NOT React. Never use
useState,useEffect,useRef, etc. - Reactive primitives:
createSignal,createEffect,createMemo,createResource - Control flow:
<Show>,<For>,<Switch>/<Match>— not ternaries or.map() - Lifecycle:
onMount,onCleanup— notuseEffect - Store pattern: exported
const fooStore = { ... }object with signal getters + action functions that wrapinvoke() - Interface naming:
FooPropsfor component props (e.g.EditPresetFormProps) - Helper functions: standalone named functions (e.g.
providerColor), not class methods - Strict TS flags:
noUnusedLocals,noUnusedParameters,erasableSyntaxOnly,verbatimModuleSyntax - Imports: use
typekeyword for type-only imports (import type { Foo } from ...) - Target: ES2023, ESM modules (
"type": "module")
- Edition 2021, rust-version 1.77.2
- Tauri commands:
#[tauri::command]async functions, snake_case - Error handling:
anyhow::Resultwith descriptive error context - Module layout:
mod.rspattern for directories - Crate name:
app_lib
- Tailwind CSS v4 via
@tailwindcss/vite— utility-first - Custom dark glassmorphism tokens in
src/styles/app.css - Separate
popup.cssfor tray popup window
- Config path is
~/.config/aether/, not~/Library/Application Support/. The Go sidecar's flag parser breaks on spaces in paths. Do not change this. - Reads
~/.config/opencode/opencode.jsonfor AI models/providers and~/.config/opencode/oh-my-opencode-slim.jsonfor preset configs. - Proxy config generated at
~/.config/aether/proxy-config.yaml, settings at~/.config/aether/settings.json. Default proxy port: 8317. - Main window close hides to tray instead of quitting.
- macOS-only:
macOSPrivateApi: true, min macOS 13.0, entitlements grant network + keychain access.
| File | Why |
|---|---|
src-tauri/build.rs |
Sidecar validation logic — wrong changes = build panic |
src-tauri/tauri.conf.json |
Window config, permissions, capabilities — breaks app if misconfigured |
src-tauri/capabilities/*.json |
macOS entitlements (network, keychain) |
.cliproxyapi-version |
Sidecar version pin — must match download script |
scripts/download-sidecar.sh |
Fetches correct binary per target triple |
src/styles/app.css |
Global design tokens — changes cascade everywhere |
This project is onboarded with Serena for LSP-aware code navigation and refactoring.
| Memory | Content |
|---|---|
project_overview |
Purpose, tech stack, three-layer architecture, file structure |
suggested_commands |
Setup, dev, build, version bump commands |
style_and_conventions |
SolidJS patterns, TS strict flags, Rust conventions, Tailwind |
task_completion |
Checklist for verifying changes (typecheck, quirks) |
architecture/dependency_graph |
Page→store, component→store, backend module deps, execution flows |
analytics/implementation |
Analytics store implementation details and patterns |
bugfix/analyticsStore_duplicate_memos |
Fix for duplicate memo computations in analytics store |
global/changelog-2026-03-31 |
Global changelog entry from March 2026 |
- Symbol lookup:
find_symbol— find any function/class/interface by name across the codebase - Go to definition:
find_declaration— jump to where a symbol is defined - Find references:
find_referencing_symbols— who calls/uses this symbol? - Find implementations:
find_implementations— concrete implementations of interfaces - Safe refactoring:
rename_symbol— LSP-powered rename across all files - Safe delete:
safe_delete_symbol— only deletes if no references exist - Diagnostics:
get_diagnostics_for_file— type errors, warnings per file - Code overview:
get_symbols_overview— quick scan of all symbols in a file
| Need | Use |
|---|---|
| Exact symbol lookup, go-to-definition, rename | Serena (LSP-precise) |
| Execution flow tracing, blast radius analysis | GitNexus (knowledge graph) |
| Find all references to a symbol | Serena find_referencing_symbols |
| Understand what an entire flow does end-to-end | GitNexus query or context |
| Pre-commit change verification | GitNexus detect_changes |
| Type error diagnostics | Serena get_diagnostics_for_file |
This project is indexed by GitNexus as aether (1469 symbols, 2752 relationships, 126 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
If any GitNexus tool warns the index is stale, run
npx gitnexus analyzein terminal first.
- MUST run impact analysis before editing any symbol. Before modifying a function, class, or method, run
gitnexus_impact({target: "symbolName", direction: "upstream"})and report the blast radius (direct callers, affected processes, risk level) to the user. - MUST run
gitnexus_detect_changes()before committing to verify your changes only affect expected symbols and execution flows. - MUST warn the user if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
- When exploring unfamiliar code, use
gitnexus_query({query: "concept"})to find execution flows instead of grepping. It returns process-grouped results ranked by relevance. - When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use
gitnexus_context({name: "symbolName"}).
- NEVER edit a function, class, or method without first running
gitnexus_impacton it. - NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
- NEVER rename symbols with find-and-replace — use
gitnexus_renamewhich understands the call graph. - NEVER commit changes without running
gitnexus_detect_changes()to check affected scope.
| Resource | Use for |
|---|---|
gitnexus://repo/aether/context |
Codebase overview, check index freshness |
gitnexus://repo/aether/clusters |
All functional areas |
gitnexus://repo/aether/processes |
All execution flows |
gitnexus://repo/aether/process/{name} |
Step-by-step execution trace |
| Task | Read this skill file |
|---|---|
| Understand architecture / "How does X work?" | .claude/skills/gitnexus/gitnexus-exploring/SKILL.md |
| Blast radius / "What breaks if I change X?" | .claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md |
| Trace bugs / "Why is X failing?" | .claude/skills/gitnexus/gitnexus-debugging/SKILL.md |
| Rename / extract / split / refactor | .claude/skills/gitnexus/gitnexus-refactoring/SKILL.md |
| Tools, resources, schema reference | .claude/skills/gitnexus/gitnexus-guide/SKILL.md |
| Index, status, clean, wiki CLI commands | .claude/skills/gitnexus/gitnexus-cli/SKILL.md |