Initial commit
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"autoMemoryDirectory": "~/claude-projects/ai-control/memory",
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"command": "jq -Rs '{systemMessage: ., hookSpecificOutput:{hookEventName:\"SessionStart\", additionalContext: .}}' /Users/marcus.hinz/claude-projects/ai-control/OFFENE-PUNKTE.md",
|
||||
"type": "command"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"permissions": {
|
||||
"additionalDirectories": [
|
||||
"~/projects/ai-control"
|
||||
],
|
||||
"allow": [
|
||||
"Edit(~/projects/ai-control/**)",
|
||||
"Edit(~/claude-projects/ai-control/**)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
---
|
||||
name: git-commit
|
||||
description: >
|
||||
Commit + Push des ai-control-App-Repos auf lintus (origin, volle Dev-Historie).
|
||||
Optional, nur auf ausdrückliche Ansage: kuratierter Squash-Publish + Tag auf
|
||||
github und GitHub-Release mit Linux-Binaries. Gedacht für die Linux-Box.
|
||||
---
|
||||
|
||||
# git-commit — ai-control veröffentlichen
|
||||
|
||||
Zwei Ebenen, strikt getrennt:
|
||||
|
||||
1. **Immer**: Commit + Push auf **lintus** (`origin`) — die volle Dev-Historie.
|
||||
2. **Optional, nur wenn ausdrücklich verlangt**: Publish auf **github** (Squash-Mirror) und ein GitHub-Release mit Linux-Binaries.
|
||||
|
||||
Nie ohne Ansage die github-Ebene mitlaufen lassen. Commit-Messages ohne jeden Claude-Hinweis (kein Co-Authored-By, kein „Generated with").
|
||||
|
||||
## Repo & Remotes
|
||||
|
||||
- App-Repo: `~/projects/ai-control`
|
||||
- `origin` → `ssh://git@git.lintus.art:2222/marcus.hinz/ai-control.git` — volle Historie, hierher geht jeder Commit.
|
||||
- `github` → `https://github.com/mHinz-hub/ai-control.git` — **kuratierter Squash-Mirror**: pro Release genau ein Commit `ai-control X.Y.Z`, dessen Tree dem Dev-Tree entspricht. Die volle Dev-Historie gehört **nicht** dorthin.
|
||||
|
||||
`~/claude-projects/ai-control` (Control-Repo) ist ein anderes Repo (nur lintus) — nicht gemeint.
|
||||
|
||||
## 1. Normaler Commit + Push (immer)
|
||||
|
||||
```bash
|
||||
cd ~/projects/ai-control
|
||||
git add -A
|
||||
git status -s # prüfen, was reingeht
|
||||
git commit -m "<sachliche Nachricht>"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
## 2. github-Publish (optional)
|
||||
|
||||
Voraussetzung: der Release-Commit liegt auf lokalem `main` und ist auf lintus gepusht; bei einem Versionssprung ist die Version in **allen vier** Dateien gehoben (siehe Abschnitt 4).
|
||||
|
||||
`git push github main` ist verboten (divergiert gegen den Squash-Mirror → Reject). Stattdessen einen einzelnen Squash-Commit mit dem aktuellen Tree auf `github/main` setzen:
|
||||
|
||||
```bash
|
||||
cd ~/projects/ai-control
|
||||
git fetch github
|
||||
tree=$(git rev-parse HEAD^{tree})
|
||||
new=$(git commit-tree "$tree" -p github/main -m "ai-control X.Y.Z")
|
||||
git push github "$new:main" # Squash-Commit als neues github/main
|
||||
git tag -f vX.Y.Z "$new" # Tag auf den Squash-Commit (nicht den Dev-Commit)
|
||||
git push github -f vX.Y.Z # bestehenden Tag ggf. ersetzen
|
||||
```
|
||||
|
||||
Das hält die lokale Dev-Historie unangetastet und reiht sich in `ai-control 0.1.0 / 0.1.1 / …` ein. Der Tag zeigt bewusst auf den Squash-Commit, nicht auf den Dev-Commit.
|
||||
|
||||
## 3. Release mit Linux-Binaries (optional, auf der Linux-Box)
|
||||
|
||||
Baudeps auf der Box: `webkit2gtk-4.1`, `libgtk-3`, `libayatana-appindicator3`, `librsvg2`, `patchelf`.
|
||||
|
||||
```bash
|
||||
cd ~/projects/ai-control
|
||||
npm run tauri build
|
||||
# Artefakte:
|
||||
# src-tauri/target/release/bundle/appimage/ai-control_*.AppImage
|
||||
# src-tauri/target/release/bundle/deb/ai-control_*.deb
|
||||
|
||||
# Release anlegen (falls noch keins zum Tag existiert):
|
||||
gh release create vX.Y.Z --repo mHinz-hub/ai-control --title "vX.Y.Z" --notes "<Änderungen>"
|
||||
|
||||
# Binaries anhängen (jederzeit nachträglich möglich):
|
||||
gh release upload vX.Y.Z --repo mHinz-hub/ai-control \
|
||||
src-tauri/target/release/bundle/appimage/ai-control_*.AppImage \
|
||||
src-tauri/target/release/bundle/deb/ai-control_*.deb
|
||||
```
|
||||
|
||||
Der macOS-Build (`./build.sh`, DMG) hängt nicht am Linux-Build; `macos-private-api` u. Ä. sind per `cfg` aus. Die GNOME-Popup-Extension ist separat, kein Teil des Binaries.
|
||||
|
||||
## 4. Version heben (bei Release)
|
||||
|
||||
Vor Abschnitt 2/3 die Version in vier Dateien gleichziehen:
|
||||
|
||||
- `package.json` → `"version"`
|
||||
- `src-tauri/Cargo.toml` → `[package] version`
|
||||
- `src-tauri/Cargo.lock` → Eintrag unter `name = "ai-control"`
|
||||
- `src-tauri/tauri.conf.json` → `"version"`
|
||||
|
||||
Dann normal committen (Abschnitt 1), danach optional 2/3.
|
||||
@@ -0,0 +1 @@
|
||||
.ai-control-running
|
||||
@@ -0,0 +1 @@
|
||||
# Offene Punkte — bei jedem Start prüfen und abhaken
|
||||
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"pool": "private",
|
||||
"terminal": {
|
||||
"theme": "monokai",
|
||||
"icon": "ai-control.png"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# connect-test — prüft, ob claude mit der aktuellen Env authentifizieren und antworten kann.
|
||||
# Exit 0 = Verbindung ok. Für Negativtest mit ungültigem Key:
|
||||
# ANTHROPIC_API_KEY=sk-ant-ungueltig connect-test
|
||||
set -euo pipefail
|
||||
|
||||
"${CLAUDE_BIN:-$HOME/.local/bin/claude}" -p 'Antworte nur mit: OK' --model claude-sonnet-5
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# kc-backup — sichert das Secret des Claude-Code-Keychain-Eintrags in eine Datei.
|
||||
# Ablage außerhalb des Git-Repos (Default: ~/.ssh), damit das Secret nie committet wird.
|
||||
# Usage: kc-backup [zieldatei]
|
||||
set -euo pipefail
|
||||
|
||||
dest=${1:-$HOME/.ssh/claude-keychain-backup.json}
|
||||
security find-generic-password -s "Claude Code-credentials" -a "$USER" -w > "$dest"
|
||||
chmod 600 "$dest"
|
||||
echo "Keychain-Secret gesichert nach: $dest ($(wc -c < "$dest" | tr -d ' ') Bytes)"
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# kc-delete — löscht den Claude-Code-Keychain-Eintrag.
|
||||
# Vorher kc-backup ausführen; zurückspielen mit kc-restore.
|
||||
set -euo pipefail
|
||||
|
||||
security delete-generic-password -s "Claude Code-credentials" -a "$USER"
|
||||
echo "Keychain-Eintrag 'Claude Code-credentials' gelöscht."
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# kc-restore — spielt das mit kc-backup gesicherte Secret in den Keychain zurück.
|
||||
# -U aktualisiert einen ggf. vorhandenen Eintrag statt zu scheitern.
|
||||
# Usage: kc-restore [backupdatei]
|
||||
set -euo pipefail
|
||||
|
||||
src=${1:-$HOME/.ssh/claude-keychain-backup.json}
|
||||
security add-generic-password -U -s "Claude Code-credentials" -a "$USER" -w "$(cat "$src")"
|
||||
echo "Keychain-Eintrag aus $src wiederhergestellt."
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# kc-status — zeigt Zustand des Claude-Code-Keychain-Eintrags und der Auth-Env.
|
||||
# mdat = letzte Änderung des Eintrags; ändert sich, wenn eine Session den Keychain beschreibt.
|
||||
set -euo pipefail
|
||||
|
||||
echo "== Keychain-Eintrag 'Claude Code-credentials' =="
|
||||
security find-generic-password -s "Claude Code-credentials" -a "$USER" 2>&1 | grep -E '"(mdat|cdat)"' || echo "kein Eintrag vorhanden"
|
||||
|
||||
echo "== Auth-Env dieser Shell =="
|
||||
env | grep -E '^(ANTHROPIC_API_KEY|CLAUDE_CODE_OAUTH_TOKEN|CLAUDE_CONFIG_DIR)=' | sed -E 's/=(.).*/=\1…/' || echo "keine Auth-Env gesetzt"
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# oauth-configdir-test — prüft, ob claude auf macOS die .credentials.json aus
|
||||
# CLAUDE_CONFIG_DIR liest, wenn kein Keychain-Eintrag existiert.
|
||||
# Ablauf: Backup → Keychain löschen → claude mit bereinigter Auth-Env →
|
||||
# Nachkontrollen → Restore. Restore läuft auch bei fehlgeschlagenem Testlauf.
|
||||
# Usage: oauth-configdir-test [pool] (Default: Mx9Privat)
|
||||
set -u
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
pool=${1:-Mx9Privat}
|
||||
pooldir="$HOME/claude-pools/$pool"
|
||||
|
||||
bin/kc-backup || exit 1
|
||||
bin/kc-delete || exit 1
|
||||
|
||||
echo "== Testlauf: Env ohne ANTHROPIC_API_KEY/CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_CONFIG_DIR=$pooldir =="
|
||||
env -u ANTHROPIC_API_KEY -u CLAUDE_CODE_OAUTH_TOKEN \
|
||||
CLAUDE_CONFIG_DIR="$pooldir" \
|
||||
"${CLAUDE_BIN:-$HOME/.local/bin/claude}" -p 'Antworte nur mit: OK' --model claude-sonnet-5
|
||||
echo "EXIT: $?"
|
||||
|
||||
echo "== credentials-Datei nach Lauf (#10039: darf nicht gelöscht sein) =="
|
||||
ls -la "$pooldir/.credentials.json"
|
||||
|
||||
echo "== Keychain nach Lauf (es darf KEIN Eintrag entstanden sein) =="
|
||||
bin/kc-status
|
||||
|
||||
echo "== Restore =="
|
||||
bin/kc-restore
|
||||
rm "$HOME/.ssh/claude-keychain-backup.json"
|
||||
bin/kc-status
|
||||
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,19 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1024" height="1024">
|
||||
<defs>
|
||||
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#2b2b2f"/>
|
||||
<stop offset="1" stop-color="#161618"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="txt" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#ffffff"/>
|
||||
<stop offset="1" stop-color="#d6d6d9"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="1024" height="1024" rx="224" fill="url(#bg)"/>
|
||||
<rect x="40" y="40" width="944" height="944" rx="192" fill="none"
|
||||
stroke="#ffffff" stroke-opacity="0.14" stroke-width="3"/>
|
||||
<text x="512" y="650" text-anchor="middle"
|
||||
font-family="Didot, 'Bodoni 72', Georgia, serif"
|
||||
font-size="400" letter-spacing="14"
|
||||
fill="url(#txt)">aIC</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 839 B |
@@ -0,0 +1,8 @@
|
||||
# Memory Index
|
||||
|
||||
- [Go-Pflicht](feedback-go-pflicht.md) — weitreichende Änderungen nie ohne ausdrückliches Go; eine Rückfrage von Marcus ist kein Go (Vorfall 2026-07-04)
|
||||
- [Terminal-Tests mit 08-07](feedback-terminal-test-08-07.md) — ABSOLUTES VERBOT: nie ein Terminal für/aus ai-control starten (killt die eigene Session, 3× Kontext verloren am 2026-07-04). Terminal-Tests nur mit 08-07 und nur auf ausdrückliche Ansage
|
||||
|
||||
- [Multi-Account & Keychain](multi-account-keychain.md) — Stand 2.1.199: suffixierter Keychain-Eintrag pro Config-Dir verifiziert; Pools umbenannt, Keychain-Endstand ein Eintrag 096c4ef9 (privateDefault); Kaltstart über Starter läuft (2026-07-04), Qualität laut Marcus noch nicht zufriedenstellend
|
||||
- [Pool-Setup Stand](ai-control-pool-setup.md) — Layout ~/.config/ai-control (pools, projects.json-Registry, icons, settings.json mit claudeCommand); eingebautes Terminal + Tray mit Statuspunkten; Stand 2026-07-05 GitHub-reif (README en, MIT, Screenshots); Deploy braucht lsregister
|
||||
- [Linux-Umzug](linux-umzug.md) — ab 2026-07-05 laufen die Sessions auf der Linux-Box; Start per start-claude.sh (Einzeiler, Pool private); macOS-Code muss noch hinter cfg(target_os)
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
name: ai-control-pool-setup
|
||||
description: "Stand des Pool-Setups seit 2026-07-03 — Layout, Starter, was gelöscht wurde, offene Punkte"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: e108ad75-f176-43b6-901d-c3ec19ec3961
|
||||
---
|
||||
|
||||
Seit 2026-07-03 produktiv:
|
||||
|
||||
- Pools: `~/.config/ai-control/pools/<pool>/` = CLAUDE_CONFIG_DIR. `pool.json` (name, credentialType), oauth: `.credentials.json`, apikey: `apikey` + `apiKeyHelper` in pool-`settings.json`. Pools (umbenannt 2026-07-03 abends): privateDefault (vorher Mx9Privat; oauth), apiDefault (vorher TestWürth; apikey — 2026-07-03 kurz auf oauth, am selben Tag zurück auf apikey via `apiKeyHelper` in Pool-settings.json; model claude-sonnet-5). Alle 7 Projekte → privateDefault; apiDefault derzeit ohne Projekt. Pool-Wechsel eines Projekts = nur noch `ai-control.json` ändern (einzige Quelle; zieht beim nächsten Start). Pool-Umbenennung ändert den Pfad und damit den Keychain-Suffix — alte Einträge greifen dann nicht mehr.
|
||||
- `CLAUDE.md`, `commands/`, `settings.json` liegen als physische Kopien in jedem Pool — bewusst poolspezifisch, keine Symlinks.
|
||||
- Zuordnung: `~/claude-projects/<projekt>/ai-control.json` `{ "pool": ... }`.
|
||||
- Starter: `~/Applications/Ghostty-<projekt>.app`, `LSEnvironment` setzt nur noch XDG_CONFIG_HOME (stabil, nie poolabhängig). Alle Ghostty-Configs starten `command = ~/.local/bin/claude-sync` (ggf. mit `--add-dir`-Args). `claude-sync` löst seit 2026-07-04 den Pool selbst auf (liest `./ai-control.json` im CWD, exportiert `CLAUDE_CONFIG_DIR`, laut scheiternd ohne Pool), macht git pull davor und commit+push danach. `claude-start` ist gelöscht — in `claude-sync` integriert. Env/plist tragen keinen Pool mehr.
|
||||
- Pool-Guard (seit 2026-07-04): `claude-sync` schreibt Sentinel `.ai-control-running` in den Projekt-Root (Inhalt pool=CLAUDE_CONFIG_DIR, pid; FD offen gehalten, nach claude-Ende gelöscht, in .gitignore). Vorab-Check (Endstand 2026-07-03 spät): Fensterzahl statt Prozesszustand, ohne Apple-Events — `ghostty-wincount <app-pid>` (Swift-Helfer, CGWindowListCopyWindowInfo onScreenOnly + Layer 0; Binary `~/.local/bin/ghostty-wincount`, Quelle `~/claude-projects/robotunits/bin/ghostty-wincount.swift`; App-pid via ps+grep auf den App-Pfad). Das Skript läuft selbst in Fenster 1; ≥2 → Arbeitsfenster existiert → `open -a` (Launch Services, kein Prompt) + 4 s + Exit 0; sonst → Sentinel-pid und FD-Holder kill -9, Sentinel kommentarlos löschen, normal starten. Gescheiterte Vorstufen: tty-Heuristik (Zombie behält totes tty), Schreiber-PID-Check (claude-sync-Bash überlebt Ghosttys X-Close manchmal kopflos), osascript count/activate (Automation-Prompt „App X will App Y steuern" = NOGO). Bekannte Grenze: minimierte/Space-fremde Fenster zählen als unsichtbar. Traps in claude-sync: EXIT löscht Sentinel, HUP/TERM killt claude (claude läuft als Hintergrund-Kind mit `<&0` — sonst stdin=/dev/null! — und `wait`), INT no-op; greifen aber bei Ghostty-X/Quit oft nicht (hartes Kill), Rest-Aufräumen beim nächsten Start ist der Normalfall. Alle 7 Ghostty-Configs (`~/.config-ghostty/<projekt>/ghostty/config`): `wait-after-command = false`; claude-sync zeigt Schlussmeldungen per sleep (2 s aktivieren, 3 s Ende, 5 s Fehler), dann schließt das Fenster selbst. SessionStart-Hook `~/claude-projects/robotunits/bin/pool-guard` in allen 7 Projekt-settings.json: Sentinel fehlt / Pool-Mismatch / Schreiber-PID tot → rot blinkender Banner auf /dev/tty + kill des claude-Elternprozesses. RAW-Nutzung außerhalb der Projekte bleibt frei; RAW-Start IM Projekt wird beendet. Achtung: greift auch bei /clear in Sessions, die noch ohne Sentinel gestartet wurden.
|
||||
- Gelöscht: `~/.claude` (komplett), Keychain-Eintrag `Claude Code-credentials`, `~/claude-pools`. Unterhaltungen (90 MB) + `history.jsonl` nach Mx9Privat umgezogen — `/resume` pro Pool.
|
||||
- App-Code (`~/projects/ai-control`, Tauri): Kernlogik mit injizierbarem Home, 22 Tests (`./build.sh`-Toolchain: CARGO_HOME=~/tools/.cargo; node via fnm, nur in interaktiver zsh). Commands unassign_pool/create_project/delete_project, seit 2026-07-04 restart_project (osascript-Quit → warten → open) + Modal in ProjectList: nach Umhängen eines laufenden Projekts Restart-Angebot inkl. Hinweis, dass der claude-sync-Push beim Abschießen entfällt.
|
||||
- Eingebautes Terminal (2026-07-04, Prototyp, funktioniert laut Marcus): `src-tauri/src/terminal.rs` (portable-pty, Commands open_terminal/term_start/term_write/term_resize) + `terminal.html`/`src/terminal.ts` (xterm.js, Output base64-Events, Capability `term-*`). „Terminal"-Button in ProjectList öffnet pro Klick ein eigenes Fenster; PTY startet `zsh -ic claude-sync` im Projektordner — Pool/Sentinel/git-Sync unverändert bei claude-sync, App setzt kein CLAUDE_CONFIG_DIR. Fenster-X killt Kind + schließt PTY (HUP wie Ghostty-X, Abschluss-Push entfällt). Damit Weg frei, die Ghostty-Starter abzulösen ("wir haben alles in der Hand"). Offen: Scrollback-Restore, Fensterposition merken.
|
||||
- Stand 2026-07-04 abends, alles committed+gepusht (bis inkl. Todo-Feature): UI komplett auf Catppuccin-Mocha-Token + JetBrains Mono (frontend-design-Skill; Plugin `frontend-design` war kaputt — installPaths in installed_plugins.json zeigten nach Pool-Umbenennung noch auf Mx9Privat, gefixt), i18n de/en (vue-i18n, Umschalter im Header). Pools: löschbar mit Zuordnungs-Auflösung, „Neu anmelden" löscht vorher den suffixierten Keychain-Eintrag (nur bei ungenutztem Pool, Warn-Dialog), Renew entfernt (Datei-Refresh-Token tot, Keychain hat Vorrang), hasCredentials (apikey-Dateicheck) mit Start-Blockierung. Verbrauch-Tab: usage_stats parst <pool>/projects/*/*.jsonl (Dedup message.id+requestId, Preistabelle Fable 10/50 Opus 5/25 Sonnet 3/15 Haiku 1/5, Cache 1.25x/0.1x), Pool-Zeilen aggregiert + Projekte aufklappbar; apiDefault hat keinerlei Transcripts (Marcus' apiKey-Abfragen vom 04.07. liefen nachweislich nicht über claude-code auf diesem Rechner — Console zeigt die Wahrheit). Projekt-Wizard (create_project_full: Scaffold nach 08-07-Muster inkl. pool-guard-Hook, Arbeitsordner anlegen/verknüpfen) + Löschen (Guard bei laufender Session, optional Arbeitsordner aus additionalDirectories mit). Todo-Feature nur Projektebene (robotunits-Muster: OFFENE-PUNKTE.md + jq-SessionStart-Hook, zuschaltbar in Wizard+Zahnrad; Pool-Ebene bewusst nicht). App heißt ai-control (Cargo-Paket umbenannt), Hand-Icon (Tray per include_bytes + Template-Icon; Dock-Icon der Terminals via NSApplication nur in RunEvent::Ready). 38 Rust-Tests. Offen/geplant: Baustein-Bibliothek (CLAUDE.md-Marker-Mechanismus, Konzept steht: ~/.config/ai-control/blocks/, verwaltete Abschnitte zwischen ai-control:block-Markern), weitere Wizard-Optionen, Split privates Repo / offizielles GitHub-Repo (Ist-Stand als Initial-Commit ohne History; OAuth-Login-Teil wegen ToS-Grauzone fürs öffentliche Repo rausnehmen — apiKey-Teil unkritisch), Vitest für UI-Tests (Vorschlag steht), Dock-Name macOS/Wayland „später überlegen".
|
||||
- Alter Zwischenstand (Commit f747379 = Terminal + Start/Beenden-Button): (a) ProjectList: ein Button pro Zeile — grün „Starten" (open_terminal) / rot „Beenden" (neues Command stop_project: SIGTERM auf exakte PIDs per `pgrep -f -- "--terminal <projekt>$"`, sonst Ghostty-Quit; NIE Quit über die App-Bundle-ID — träfe die Haupt-App); is_running = Ghostty ODER --terminal-Prozess; Status-Kreis ohne Prozess unsichtbar. (b) Terminal-Config-Dialog (Zahnrad): `terminal: { theme, icon, title }` in projekt-`ai-control.json` (pool-Feld jetzt Option, Datei bleibt bei unassign wenn terminal gesetzt); 5 Themes (mocha/dracula/solarized-dark/gruvbox/one-dark, Paletten in terminal.ts, Fenster-BG gespiegelt in terminal.rs theme_background — muss synchron bleiben); Icon = PNG/ICNS-Pfad via tauri-plugin-dialog-Picker, gesetzt per NSApplication.applicationIconImage (objc2, nur in RunEvent::Ready — in setup() überschreibt macOS es wieder); Titel: Fenstertitel + Header, leer → Projektname. `tauri::generate_context!` darf nur 1× expandieren (_EMBED_INFO_PLIST, fällt nur im Release-Build auf).
|
||||
- Dock-Grenze macOS: Hover-Label im Dock = Bundle-Name, zur Laufzeit nicht öffentlich änderbar; Wrapper-Bundle pro Projekt von Marcus abgelehnt („verlieren zu viel"). Windows/X11: Titel+Icon greifen fensterbasiert; Wayland-Docks bräuchten .desktop pro Projekt (xdg-toplevel-icon nur KDE). → „da müssen wir was überlegen, nicht jetzt".
|
||||
|
||||
Frische Pools zeigen Promo-/Upsell-Banner („Werbung"), privateDefault nicht — Ursache ungeklärt (Stand 2026-07-04, nicht weiter vertiefen): Hochsetzen der Zähler in der Pool-`.claude.json` (`tipsHistory.fable-5-promo-2`, `passesUpsellSeenCount`) half nicht, ebenso wenig `cachedGrowthBookFeatures.tengu_birch_lantern = "off"` (einziger Flag-Unterschied der Pools). Kein Settings-Switch vorhanden.
|
||||
|
||||
**Stand 2026-07-05 (Session GitHub-Release, alles committed bis 0ebdaf0):**
|
||||
- **Projekt-Registry statt festem Root:** `~/.config/ai-control/projects.json` (Name → Pfad, Home-Pfade ~-kontrahiert), Alt-Layout-Scan komplett entfernt — ohne Registry keine Projekte. Marcus' 7 Projekte migriert. Neue Commands add_project (Import bestehender Ordner, UI „Projekt importieren …"), remove_project (nur Eintrag), set_project_dir (Root im ⚙︎-Dialog änderbar; schreibt autoMemoryDirectory + Edit-Permission um). Arbeitsordner nachträglich im ⚙︎-Dialog erfassbar/entfernbar (additionalDirectories + Edit-Permission, ~-kontrahiert).
|
||||
- **Icons zentral:** `~/.config/ai-control/icons/<projekt>.<ext>` (NICHT Pool — Marcus' Entscheidung: gemeinsames Resourcen-Verzeichnis, kein Umzug bei Pool-Wechsel, nichts im Quell-Repo). Alle 7 Projekte migriert. Nicht ladbares Icon crasht den Tray nicht mehr (eprintln + Eintrag ohne Icon; vorher Crash-Ursache: gelöschtes icon.png).
|
||||
- **Terminal:** `claudeCommand` in App-settings.json (Default `claude`; bei Marcus `claude-sync`), App setzt CLAUDE_CONFIG_DIR aus dem Projekt-Pool selbst. Terminal-Fenster aktiviert sich beim Öffnen (Starter yieldActivationToApplicationWithBundleIdentifier + activate im Ready-Event — Aktivierung seit macOS 14 kooperativ, sonst Pop-under). Tray-Menü listet Projekte mit Icon + grünem Statuspunkt (56×36-RGBA im Icon-Slot, muda skaliert auf 18 pt); Klick startet bzw. fokussiert (NSRunningApplication über PID).
|
||||
- **Session-Sync:** Watcher synct per Projekt das umgebende Git-Repo (add/commit/pull --rebase/push inline), git-sync-Skript-Kopplung raus.
|
||||
- **GitHub-reif:** README englisch mit Screenshots (docs/), MIT-Lizenz, Anthropic-Lizenz-Hinweis (reine Pool-Verwaltung, OAuth-Login macht claude selbst). Deploy-Falle: nach rm -rf+cp nach ~/Applications `lsregister -f` nötig, sonst „App weg" in Spotlight.
|
||||
- 51 Rust-Tests. Zwischenfall: Commit im falschen Repo (Shell-cwd springt auf ~/claude-projects/ai-control zurück — bei git-Befehlen immer explizit cd ~/projects/ai-control), per amend+force-with-lease bereinigt.
|
||||
- **Veröffentlicht 2026-07-05:** github.com/mHinz-hub/ai-control — main = Squash-Commit ohne History (Gitea behält volle History; Remote `github` im App-Repo, HTTPS mit Fine-grained-PAT im macOS-Keychain; SSH-Key des Rechners gehört zum Arbeits-Account ex08802409_wdp, NICHT für mHinz-hub nutzbar). Tag v0.1.0 + Release mit DMG-Asset (build.sh baut app+dmg; CI=true wegen TCC). FUNDING.yml → buymeacoffee.com/marcusH. `poolSyncDir` in settings.json steuert Pool-Runtime-Verlinkung (bei Marcus ~/claude-projects/pool; ungesetzt = lokal). Release-Flow künftig: Gitea entwickeln → `git commit-tree` Squash → force-push github main → Tag → DMG via API hochladen.
|
||||
|
||||
**Agenda 2026-07-05 (alt):** Sync-Test auf neuem Mac (pool-Repo mit Symlink-Runtime: clonen, `link-pool-runtime` bzw. Pool-Anlage über die App, /resume-Übernahme prüfen).
|
||||
|
||||
**Why:** Getrennte Zugänge pro Pool, [[multi-account-keychain]].
|
||||
|
||||
**Agenda 2026-07-04:** Start/Stopp-Architektur grundsätzlich besprechen — Stand vom 2026-07-03 spät (wincount/kill-9/Sentinel-Reste) funktioniert im Test, ist aber Flickwerk um Ghosttys unzuverlässiges Kill-Verhalten herum; Marcus will eine saubere Lösung statt Workarounds. Außerdem: Pool-Guard + Kaltstart über Starter testen; App: UI aufräumen, Projekte managen, Defaults/Standardverhalten (z. B. Todolist); Linux gesondert; Open-Source-Frage („works for my workflow") entschieden nach Feinschliff; außerdem Ghostty und Zed besprechen. Stand App: beta-0.8 gepusht (Tray statt Dock, Autostart-Schalter, Fenster startet unsichtbar, Restart-Dialog).
|
||||
|
||||
**How to apply — offen (Stand 2026-07-03):** (1) Sync-Konzept für `~/.config/ai-control` inkl. Unterhaltungen, Secrets-Frage (git). (2) UI kennt die drei neuen Commands nicht. (3) Erledigt durch Integration in `claude-sync` (2026-07-04): der „Flicker" betraf das gelöschte `claude-start`; `claude-sync` läuft in den Ghostty-Wrappern nachweislich interaktiv.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: erklaerungen-frage-getrieben
|
||||
description: "Erklärthemen (auch \"für Dumme\"-Punkte) nie als Vortrag, sondern kurz und frage-getrieben"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: feedback
|
||||
originSessionId: 40d78c29-a103-4420-b913-4d49b26def7a
|
||||
---
|
||||
|
||||
Marcus will sich durch Erklärthemen selbst durchfragen (Vorfall 2026-07-05, Vertex-Aufklärung: langer Vortrag kam schlecht an).
|
||||
|
||||
**Why:** Auch wenn ein offener Punkt "von Grund auf erklären" sagt, heißt das nicht Monolog — er steuert per Fragen, Antworten knapp, keine Wiederholungen, ihn nicht für ahnungslos halten.
|
||||
|
||||
**How to apply:** Bei Aufklärungs-/Lernthemen: kurzer Einstieg (wenige Sätze oder kompakte Tabelle), dann auf seine Fragen antworten. Nur exakt das Gefragte.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: feedback-go-pflicht
|
||||
description: Weitreichende Änderungen NIE ohne ausdrückliches Go; eine Rückfrage von Marcus ist kein Go
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: feedback
|
||||
originSessionId: 6c3fc02d-bc5c-4476-9384-8062394a85ff
|
||||
---
|
||||
|
||||
Weitreichende Änderungen (Verhaltensänderungen im Backend, Löschlogik, alles mit Datenverlust-Potenzial) nie umsetzen, bevor Marcus ausdrücklich Go gegeben hat. Eine Rückfrage oder Diskussionsfrage von Marcus („was machen wir dann mit X?") ist KEIN Go — Frage beantworten, dann stoppen und warten.
|
||||
|
||||
**Why:** 2026-07-04: Nach Marcus' Rückfrage zur Pool-Löschung habe ich direkt implementiert; Marcus hat abgebrochen („ICH HATTE NICHT GESAGT, DASS DU DAS TUN SOLLST"). Sein „ja" galt dem Plan davor, seine Folgefrage hat die Diskussion wieder geöffnet.
|
||||
|
||||
**How to apply:** Bei jedem Plan mit offener Designfrage: erst alle offenen Punkte klären, dann explizites Go für den Gesamtumfang abwarten. Antwort auf eine Frage endet mit der Antwort, nicht mit Tool-Calls.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: feedback-terminal-test-08-07
|
||||
description: "Terminal-/Restart-Tests der App immer mit Projekt 08-07, nie mit ai-control"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: feedback
|
||||
originSessionId: dd1d2798-9e9a-4e95-bf63-7793e7801020
|
||||
---
|
||||
|
||||
Für Tests des eingebauten Terminals und von restart_project immer das Projekt **08-07** als Beispiel nehmen, nie **ai-control**.
|
||||
|
||||
**Why:** Die Arbeitssession läuft selbst im Projekt ai-control — ein Terminal-/Restart-Test dort killt die eigene Session und der Kontext ist weg.
|
||||
|
||||
**How to apply:** In Testanweisungen, Beispielaufrufen und UI-Tests (`open_terminal`, `restart_project`) als Projektname `08-07` verwenden. Siehe [[ai-control-pool-setup]].
|
||||
|
||||
**Stand 2026-07-04:** Die Session läuft selbst im eingebauten Terminal der App (xterm.js + portable-pty). Ein Neustart/Beenden der App killt die Session direkt — die 08-07-Regel schützt nur gegen `restart_project ai-control`, nicht gegen Tests auf App-Ebene.
|
||||
|
||||
**Verschärfung (2026-07-04, nach erneutem Vorfall):** Alles, was den App-Prozess oder das eigene Terminal berührt, ist tabu — App-Neustart, App-Build+Relaunch, Kill von Electron-/pty-Prozessen, `pkill`/`kill` auf Prozesse, deren Zugehörigkeit nicht geprüft ist. Vor jedem Kill/Restart erst prüfen, ob der Zielprozess in der eigenen Prozesskette hängt. Solche Tests laufen nur nach Ansage von Marcus und dann in 08-07 bzw. einer separaten App-Instanz.
|
||||
|
||||
**Absolutes Verbot (2026-07-04, dritter Vorfall — Kontext erneut verloren):** NIE ein Terminal für oder aus ai-control starten — kein `open_terminal ai-control`, kein Terminal-Start über die App, keine Ausnahme „nur kurz testen". Jeder Terminal-Start, der ai-control betrifft, killt diese Session. Terminal-Funktionen werden ausschließlich mit 08-07 getestet, und nur wenn Marcus es ausdrücklich anweist.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: feedback-warum-ist-keine-suchlizenz
|
||||
description: "Auch eine dringliche 'warum'-Frage ist keine Erlaubnis zum Suchen/Ausführen — nur aus Wissen/Memory beantworten, sonst 'weiß ich nicht' sagen"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: feedback
|
||||
originSessionId: 9ca637e1-89b8-4a5f-beaf-f2eab81d2302
|
||||
---
|
||||
|
||||
Wenn Marcus "warum" fragt (auch wiederholt, auch in Großbuchstaben/dringlich), ist das KEINE explizite Suchanweisung. Die Regel „nur suchen, wenn ausdrücklich angewiesen" gilt unverändert — eine Faktenfrage wird aus vorhandenem Wissen/Memory beantwortet, nicht durch Bash/Grep/Read „belegt".
|
||||
|
||||
**Why:** Vorfall 2026-07-04 — auf wiederholtes "WARUM" habe ich eigenmächtig `cat`/`ls`/env-Check ausgeführt, obwohl [[feedback-go-pflicht]] und die globale Suchregel das explizit verbieten. Marcus hat den Tool-Call abgelehnt und auf den „Vertrag" verwiesen. Dringlichkeit/Großschreibung der Frage ändert nichts an der Erlaubnis.
|
||||
|
||||
**How to apply:** Bei „warum"-Fragen ohne explizites „such nach…", „schau nach…", „prüf…": nur aus bereits geladenem Kontext/Memory antworten, notfalls „weiß ich nicht ohne nachzuschauen" sagen — nicht eigenständig Bash/Read/Grep/Agent starten, egal wie dringlich die Frage klingt.
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: linux-umzug
|
||||
description: ai-control soll unter Linux laufen; Sessions laufen ab 2026-07-05 auf der Linux-Box weiter
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: 7fa72046-ab7a-4b41-a496-f0f6b9a4729d
|
||||
---
|
||||
|
||||
Stand 2026-07-05: Marcus testet ai-control auf seiner Linux-Box und will die Arbeit dort fortsetzen — die Mac-Session wurde dafür beendet. Linux- und Windows-Integration sind im README bereits angekündigt.
|
||||
|
||||
**Wie gestartet wird:** `~/claude-projects/ai-control/start-claude.sh` — bewusst nur ein Einzeiler: `cd` ins Skriptverzeichnis, `CLAUDE_CONFIG_DIR=~/.config/ai-control/pools/private`, `exec claude`. Die Pfade sind auf beiden Maschinen identisch (`~`-relativ), der Transport läuft über den claude-projects-Git-Sync (Gitea).
|
||||
|
||||
**Gescheitert und verworfen:** ein parametrisiertes Setup-/Startskript-Paar (setup-config.sh legte nur ein leeres Skelett an statt die echte Config zu migrieren; start-claude.sh verlangte einen Projektnamen). Marcus wollte genau dieses eine Projekt und keine zusätzliche Konfiguration pro Maschine. Lehre: [[feedback-go-pflicht]] — erst das Minimalste bauen, das er wörtlich beschreibt.
|
||||
|
||||
**Offen für Linux:** macOS-spezifischer Code in der App (objc2-Aktivierung, sips-Icons, Tray) muss hinter `cfg(target_os)`; Build mit webkit2gtk/AppIndicator ungetestet. Siehe [[ai-control-pool-setup]].
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: multi-account-keychain
|
||||
description: "Multi-Account auf macOS — Stand 2.1.199: pro CLAUDE_CONFIG_DIR eigener suffixierter Keychain-Eintrag; .credentials.json-Ansatz überholt"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: e108ad75-f176-43b6-901d-c3ec19ec3961
|
||||
---
|
||||
|
||||
ÜBERHOLT (galt bis Version vor 2.1.199): claude las die `.credentials.json` direkt aus `CLAUDE_CONFIG_DIR` (verifiziert 2026-07-03 vormittags, Test `bin/oauth-configdir-test`).
|
||||
|
||||
Stand 2026-07-03 abends, Version 2.1.199 (native Installation): Neu-Login war nötig. Die `.credentials.json` im Pool `Mx9Privat` ist weg; claude speichert jetzt pro Config-Dir einen Keychain-Eintrag `Claude Code-credentials-<suffix>`, Suffix = erste 8 Hex-Zeichen von SHA-256 über den `CLAUDE_CONFIG_DIR`-Pfad (Mx9Privat → `a014e206`, TestWürth → erwartet `4c0ad9a9`, ggf. NFC/NFD-Frage wegen „ü"). Ohne gesetztes `CLAUDE_CONFIG_DIR` entsteht der unsuffixierte Eintrag `Claude Code-credentials` plus `~/.claude`/`~/.claude.json`. Damit ist #20553 (Überschreiben) upstream gelöst — pro Pool ein eigener Eintrag. Verifiziert 2026-07-03 abends: Nach `/login` in ai-control (Mx9Privat) lief wuerth-plato (gleicher Pool) ohne erneutes Login — Eintrag `a014e206` wird poolweit geteilt. Keychain enthielt danach nur diesen einen Claude-Code-Eintrag (kein unsuffixierter). Zweiter Pool ebenfalls verifiziert: 08-07 (TestWürth, oauth) verlangte wie erwartet erneutes Login und erzeugte `Claude Code-credentials-4c0ad9a9` — Suffix stimmt mit der Vorab-Berechnung überein, NFC/NFD-Frage wegen „ü" damit geklärt. Keychain-Stand: genau zwei Einträge, `a014e206` (Mx9Privat) und `4c0ad9a9` (TestWürth). Multi-Account über suffixierte Keychain-Einträge funktioniert damit vollständig. Dritter Beleg: robotunits nach Umzug auf TestWürth ohne Login gestartet (Starter-Pfad hasht identisch auf `4c0ad9a9`). Mit gesetztem `CLAUDE_CONFIG_DIR` entsteht dabei kein neues `~/.claude` im Home — das gelöschte bleibt weg.
|
||||
|
||||
Umbenennung 2026-07-03 spätabends: Mx9Privat → privateDefault, TestWürth → apiDefault. Suffixe: privateDefault → `096c4ef9`, apiDefault → `15e10251`. Die alten Einträge `a014e206`/`4c0ad9a9` wurden gelöscht; kurz darauf lag `096c4ef9` im Keychain — eine laufende Session hat die Credentials unter dem neuen Pfad selbst neu geschrieben, ohne Login-Prompt. Weitere Session-Starts erzeugten keinen zusätzlichen Eintrag. Keychain-Endstand 2026-07-03: genau ein Eintrag `096c4ef9`; für apiDefault (`15e10251`) existiert noch keiner, dort ist beim ersten Start Login nötig.
|
||||
|
||||
Kaltstart-Test über die umgestellten Starter (2026-07-04): durchgeführt, funktioniert grundsätzlich (kein Login nötig), aber laut Marcus nicht in der gewünschten Qualität — worin genau der Mangel liegt, ist noch nicht festgehalten.
|
||||
|
||||
Umbenennung 2026-07-05: privateDefault → private (Runtime-Ordner, Repo-Ordner, Symlinks, alle 7 Projekt-ai-control.json). Neuer Suffix `485a513f`, von der laufenden Session ohne Login selbst geschrieben; `096c4ef9` gelöscht. Im Keychain liegen daneben vier ungeklärte Einträge (54743385, 550a1032, b425db93, dfbfcf1a), keinem Pool zugeordnet — vermutlich Test-Reste.
|
||||
|
||||
**Why:** Mehrere Claude-Zugänge (Abo + Kunden-Keys) strikt getrennt auf einem Rechner.
|
||||
|
||||
**How to apply:** Pro Pool ein Ordner als `CLAUDE_CONFIG_DIR` (siehe [[ai-control-pool-setup]]). OAuth: `.credentials.json` (0600) in den Pool-Ordner. API-Key: `apiKeyHelper` in der Pool-`settings.json` auf die Key-Datei. `CLAUDE_CODE_OAUTH_TOKEN`-Export ist unnötig.
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# migrate-linux.sh — richtet ~/.config/ai-control auf dieser Maschine so ein,
|
||||
# wie es auf dem Mac für das Projekt ai-control steht (übrige Projekte später).
|
||||
# Quelle ist das synced Repo ~/claude-projects/pool (CLAUDE.md, settings.json,
|
||||
# commands, Runtime) — deshalb: erst pullen, dann ausführen.
|
||||
# Überschreibt vorhandene Config; lokale Test-Sessions im Pool werden verworfen.
|
||||
set -euo pipefail
|
||||
|
||||
config="$HOME/.config/ai-control"
|
||||
poolrepo="$HOME/claude-projects/pool"
|
||||
pooldir="$config/pools/private"
|
||||
|
||||
mkdir -p "$pooldir"
|
||||
|
||||
# Projekt-Icons liegen im synced Repo; unter .config nur ein Symlink
|
||||
if [ -d "$config/icons" ] && [ ! -L "$config/icons" ]; then rm -rf "$config/icons"; fi
|
||||
ln -sfn "$poolrepo/icons" "$config/icons"
|
||||
|
||||
# App-Settings — wie auf dem Mac
|
||||
cat > "$config/settings.json" <<'EOF'
|
||||
{
|
||||
"claudeCommand": "claude-sync",
|
||||
"poolSyncDir": "~/claude-projects/pool"
|
||||
}
|
||||
EOF
|
||||
|
||||
# Registry: erst mal nur ai-control
|
||||
cat > "$config/projects.json" <<'EOF'
|
||||
{
|
||||
"ai-control": "~/claude-projects/ai-control"
|
||||
}
|
||||
EOF
|
||||
|
||||
# Pool private: Identität + User-Scope aus dem synced Repo
|
||||
cat > "$pooldir/pool.json" <<'EOF'
|
||||
{
|
||||
"name": "private",
|
||||
"credentialType": "oauth"
|
||||
}
|
||||
EOF
|
||||
cp "$poolrepo/settings.json" "$pooldir/settings.json"
|
||||
cp "$poolrepo/CLAUDE.md" "$pooldir/CLAUDE.md"
|
||||
rm -rf "$pooldir/commands"
|
||||
cp -R "$poolrepo/commands" "$pooldir/commands"
|
||||
|
||||
# Runtime (projects/todos/history.jsonl) aufs synced Repo verlinken —
|
||||
# damit funktionieren Resume und History maschinenübergreifend
|
||||
"$poolrepo/bin/link-pool-runtime" private
|
||||
|
||||
echo "migriert: $config (Projekt ai-control, Pool private)"
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bereitet ~/.config/ai-control auf einer frischen Maschine vor — dasselbe
|
||||
# Layout, das die App anlegt:
|
||||
# settings.json App-Settings (claudeCommand; poolSyncDir ungesetzt = lokal)
|
||||
# projects.json Projekt-Registry (Name -> Pfad, ~-relativ)
|
||||
# icons/ gemeinsames Icon-Verzeichnis
|
||||
# pools/<pool>/ oauth-Pool: pool.json, settings.json, CLAUDE.md
|
||||
# Vorhandene Dateien bleiben unangetastet.
|
||||
#
|
||||
# Aufruf: setup-config.sh [pool-id] (Default: private)
|
||||
set -euo pipefail
|
||||
|
||||
pool="${1:-private}"
|
||||
config="$HOME/.config/ai-control"
|
||||
pooldir="$config/pools/$pool"
|
||||
|
||||
mkdir -p "$config/icons" "$pooldir"
|
||||
|
||||
[ -f "$config/settings.json" ] || cat > "$config/settings.json" <<'EOF'
|
||||
{
|
||||
"claudeCommand": "claude"
|
||||
}
|
||||
EOF
|
||||
|
||||
[ -f "$config/projects.json" ] || echo '{}' > "$config/projects.json"
|
||||
|
||||
[ -f "$pooldir/pool.json" ] || cat > "$pooldir/pool.json" <<EOF
|
||||
{
|
||||
"name": "$pool",
|
||||
"credentialType": "oauth"
|
||||
}
|
||||
EOF
|
||||
|
||||
# UI-Defaults wie init_pool_config: Prompt-Vorschläge/Away-Summary aus
|
||||
[ -f "$pooldir/settings.json" ] || cat > "$pooldir/settings.json" <<'EOF'
|
||||
{
|
||||
"promptSuggestionEnabled": false,
|
||||
"awaySummaryEnabled": false
|
||||
}
|
||||
EOF
|
||||
|
||||
[ -f "$pooldir/CLAUDE.md" ] || : > "$pooldir/CLAUDE.md"
|
||||
|
||||
echo "fertig: $config (Pool: $pool)"
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
cd "$(dirname "$0")"
|
||||
CLAUDE_CONFIG_DIR=~/.config/ai-control/pools/private exec claude
|
||||