994d5070f0
- Archiv-Home pro Projekt (archiveHome in ai-control.json); archive_panel mit Ordner, Beschreibung und Schlagwörtern (Frontmatter + Zeitstempel-Stem) - Archiv-Index (archive_index.rs): Scan mit Frontmatter, Wikilinks, Backlinks; Wiki-Seiten als strukturierte Daten (Übersicht/Tag-Seiten) - FTS5-Suche (archive_search.rs, rusqlite bundled): in-memory-Index pro Anfrage; MCP search_archive und Panel-Suchfeld (search_run) teilen die Engine - Panel: vier Puffer/Ansichten (Dokument, Befehle, Suche, Wiki) mit Tabs im Fenster-Header; gemeinsame Verdrahtung panel-wiring.ts, Kachel-CSS, Wiki-View mit Tag-Chips, Ordner-Sektionen und Backlinks - Archivieren speichert offene Bearbeitung (flush); Tab-Wechsel speichert statt zu blockieren; Fehler sichtbar als Panel-Toast - Abgelöstes Fenster: rahmenlos (Linux), eigene Kopfleiste mit Tabs und Fensterknöpfen, Theme-Kopplung über gemeinsames themes.ts - MCP-Tools show_commands, show_archive; Befehls-History mit Kachel-Löschen
157 lines
9.6 KiB
Markdown
157 lines
9.6 KiB
Markdown
# aICentral
|
|
|
|
**Get Claude Code organized** — pool and session management for [Claude Code](https://claude.com/claude-code), as a tray app with a built-in terminal and a draft panel. macOS and Linux; Windows support follows soon. (Repository and binary name: `ai-control`.)
|
|
|
|
> All code in this project was generated by Claude (Claude Code).
|
|
|
|
<img src="docs/projects.png" width="640" alt="Projects">
|
|
|
|
## Purpose
|
|
|
|
Running Claude Code with multiple accounts or credential sets means hitting the right `CLAUDE_CONFIG_DIR` (plus keychain entry) for every session. aICentral turns that into clicks:
|
|
|
|
- **Pools** — named credential sets (OAuth login or API key) under `~/.config/ai-control/pools/<pool>`. Each pool is a self-contained Claude config directory with its own keychain entry.
|
|
- **Projects** — arbitrary directories, mapped through a registry (`~/.config/ai-control/projects.json`, name → path; paths under home are stored as `~/…` and therefore stable across machines). Each project is assigned a pool, plus terminal settings (theme, icon, window title).
|
|
- **Sessions** — a built-in terminal per project (xterm.js + PTY) that launches Claude Code with the pool's config directory as `CLAUDE_CONFIG_DIR`. Every terminal runs as its own process — on macOS with its own Dock icon and Cmd-Tab entry, on Linux as its own window with its own app id.
|
|
- **Tray** — the app itself is a pure tray app. Clicking the tray icon opens a popup listing all projects with icon and status dot (green = running); clicking a project starts it or brings the running terminal to the front.
|
|
- **Text panel** — a draft panel beside the terminal. Claude writes longer texts (ADRs, emails, commit messages, specs) into it through a bundled MCP tool instead of flooding the chat; the panel text is mouse-selectable, copyable via button, and archivable per project.
|
|
- **Session watcher** — detects the end of a session by the terminal process disappearing and then (opt-in) syncs the Git repository containing the project: add → commit → pull --rebase → push.
|
|
|
|
## Text panel
|
|
|
|
The app ships an MCP stdio server (`ai-control --mcp-panel`, server key `text-panel`) and provisions it into every pool, including the tool permission — no per-pool setup:
|
|
|
|
- **`write_panel`** — Claude places a Markdown draft in the panel next to the terminal instead of printing it as chat prose.
|
|
- **`archive_panel`** — saves the current draft as a Markdown file into the project's archive directory (`archiveDir` in the project's `ai-control.json`).
|
|
|
|
The panel docks into the terminal window and can be detached into its own window; the title is taken from the draft's first heading and can be edited, the content is editable too. Spell checking follows `spellcheckLang` (per-text override in the panel).
|
|
|
|
## Screenshots
|
|
|
|
| Pools | Usage |
|
|
|---|---|
|
|
|  |  |
|
|
|
|
| Tray menu | Session terminal |
|
|
|---|---|
|
|
|  |  |
|
|
|
|
## Installation
|
|
|
|
### macOS
|
|
|
|
Prebuilt DMGs are attached to the releases. The bundles are **not signed or notarized** — an Apple Developer ID costs €99/year, which this project doesn't have. If you'd like to change that: [Buy me a coffee](https://buymeacoffee.com/marcusH). macOS quarantines the unsigned download; after copying `ai-control.app` to `~/Applications`, clear it with:
|
|
|
|
```sh
|
|
xattr -d com.apple.quarantine ~/Applications/ai-control.app
|
|
```
|
|
|
|
Or avoid the topic entirely and build from source (below) — self-built apps aren't quarantined.
|
|
|
|
### Linux
|
|
|
|
Releases carry a `.deb` and an AppImage.
|
|
|
|
- **deb** — recommended. It also installs the GNOME Shell extension and the KWin script that provide the tray/popup integration on GNOME and KDE Wayland.
|
|
- **AppImage** — runs on desktops with a standard tray (KDE, XFCE, Cinnamon). On GNOME it refuses to start and points to the deb: the tray there needs the shell extension, which an installation-free AppImage cannot provide.
|
|
|
|
Tray integration by desktop: GNOME via the bundled shell extension, KDE Wayland via StatusNotifierItem plus the bundled KWin script for popup placement, KDE X11/XFCE/Cinnamon via StatusNotifierItem directly.
|
|
|
|
### Installer tests
|
|
|
|
The installers are hand-tested per release. Current state: Ubuntu 26.04 (GNOME), Kubuntu (KDE Plasma, Wayland) and Linux Mint (Cinnamon) via deb — on Mint install through the graphical installer; macOS re-test of the current build is in progress.
|
|
|
|
### Windows
|
|
|
|
Follows soon.
|
|
|
|
## Project layout
|
|
|
|
```
|
|
├── index.html main UI (project/pool management)
|
|
├── terminal.html terminal window (xterm.js) + docked text panel
|
|
├── panel.html detached text panel window
|
|
├── popup.html tray popup
|
|
├── src/ frontend: Vue 3 + TypeScript
|
|
├── src-tauri/
|
|
│ ├── src/lib.rs entry point, process roles
|
|
│ ├── src/app.rs Tauri wiring: tray, main/popup windows, watcher
|
|
│ ├── src/mcp.rs MCP stdio server (write_panel / archive_panel)
|
|
│ ├── src/terminal.rs PTY sessions (portable-pty), terminal windows
|
|
│ ├── src/platform/ macOS / Linux / Windows specifics
|
|
│ └── icons/ app and tray icons
|
|
├── gnome-shell-extension/ tray/popup integration for GNOME
|
|
├── kwin-script/ popup placement for KDE Wayland
|
|
├── dev.sh development mode (tauri dev)
|
|
└── build.sh macOS release build (.app bundle + DMG)
|
|
```
|
|
|
|
Process roles from one binary:
|
|
|
|
- **Main app** (`ai-control`) — tray, main window, management, watcher.
|
|
- **Terminal process** (`ai-control --terminal <project>`) — one window with its own PTY; launches Claude Code in the project directory with the assigned pool's `CLAUDE_CONFIG_DIR`.
|
|
- **MCP server** (`ai-control --mcp-panel`) — stdio server started by Claude Code itself; no GUI.
|
|
|
|
Running projects are detected through their terminal processes (`pgrep` for `--terminal <project>`), without a state file.
|
|
|
|
## Tooling
|
|
|
|
| Area | Stack |
|
|
|-----------|-------|
|
|
| Shell | Tauri 2 (Rust) |
|
|
| Frontend | Vue 3, TypeScript, Vite |
|
|
| Terminal | xterm.js, portable-pty |
|
|
| macOS | objc2 / objc2-app-kit (Dock icon, window focus, tray) |
|
|
| Linux | GTK 3 / WebKitGTK, ksni (StatusNotifierItem), zbus (D-Bus) |
|
|
| Secrets | keyring (macOS Keychain / Secret Service) |
|
|
|
|
## Development
|
|
|
|
```sh
|
|
./dev.sh # tauri dev with hot reload
|
|
./build.sh # macOS release build; bundle lands in src-tauri/target/release/bundle/macos.noindex/
|
|
```
|
|
|
|
On Linux, build with `npm run tauri build`; artifacts land under `src-tauri/target/release/bundle/` (`deb/`, `appimage/`). Build dependencies: `webkit2gtk-4.1`, `libgtk-3`, `libayatana-appindicator3`, `librsvg2`, `patchelf`.
|
|
|
|
`build.sh` moves the macOS bundle into a `.noindex` directory and unregisters it from Launch Services so Spotlight only finds the installed copy. Install by copying `ai-control.app` to `~/Applications`.
|
|
|
|
Prerequisites: Rust (stable), Node.js/npm. `dev.sh`/`build.sh` expect `CARGO_HOME`/`RUSTUP_HOME` under `~/tools/` — adjust the two exports in the scripts for a standard installation.
|
|
|
|
## Configuration layout
|
|
|
|
```
|
|
~/.config/ai-control/
|
|
├── settings.json app settings (see below)
|
|
├── projects.json project registry: name → directory
|
|
└── pools/<pool>/ one Claude config directory per pool
|
|
└── pool.json name + credential type
|
|
|
|
<project directory>/ any path, mapped via the registry
|
|
├── .claude/ Claude Code project configuration
|
|
└── ai-control.json pool assignment, terminal settings,
|
|
panel archive directory (archiveDir)
|
|
```
|
|
|
|
### settings.json
|
|
|
|
| Key | Default | Meaning |
|
|
|--------------------|----------|---------|
|
|
| `claudeCommand` | `claude` | Command launched in the project terminal (via your login shell, `$SHELL -lc`, so your profile PATH applies). |
|
|
| `syncOnSessionEnd` | `false` | After a session ends, commit and push the Git repository containing the project. |
|
|
| `poolSyncDir` | unset | Directory to sync pool runtime data into (session transcripts, todos, prompt history — what `/resume` needs). When set, a pool's runtime files are replaced by symlinks into `<poolSyncDir>/<pool>`, so sessions travel with however that directory is synced (git, Syncthing, …). Unset: everything stays local in the pool directory. |
|
|
| `terminalFontSize` | `13` | Font size of the built-in terminal (also adjustable from the terminal window). |
|
|
| `spellcheckLang` | unset | Default spell-check language of the text panel (per-text override in the panel). |
|
|
|
|
## Claude and Anthropic licensing
|
|
|
|
aICentral is pool management only — it does not change, extend, or circumvent Anthropic's licensing in any way. Using Claude Code through aICentral is subject to the same Anthropic terms as running it directly.
|
|
|
|
For that reason the app stores no OAuth tokens itself: with an OAuth pool, the first session of a project on that pool goes through the regular Anthropic login (`/login`, browser, against your subscription), run by Claude Code itself. Credentials live where Claude Code puts them — in the macOS Keychain or the freedesktop Secret Service, one entry per pool.
|
|
|
|
API keys go into the keychain as well (one entry per pool). Only when no keychain/keyring is available does the app offer — after an explicit confirmation — to store the key as a file in the pool directory (mode 0600). We strongly advise against that fallback: an API key on disk is readable by every process running as your user. Use the keychain.
|
|
|
|
## License
|
|
|
|
[MIT](LICENSE)
|