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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 7 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,22 @@ permissions:

jobs:
test:
name: Rust unit tests
name: Unit tests
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: dtolnay/rust-toolchain@stable
- uses: swatinem/rust-cache@v2
with:
workspaces: './src-tauri -> target'
- name: Install Linux deps
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.1-dev libssl-dev
# i18n dictionary parity + the repo-wide 220-line module rule.
- name: npm test
run: node test/run.js
- name: cargo test
run: cargo test --lib --manifest-path src-tauri/Cargo.toml

Expand Down
5 changes: 1 addition & 4 deletions build/generate-tray-icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,5 @@ const out2x = path.join(__dirname, 'iconTemplate@2x.png');
fs.writeFileSync(out1x, generatePng(22, 1));
fs.writeFileSync(out2x, generatePng(44, 2));

// Copy to source folder
fs.copyFileSync(out1x, path.join(__dirname, '..', 'src', 'main', 'iconTemplate.png'));
fs.copyFileSync(out2x, path.join(__dirname, '..', 'src', 'main', 'iconTemplate@2x.png'));

// build/iconTemplate.png is the tray icon the Rust backend embeds (include_bytes! in lib.rs).
console.log('Successfully generated minimalist template icons.');
53 changes: 53 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Architecture

CC Buddy is a Tauri app: a Rust backend (`src-tauri/`) and a plain-ESM renderer (`src/renderer/`)
with no bundler. This document records the two rules that shape the codebase.

## Rule 1 — no source file over 220 lines

Enforced by `test/file-size.test.js` (part of `npm test`). Vendored bundles, the generated
`styles.css` and the build-synced `src/renderer/shared/` copy are exempt; everything else is
hand-maintained source and must stay under the limit. Reaching for a split is the intended
response, not raising the number.

The corollary is a module per responsibility. Where a file would otherwise grow, it becomes a
directory module (`foo.rs` → `foo/mod.rs` + siblings; a view → `views/<name>/index.js` + siblings)
whose `mod.rs` / `index.js` is the only public surface.

## Rule 2 — nothing on the cold-start path that a later click could load

**Backend.** `setup()` in `src-tauri/src/lib.rs` only builds the window, tray and event hooks.
Every filesystem-heavy boot step — one-time `historyDirs` migrations, plugin reconcile, CLI
connection repair, gateway and plugin start, history-watcher registration, usage-cache warm —
runs off the main thread from `startup::spawn_background_boot`, in the same order as before.
The window paints and accepts input while that work proceeds.

**Renderer.** `index.html` ships the shell plus the first view (服务) only. `js/main.js` and the
`js/core/` modules it imports are the only JavaScript parsed before first paint:

| Loaded at startup | Loaded on demand |
| --- | --- |
| shell markup + 服务 view | 插件 / 监控 / 设置 / 会话 markup and modules (`views/registry.js`) |
| active locale's dictionary parts | the other four locales (`shared/i18n/parts.js` manifest) |
| `theme-boot.js` (pre-paint theme/lang stamp) | `marked` + `highlight.js` (`core/loader.js`, on first transcript or inspector open) |
| analytics queue stub (deferred) | provider modal, request-inspector drawer, plugin forms |

Two idle prefetches warm the heaviest lazy paths (vendor bundles, the 会话 view) after boot, so
the first click still feels instant without costing startup.

## Module map

```
src/renderer/
js/core/ bridge (IPC) · state · i18n · loader · dom · icons · theme · toast
js/views/ registry + providers/ plugins/ monitor/ settings/ conversations/
js/popover/ tray usage window
css/ numbered partials; input.css is the @import manifest (order = cascade order)
src/shared/i18n/ per-language, per-domain dictionary parts + index (Node) / parts.js (browser)
src-tauri/src/ startup · gateway/ · history/ · protocol/ · codex/ · store · usage · plugin · …
```

## Testing

- `npm test` — i18n dictionary parity across locales, part-manifest integrity, file-size rule.
- `cd src-tauri && cargo test` — the gateway, history, usage, export and protocol engines.
93 changes: 3 additions & 90 deletions package-lock.json

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

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ccbud",
"version": "1.3.8",
"version": "1.3.9",
"description": "CC Buddy — Coding CLI Buddy. A cross-platform desktop app that proxies Claude Code to any Anthropic-compatible provider (one-click switching, model mapping) and browses your Claude Code & Codex session history.",
"author": {
"name": "loadchange",
Expand All @@ -19,7 +19,7 @@
"release": "node scripts/release.js",
"start": "tauri dev",
"dev": "tauri dev",
"test": "node test/selftest.js",
"test": "node test/run.js",
"update:cask": "node scripts/update-cask.js",
"dist": "tauri build",
"dist:mac": "tauri build",
Expand All @@ -34,7 +34,6 @@
"tailwindcss": "^4.3.1"
},
"dependencies": {
"@microsoft/clarity": "^1.0.2",
"js-tiktoken": "^1.0.21"
"@microsoft/clarity": "^1.0.2"
}
}
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

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

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "app"
version = "1.3.8"
version = "1.3.9"
description = "CCBuddy — Coding CLI Buddy"
authors = ["loadchange <soocto@gmail.com>"]
license = "GPL-3.0-only"
Expand Down
Loading
Loading