diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f26bf23
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Marcus Hinz
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index acf5f05..59bb1bc 100644
--- a/README.md
+++ b/README.md
@@ -1,73 +1,102 @@
# ai-control
-Pool- und Session-Verwaltung für [Claude Code](https://claude.com/claude-code) auf macOS — als Tray-App mit eingebautem Terminal. Linux- und Windows-Integration folgen.
+Pool and session management for [Claude Code](https://claude.com/claude-code) on macOS — a tray app with a built-in terminal. Linux and Windows integration to follow.
-> Der gesamte Code dieses Projekts wurde von Claude (Claude Code) generiert.
+> All code in this project was generated by Claude (Claude Code).
-## Zweck
+
-Wer Claude Code mit mehreren Accounts bzw. Credential-Sets betreibt, muss pro Session das richtige `CLAUDE_CONFIG_DIR` samt Keychain-Eintrag treffen. ai-control macht daraus Klicks:
+## Purpose
-- **Pools** — benannte Credential-Sets (OAuth-Login oder API-Key) unter `~/.config/ai-control/pools/`. Jeder Pool ist ein eigenständiges Claude-Config-Verzeichnis mit eigenem Keychain-Eintrag.
-- **Projekte** — beliebige Verzeichnisse, gemappt über eine Registry (`~/.config/ai-control/projects.json`, Name → Pfad; Home-Pfade als `~/…` und damit maschinenübergreifend stabil). Jedem Projekt ist ein Pool zugeordnet; dazu Terminal-Einstellungen (Theme, Icon, Fenstertitel).
-- **Sessions** — pro Projekt ein eingebautes Terminal (xterm.js + PTY), das Claude Code mit der Pool-Umgebung startet. Jedes Terminal läuft als eigener Prozess mit eigenem Dock-Icon und Cmd-Tab-Eintrag.
-- **Tray** — die App selbst ist eine reine Menüleisten-App ohne Dock-Eintrag. Das Tray-Menü listet alle Projekte mit Icon und Status-Punkt (grün = läuft); Klick startet das Projekt oder holt das laufende Terminal nach vorn.
-- **Session-Watcher** — erkennt das Ende einer Session über das Verschwinden des Terminal-Prozesses und synct dann (opt-in) das Git-Repo, in dem das Projekt liegt: add → commit → pull --rebase → push.
+Running Claude Code with multiple accounts or credential sets means hitting the right `CLAUDE_CONFIG_DIR` (plus keychain entry) for every session. ai-control turns that into clicks:
-## Projektaufbau
+- **Pools** — named credential sets (OAuth login or API key) under `~/.config/ai-control/pools/`. 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 with its own Dock icon and Cmd-Tab entry.
+- **Tray** — the app itself is a pure menu-bar app without a Dock entry. The tray menu lists all projects with icon and status dot (green = running); clicking starts the project or brings the running terminal to the front.
+- **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.
+
+## Screenshots
+
+| Pools | Usage |
+|---|---|
+|  |  |
+
+| Tray menu | Session terminal |
+|---|---|
+|  |  |
+
+## Project layout
```
-├── index.html Haupt-UI (Projekt-/Pool-Verwaltung)
-├── terminal.html Terminal-Fenster (xterm.js)
-├── src/ Frontend: Vue 3 + TypeScript
+├── index.html main UI (project/pool management)
+├── terminal.html terminal window (xterm.js)
+├── src/ frontend: Vue 3 + TypeScript
├── src-tauri/
-│ ├── src/lib.rs Tauri-Commands: Projekte, Pools, Keychain,
-│ │ OAuth-Login, Tray-Menü, Session-Watcher
-│ ├── src/terminal.rs PTY-Sessions (portable-pty), Terminal-Fenster,
-│ │ Dock-Icon, Fokussieren laufender Terminals
-│ └── icons/ App- und Tray-Icons
-├── dev.sh Entwicklungsmodus (tauri dev)
-└── build.sh Release-Build (.app-Bundle)
+│ ├── src/lib.rs Tauri commands: projects, pools, keychain,
+│ │ OAuth login, tray menu, session watcher
+│ ├── src/terminal.rs PTY sessions (portable-pty), terminal windows,
+│ │ Dock icon, focusing running terminals
+│ └── icons/ app and tray icons
+├── dev.sh development mode (tauri dev)
+└── build.sh release build (.app bundle)
```
-Zwei Prozessrollen aus einem Binary:
+Two process roles from one binary:
-- **Haupt-App** (`ai-control`) — Tray, Hauptfenster, Verwaltung, Watcher.
-- **Terminal-Prozess** (`ai-control --terminal `) — ein Fenster mit eigener PTY; startet Claude Code im Projektverzeichnis mit `CLAUDE_CONFIG_DIR` des zugeordneten Pools.
+- **Main app** (`ai-control`) — tray, main window, management, watcher.
+- **Terminal process** (`ai-control --terminal `) — one window with its own PTY; launches Claude Code in the project directory with the assigned pool's `CLAUDE_CONFIG_DIR`.
-Laufende Projekte werden über die Terminal-Prozesse erkannt (`pgrep` auf `--terminal `), ohne Zustandsdatei.
+Running projects are detected through their terminal processes (`pgrep` for `--terminal `), without a state file.
## Tooling
-| Bereich | Stack |
+| Area | Stack |
|-----------|-------|
| Shell | Tauri 2 (Rust) |
| Frontend | Vue 3, TypeScript, Vite |
| Terminal | xterm.js, portable-pty |
-| macOS | objc2 / objc2-app-kit (Dock-Icon, Fenster-Fokus, Tray) |
+| macOS | objc2 / objc2-app-kit (Dock icon, window focus, tray) |
| Secrets | keyring (macOS Keychain) |
-## Entwicklung
+## Development
```sh
-./dev.sh # tauri dev mit Hot-Reload
-./build.sh # Release-Build; Bundle landet in src-tauri/target/release/bundle/macos.noindex/
+./dev.sh # tauri dev with hot reload
+./build.sh # release build; bundle lands in src-tauri/target/release/bundle/macos.noindex/
```
-`build.sh` verschiebt das Bundle in ein `.noindex`-Verzeichnis und trägt es aus Launch Services aus, damit Spotlight nur die installierte Kopie findet. Installation: `ai-control.app` nach `~/Applications` kopieren.
+`build.sh` moves the 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`.
-Voraussetzungen: Rust (stable), Node.js/npm, macOS. `dev.sh`/`build.sh` erwarten `CARGO_HOME`/`RUSTUP_HOME` unter `~/tools/` — bei Standard-Installation die beiden Exporte in den Skripten anpassen.
+Prerequisites: Rust (stable), Node.js/npm, macOS. `dev.sh`/`build.sh` expect `CARGO_HOME`/`RUSTUP_HOME` under `~/tools/` — adjust the two exports in the scripts for a standard installation.
-## Konfigurationslayout
+## Configuration layout
```
~/.config/ai-control/
-├── settings.json App-Einstellungen (z. B. syncOnSessionEnd)
-├── projects.json Projekt-Registry: Name → Ordner
-└── pools// je Pool ein Claude-Config-Verzeichnis
- └── pool.json Name + Credential-Typ
+├── settings.json app settings (see below)
+├── projects.json project registry: name → directory
+└── pools// one Claude config directory per pool
+ └── pool.json name + credential type
-/ beliebiger Pfad, per Registry gemappt
-├── .claude/ Claude-Code-Projektkonfiguration
-└── ai-control.json Pool-Zuordnung + Terminal-Einstellungen
+/ any path, mapped via the registry
+├── .claude/ Claude Code project configuration
+└── ai-control.json pool assignment + terminal settings
```
+
+### settings.json
+
+| Key | Default | Meaning |
+|--------------------|----------|---------|
+| `claudeCommand` | `claude` | Command launched in the project terminal (via `zsh -ic`, so your `.zshrc` PATH applies). |
+| `syncOnSessionEnd` | `false` | After a session ends, commit and push the Git repository containing the project. |
+
+## Claude and Anthropic licensing
+
+ai-control is pool management only — it does not change, extend, or circumvent Anthropic's licensing in any way. Using Claude Code through ai-control 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, one entry per pool.
+
+## License
+
+[MIT](LICENSE)
diff --git a/docs/pools.png b/docs/pools.png
new file mode 100644
index 0000000..bd23631
Binary files /dev/null and b/docs/pools.png differ
diff --git a/docs/projects.png b/docs/projects.png
new file mode 100644
index 0000000..a0b7e5c
Binary files /dev/null and b/docs/projects.png differ
diff --git a/docs/terminal.png b/docs/terminal.png
new file mode 100644
index 0000000..5902262
Binary files /dev/null and b/docs/terminal.png differ
diff --git a/docs/tray.png b/docs/tray.png
new file mode 100644
index 0000000..f46b31d
Binary files /dev/null and b/docs/tray.png differ
diff --git a/docs/usage.png b/docs/usage.png
new file mode 100644
index 0000000..80b95a7
Binary files /dev/null and b/docs/usage.png differ
diff --git a/package.json b/package.json
index 3e6a321..d7137b6 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,7 @@
"name": "ai-control",
"private": true,
"version": "0.0.0",
+ "license": "MIT",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 883dc8b..5d62cd3 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -3,7 +3,7 @@ name = "ai-control"
version = "0.1.0"
description = "Pool- und Session-Verwaltung für Claude Code"
authors = ["marcus.hinz"]
-license = ""
+license = "MIT"
repository = ""
edition = "2021"
rust-version = "1.77.2"
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index 67872a4..d91b172 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -48,6 +48,12 @@ impl Paths {
self.config_dir().join("pools")
}
+ /// Gemeinsames Icons-Verzeichnis aller Projekte — synct mit der App-Config,
+ /// unabhängig von Pool-Zuordnung und Quell-Repos.
+ fn icons_dir(&self) -> PathBuf {
+ self.config_dir().join("icons")
+ }
+
fn pool_dir(&self, pool: &str) -> PathBuf {
self.pools_dir().join(pool)
}
@@ -208,6 +214,22 @@ fn sync_on_session_end(paths: &Paths) -> bool {
.unwrap_or(false)
}
+/// Kommando, das im Projekt-Terminal startet (settings.json: claudeCommand).
+pub(crate) fn claude_command(paths: &Paths) -> String {
+ fs::read_to_string(paths.config_dir().join(APP_SETTINGS_FILE))
+ .ok()
+ .and_then(|s| serde_json::from_str::(&s).ok())
+ .and_then(|v| v["claudeCommand"].as_str().map(str::to_string))
+ .unwrap_or_else(|| "claude".into())
+}
+
+/// Pool-Config-Verzeichnis eines Projekts — wird dem Terminal als
+/// CLAUDE_CONFIG_DIR mitgegeben.
+pub(crate) fn project_pool_dir(project: &str) -> Result