kimal3 0.4.0-durchstich.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +6 -0
  2. package/claude-plugins/.claude-plugin/marketplace.json +8 -8
  3. package/claude-plugins/README.md +7 -7
  4. package/claude-plugins/kimal3-logo/.claude-plugin/plugin.json +6 -6
  5. package/claude-plugins/kimal3-logo/hooks/hooks.json +1 -1
  6. package/claude-plugins/kimal3-logo/hooks/register.tsx +80 -80
  7. package/coach/de/kimal3-coach.md +167 -0
  8. package/coach/en/kimal3-coach.md +167 -0
  9. package/dist/arbeitsplatz-dateien.js +1 -1
  10. package/dist/arbeitsplatz-finden.js +115 -0
  11. package/dist/arbeitsplatz-suche.js +176 -0
  12. package/dist/befehle/einrichten.js +250 -32
  13. package/dist/befehle/kurs.js +77 -0
  14. package/dist/befehle/login.js +12 -1
  15. package/dist/befehle/skill-install.js +15 -0
  16. package/dist/befehle/zeigen-einrichten.js +104 -0
  17. package/dist/befehle/zeigen-start.js +143 -0
  18. package/dist/befehle/zeigen.js +288 -0
  19. package/dist/befehle-katalog-en.js +39 -0
  20. package/dist/befehle-katalog.js +39 -0
  21. package/dist/befehlswoerter.js +15 -0
  22. package/dist/coach-ablegen.js +130 -0
  23. package/dist/coach-rechnung.js +40 -0
  24. package/dist/kimal3.js +14 -2
  25. package/dist/logo-ablegen.js +26 -6
  26. package/dist/slash-befehle.js +1 -0
  27. package/dist/texte/coach.js +27 -0
  28. package/dist/texte/einrichten-marken.js +2 -2
  29. package/dist/texte/einrichten.js +58 -5
  30. package/dist/texte/kurs.js +21 -0
  31. package/dist/texte/zeigen.js +189 -0
  32. package/dist/zeigen-rechnung.js +226 -0
  33. package/dist/zeigen-umgebung.js +190 -0
  34. package/package.json +3 -1
  35. package/skill/SKILL.md +10 -5
  36. package/skill/commands/k3.md +4 -3
  37. package/skill/commands/k3feierabend.md +2 -3
  38. package/skill/commands/k3kurs.md +27 -39
  39. package/skill/commands/k3start.md +4 -3
  40. package/skill/commands/k3zeigen.md +303 -0
  41. package/skill/en/SKILL.md +10 -5
  42. package/skill/en/commands/k3.md +4 -3
  43. package/skill/en/commands/k3course.md +27 -40
  44. package/skill/en/commands/k3show.md +302 -0
  45. package/skill/en/commands/k3start.md +4 -3
  46. package/skill/en/commands/k3wrapup.md +3 -4
  47. package/zeigen/gemeinsam.py +82 -0
  48. package/zeigen/starter.py +163 -0
  49. package/zeigen/werkzeug.py +250 -0
  50. package/zeigen/zeitleiste.py +393 -0
@@ -118,6 +118,18 @@ export const BEFEHLE_EN = {
118
118
  "What it's really for: Claude looks here BEFORE adding a project. Without that check, the same project would sooner or later appear twice on a public page that carries your name.",
119
119
  ],
120
120
  },
121
+ "kimal3 kurs": {
122
+ stempel: "3a5c7600",
123
+ befehl: "kimal3 course",
124
+ tippen: "/k3course",
125
+ terminal: "kimal3 course",
126
+ beschreibung: "Show where you are in the mini-course",
127
+ rhythmusOderSatz: "where am I in the course",
128
+ details: [
129
+ "Shows which parts you have finished, what is next and what is still open — and for each step whether you tick it off or Claude sets it.",
130
+ "Claude reads this when you come back to the course and picks up exactly where you left off.",
131
+ ],
132
+ },
121
133
  "kimal3 firma daten": {
122
134
  stempel: "3195364c",
123
135
  befehl: "kimal3 company data",
@@ -131,6 +143,33 @@ export const BEFEHLE_EN = {
131
143
  "⚠️ This is personal data about your colleagues. For use in a real company you need a commercial Claude account with a data processing agreement. If employees' performance is analysed, in Germany this requires the works council's agreement (co-determination).",
132
144
  ],
133
145
  },
146
+ "kimal3 zeigen start": {
147
+ stempel: "35a185f9",
148
+ befehl: "kimal3 show start",
149
+ tippen: "/k3show",
150
+ terminal: 'kimal3 show start "Send the open quotes to my boss every Monday"',
151
+ beschreibung: "Start a recording while you show a task",
152
+ rhythmusOderSatz: "I want to show you a task",
153
+ details: [
154
+ "You do a task once on screen and say out loud what you are doing and why. Claude guides you through it: first the briefing on what gets recorded, then the recording, then the evaluation on your computer.",
155
+ "All screens, sound, clicks and keys are recorded — so don't type a password. The recording lies in the project under material/aufnahmen/ and never ends up in Git; it stops by itself after 15 minutes at the latest.",
156
+ "Claude asks you before reading any of it: only after your yes does the timeline go to Anthropic. At the end the task is written down in the project's plan folder, and Claude suggests deleting the recording.",
157
+ "Windows-only for now.",
158
+ ],
159
+ },
160
+ "kimal3 zeigen status": {
161
+ stempel: "7ebd2b8f",
162
+ befehl: "kimal3 show status",
163
+ tippen: "! kimal3 show status",
164
+ terminal: "kimal3 show status",
165
+ beschreibung: "Check whether a recording is running and whether the recorder is set up",
166
+ rhythmusOderSatz: "when you want to know whether something is being recorded",
167
+ details: [
168
+ "Shows two blocks: what is set up (uv, recorder, FFmpeg, speech model) and whether a recording of your screen is running — with start time, folder and the time at which it stops by itself at the latest.",
169
+ "If it can't tell whether something is being recorded, it says exactly that, with exit code 1 — it then never claims that nothing is running.",
170
+ "It only reads and changes nothing. Windows-only for now.",
171
+ ],
172
+ },
134
173
  "kimal3 wache": {
135
174
  stempel: "2daae4e2",
136
175
  befehl: "kimal3 watch",
@@ -167,6 +167,18 @@ export const BEFEHLE = [
167
167
  "Wofür es wirklich da ist: Claude schaut hier VOR dem Eintragen nach. Ohne diesen Blick stünde dasselbe Projekt irgendwann zweimal auf einer öffentlichen Seite, die deinen Namen trägt.",
168
168
  ],
169
169
  },
170
+ {
171
+ befehl: "kimal3 kurs",
172
+ beschreibung: "Zeigen, wo du im Mini-Kurs stehst",
173
+ wer: "claude",
174
+ ausloeser: "wo stehe ich im Kurs",
175
+ tippen: "/k3kurs",
176
+ terminal: "kimal3 kurs",
177
+ details: [
178
+ "Zeigt, welche Beats du fertig hast, was als Nächstes dran ist und was noch offen ist — und bei jedem Schritt, ob du ihn abhakst oder Claude ihn setzt.",
179
+ "Claude liest das, wenn du in den Kurs zurückkehrst, und macht genau dort weiter, wo du aufgehört hast.",
180
+ ],
181
+ },
170
182
  {
171
183
  befehl: "kimal3 firma daten",
172
184
  beschreibung: "Die Daten deiner Firma holen, damit Claude sie auswerten kann",
@@ -180,6 +192,33 @@ export const BEFEHLE = [
180
192
  "⚠️ Es sind personenbezogene Daten von Kolleginnen und Kollegen. Für den Einsatz in einer echten Firma braucht es ein kommerzielles Claude-Konto mit Auftragsverarbeitungsvertrag; werden Leistungen von Beschäftigten ausgewertet, ist das in Deutschland mitbestimmungspflichtig.",
181
193
  ],
182
194
  },
195
+ {
196
+ befehl: "kimal3 zeigen start",
197
+ beschreibung: "Eine Aufnahme starten, während du eine Aufgabe vormachst",
198
+ wer: "claude",
199
+ ausloeser: "ich will dir eine Aufgabe vormachen",
200
+ tippen: "/k3zeigen",
201
+ terminal: 'kimal3 zeigen start "Offene Angebote jeden Montag an die Chefin schicken"',
202
+ details: [
203
+ "Du machst eine Aufgabe einmal am Bildschirm vor und sagst dabei laut, was du tust und warum. Claude führt dich durch: vorher die Ansage, was aufgenommen wird, dann die Aufnahme, danach das Auswerten auf deinem Rechner.",
204
+ "Aufgenommen werden alle Bildschirme, Ton, Klicks und Tasten — tippe deshalb kein Passwort. Die Aufnahme liegt im Projekt unter material/aufnahmen/ und landet nie in Git; spätestens nach 15 Minuten stoppt sie von selbst.",
205
+ "Bevor Claude etwas davon liest, fragt er dich: Erst nach deinem Ja geht die Zeitleiste an Anthropic. Am Ende steht die Aufgabe in plan/aufgabe-vorgefuehrt.md, und Claude schlägt vor, die Aufnahme zu löschen.",
206
+ "Gibt es bisher nur unter Windows.",
207
+ ],
208
+ },
209
+ {
210
+ befehl: "kimal3 zeigen status",
211
+ beschreibung: "Nachsehen, ob gerade aufgenommen wird und ob der Aufnehmer eingerichtet ist",
212
+ wer: "du",
213
+ rhythmus: "wenn du wissen willst, ob gerade aufgenommen wird",
214
+ tippen: "! kimal3 zeigen status",
215
+ terminal: "kimal3 zeigen status",
216
+ details: [
217
+ "Zeigt zwei Blöcke: was eingerichtet ist (uv, Aufnehmer, FFmpeg, Sprachmodell) und ob gerade eine Aufnahme von deinem Bildschirm läuft — mit Startzeit, Ordner und der Uhrzeit, zu der sie spätestens von selbst stoppt.",
218
+ "Kann es nicht feststellen, ob aufgenommen wird, sagt es genau das, mit Rückgabewert 1 — es behauptet dann nie, dass nichts läuft.",
219
+ "Es liest nur und ändert nichts. Gibt es bisher nur unter Windows.",
220
+ ],
221
+ },
183
222
  /*
184
223
  🔴 Dieser Eintrag steht bewusst NICHT im "Weg, den ein Mensch geht" --
185
224
  niemand muss ihn selbst tippen. Er wird bei jedem Start von Claude Code
@@ -11,9 +11,17 @@ export const BEFEHLSWOERTER = {
11
11
  "projekt neu": { de: "projekt neu", en: "project new" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
12
12
  "projekt liste": { de: "projekt liste", en: "project list" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
13
13
  "firma daten": { de: "firma daten", en: "company data" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
14
+ kurs: { de: "kurs", en: "course" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
14
15
  wache: { de: "wache", en: "watch" },
15
16
  "wache an": { de: "wache an", en: "watch on" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
16
17
  "wache aus": { de: "wache aus", en: "watch off" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
18
+ // `kimal3 zeigen` / `show` (Spec 2026-10-18-k3zeigen-design.md, Abschnitt 1)
19
+ "zeigen einrichten": { de: "zeigen einrichten", en: "show setup" }, // kein-anzeigetext: Befehlswörter (Spec k3zeigen)
20
+ "zeigen start": { de: "zeigen start", en: "show start" }, // kein-anzeigetext: Befehlswörter (Spec k3zeigen)
21
+ "zeigen stopp": { de: "zeigen stopp", en: "show stop" }, // kein-anzeigetext: Befehlswörter (Spec k3zeigen)
22
+ "zeigen auswerten": { de: "zeigen auswerten", en: "show evaluate" }, // kein-anzeigetext: Befehlswörter (Spec k3zeigen)
23
+ "zeigen bild": { de: "zeigen bild", en: "show picture" }, // kein-anzeigetext: Befehlswörter (Spec k3zeigen)
24
+ "zeigen status": { de: "zeigen status", en: "show status" }, // kein-anzeigetext: Befehlswörter (Spec k3zeigen)
17
25
  };
18
26
  /**
19
27
  * Welcher Befehl steht vorne in `argv` -- und was bleibt dahinter?
@@ -56,6 +64,13 @@ export const SCHALTER_EN = {
56
64
  impact: "wirkung",
57
65
  "impact-label": "wirkung-label",
58
66
  "live-since": "live-seit",
67
+ // `kimal3 einrichten` / `setup` (Spec 2026-10-16, Bauform 6)
68
+ workplace: "arbeitsplatz",
69
+ workbench: "werkbank",
70
+ // `kimal3 show …` (Spec 2026-10-18-k3zeigen-design.md)
71
+ "at-most": "hoechstens",
72
+ language: "sprache",
73
+ "without-typed": "ohne-getipptes",
59
74
  };
60
75
  /** `company` -> `firma`; ein deutscher (oder unbekannter) Name bleibt, wie er ist. */
61
76
  export function deutscherSchalter(getippt) {
@@ -0,0 +1,130 @@
1
+ import { mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { coachNachher } from "./coach-rechnung.js";
6
+ import { COACH_TEXTE } from "./texte/coach.js";
7
+ /**
8
+ * Der Coach im Regel-Ordner (Spec 2026-10-16): Claude Code lädt jede Datei in `~/.claude/rules/` bei jedem Start mit,
9
+ * in jedem Ordner -- dort wirkt er, ohne dass `~/.claude/CLAUDE.md` angefasst wird (die gehört dem Menschen).
10
+ * Was in der Datei steht, rechnet `coach-rechnung.ts` (rein, bewacht von `check:wache`); hier wird nur gelesen und
11
+ * geschrieben. Gemessen am gebauten Programm von `check:cli-live`.
12
+ */
13
+ export const coachPfad = () => join(homedir(), ".claude", "rules", "kimal3-coach.md"); // kein-anzeigetext: Dateiname
14
+ /** Fehlt die Trenn-Marke, landet die neue Fassung HIER -- außerhalb des Regel-Ordners, sonst lüden zwei Coaches (UX-10). */
15
+ export const coachErsatzPfad = () => join(homedir(), ".kimal3", "kimal3-coach-neu.md"); // kein-anzeigetext: Dateiname
16
+ /** Der Coach aus dem alten Mini-Kurs, und wohin Claude ihn nach einem Ja verschiebt (S-14) -- `kimal3` schreibt ihn nie. */
17
+ export const alterKursCoachPfad = () => join(homedir(), ".claude", "CLAUDE.md"); // kein-anzeigetext: Dateiname
18
+ export const alterKursCoachAblage = () => join(homedir(), ".kimal3", "alter-kurs-coach.md"); // kein-anzeigetext: Dateiname
19
+ /**
20
+ * Legt den Coach ab oder frischt ihn auf. `null` = es liegt keiner da, und dieser Aufruf darf keinen anlegen
21
+ * (nur `einrichten` darf das; `skill install` und `login` frischen nur auf).
22
+ * 🔑 Wirft nie: Jeder Lese- oder Schreibfehler wird `gescheitert` mit der Meldung des Systems -- die Einrichtung läuft
23
+ * weiter (C-10), und der Mensch erfährt den Grund statt einer Stapelspur.
24
+ */
25
+ export function legeCoachAb(s, darfAnlegen) {
26
+ const pfad = coachPfad();
27
+ try {
28
+ const da = statSync(pfad, { throwIfNoEntry: false });
29
+ // Ein Ordner unter dem Namen gehört nicht uns -- nichts anfassen, wie bei einer fremden Datei (C-11).
30
+ if (da !== undefined && !da.isFile())
31
+ return { art: "fremd", pfad, spracheGewechselt: false };
32
+ if (da === undefined && !darfAnlegen)
33
+ return null;
34
+ // Die Vorlage erst NACH dem `null`: Wer keinen Coach hat, soll von `login` und `skill install` auch dann nichts hören,
35
+ // wenn die Vorlage im Paket fehlt (Gesamt-Durchsicht, Fund 6).
36
+ // `dist/coach-ablegen.js` -> `../coach/<sprache>/…` im installierten Paket (`files` in package.json).
37
+ const vorlage = readFileSync(fileURLToPath(new URL(`../coach/${s}/kimal3-coach.md`, import.meta.url)), "utf8"); // kein-anzeigetext: Paketpfad
38
+ const ergebnis = coachNachher(da === undefined ? null : readFileSync(pfad, "utf8"), vorlage);
39
+ switch (ergebnis.art) {
40
+ case "neu":
41
+ mkdirSync(dirname(pfad), { recursive: true });
42
+ tauscheEin(pfad, ergebnis.inhalt);
43
+ return { art: "angelegt", pfad, spracheGewechselt: false };
44
+ case "aktualisiert":
45
+ tauscheEin(pfad, ergebnis.inhalt);
46
+ return { art: "aktualisiert", pfad, spracheGewechselt: ergebnis.spracheVorher !== null && ergebnis.spracheVorher !== s };
47
+ case "ohne-trenner": {
48
+ // Das Original bleibt Byte für Byte (C-8): Ohne Trenn-Marke wüssten wir nicht, wo seine Regeln anfangen.
49
+ const ersatz = coachErsatzPfad();
50
+ mkdirSync(dirname(ersatz), { recursive: true });
51
+ writeFileSync(ersatz, ergebnis.inhalt, "utf8");
52
+ return { art: "ohne-trenner", pfad, ersatz };
53
+ }
54
+ case "vorlage-ohne-trenner":
55
+ return { art: "gescheitert", pfad, grund: COACH_TEXTE[s].templateWithoutSeparator };
56
+ default:
57
+ return { art: ergebnis.art, pfad, spracheGewechselt: false };
58
+ }
59
+ }
60
+ catch (e) {
61
+ return { art: "gescheitert", pfad, grund: e.message };
62
+ }
63
+ }
64
+ /**
65
+ * Erst in eine Nebendatei, dann tauschen (Durchsicht Aufgabe 5, Fund 1): `writeFileSync` leert die Datei, BEVOR es
66
+ * schreibt -- bei voller Platte wären die gelernten Regeln weg, und der nächste Lauf hielte den leeren Rest für fremd.
67
+ * 🔑 `kimal3-coach.md.neu` endet nicht auf `.md`: Claude lädt sie nie als zweiten Coach, auch wenn sie liegen bliebe.
68
+ * Scheitert ein Schritt, kommt die Nebendatei weg (ein Ordner unter dem Namen ist nicht unserer und bleibt), und der
69
+ * Fehler geht an `legeCoachAb`, das ihn zu `gescheitert` macht.
70
+ */
71
+ function tauscheEin(pfad, inhalt) {
72
+ const neben = `${pfad}.neu`; // kein-anzeigetext: Dateiname
73
+ try {
74
+ writeFileSync(neben, inhalt, "utf8");
75
+ renameSync(neben, pfad);
76
+ }
77
+ catch (e) {
78
+ try {
79
+ rmSync(neben);
80
+ }
81
+ catch {
82
+ // Lag nie da, oder es ist ein Ordner -- dann nichts anfassen.
83
+ }
84
+ throw e;
85
+ }
86
+ }
87
+ /** Liegt unter dem Coach-Pfad eine DATEI (unsere oder eine fremde)? Daran hängt `beat2-coach` (E-5, E-9). Wirft nie. */
88
+ export function coachDateiLiegt() {
89
+ try {
90
+ return statSync(coachPfad(), { throwIfNoEntry: false })?.isFile() === true;
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ }
96
+ /**
97
+ * Die eine Zeile zu einer Ablage, in der Sprache des Laufs -- für `einrichten` (Task 5), `skill install` und `login`.
98
+ * `sprachwechselSagen`: Nur `login` und `skill install` sagen einen Sprachwechsel mit eigenem Satz (Spec 2.6) -- er
99
+ * sagt, was der Mensch dort sonst nicht merkt: dass seine Regeln den Wechsel überlebt haben. `einrichten` bleibt bei der
100
+ * Zeile mit `Coach:`, an der die Anleitung liest. Welche Fälle ein Aufruf verschweigt (`gleich`, `fremd` beim
101
+ * Auffrischen), entscheidet der Aufrufer.
102
+ */
103
+ export function meldeCoach(ablage, s, sprachwechselSagen = false) {
104
+ if (ablage === null)
105
+ return;
106
+ const t = COACH_TEXTE[s];
107
+ if (ablage.art === "angelegt")
108
+ console.log(t.setUp(ablage.pfad));
109
+ else if (ablage.art === "gleich")
110
+ console.log(t.upToDate);
111
+ else if (ablage.art === "aktualisiert")
112
+ console.log(sprachwechselSagen && ablage.spracheGewechselt ? t.languageSwitched : t.updated);
113
+ else if (ablage.art === "fremd")
114
+ console.log(t.foreign(ablage.pfad));
115
+ else if (ablage.art === "ohne-trenner")
116
+ console.log(t.noSeparator(ablage.pfad, ablage.ersatz));
117
+ else if (ablage.art === "gescheitert")
118
+ console.log(t.failed(ablage.grund));
119
+ }
120
+ /**
121
+ * Für `skill install` und `login`: einen VORHANDENEN Coach auffrischen (Update, Sprachwechsel), nie einen anlegen --
122
+ * das darf nur `einrichten` (Spec C-13b: Auffrischen ist kein Anlegen). Schweigt, wenn nichts zu sagen ist: kein Coach,
123
+ * ein fremder, ein schon aktueller. Ein Sprachwechsel bekommt seinen eigenen Satz (Spec 2.6).
124
+ */
125
+ export function frischeCoachAuf(s) {
126
+ const ablage = legeCoachAb(s, false);
127
+ if (ablage === null || ablage.art === "gleich" || ablage.art === "fremd")
128
+ return;
129
+ meldeCoach(ablage, s, true);
130
+ }
@@ -0,0 +1,40 @@
1
+ // Ein BOM (U+FEFF) vor der ersten Zeile setzen manche Windows-Editoren; er gehört nicht zur Marke.
2
+ const KOPF = /^\uFEFF?<!-- kimal3:coach/;
3
+ const KOPF_SPRACHE = /^\uFEFF?<!-- kimal3:coach sprache=(de|en)(?![A-Za-z])/;
4
+ // Nur am ZEILENANFANG, ohne Einrückung: Die Kopfzeile nennt die Trenn-Marke im Fließtext, und eine gelernte Regel darf
5
+ // es auch. 🔑 Exportiert, weil `check:cli` die Vorlagen mit GENAU diesem Ausdruck prüft -- eine eigene, nachsichtigere
6
+ // Erkennung dort ließe eine eingerückte Marke grün durch, die diese Rechnung nicht findet (Gesamt-Durchsicht, Fund 3).
7
+ export const TRENNER = /^<!-- kimal3:gelernte-regeln/m;
8
+ const ALTER_KURS_COACH = /^\uFEFF?# CLAUDE\.md — (Dein Claude-Coach|Your Claude coach)/;
9
+ export const istUnserCoach = (inhalt) => KOPF.test(inhalt);
10
+ export function coachSprache(inhalt) {
11
+ const treffer = KOPF_SPRACHE.exec(inhalt);
12
+ return treffer ? treffer[1] : null;
13
+ }
14
+ // Der Kurs-Coach von früher (Beat 2 des Mini-Kurses) beginnt mit dieser Überschrift, deutsch wie englisch.
15
+ export const istAlterKursCoach = (inhalt) => ALTER_KURS_COACH.test(inhalt);
16
+ // Alles bis einschließlich des Zeilenendes der ersten Trenn-Zeile (\n oder \r\n -- das \r steht vor dem \n und
17
+ // gehört damit zur Zeile). Ohne Zeilenende danach reicht die Zeile bis zum Dateiende. -1 = keine Trenn-Zeile.
18
+ function obenBis(text) {
19
+ const treffer = TRENNER.exec(text);
20
+ if (!treffer)
21
+ return -1;
22
+ const umbruch = text.indexOf("\n", treffer.index);
23
+ return umbruch === -1 ? text.length : umbruch + 1;
24
+ }
25
+ export function coachNachher(vorher, vorlage) {
26
+ const vorlageEnde = obenBis(vorlage);
27
+ if (vorlageEnde === -1)
28
+ return { art: "vorlage-ohne-trenner" };
29
+ if (vorher === null)
30
+ return { art: "neu", inhalt: vorlage };
31
+ if (!istUnserCoach(vorher))
32
+ return { art: "fremd" };
33
+ const altEnde = obenBis(vorher);
34
+ if (altEnde === -1)
35
+ return { art: "ohne-trenner", inhalt: vorlage };
36
+ const neu = vorlage.slice(0, vorlageEnde) + vorher.slice(altEnde);
37
+ if (neu === vorher)
38
+ return { art: "gleich" };
39
+ return { art: "aktualisiert", inhalt: neu, spracheVorher: coachSprache(vorher) };
40
+ }
package/dist/kimal3.js CHANGED
@@ -33,10 +33,14 @@ import { kontextRunter } from "./befehle/kontext-runter.js";
33
33
  import { kontextHoch } from "./befehle/kontext-hoch.js";
34
34
  import { login } from "./befehle/login.js";
35
35
  import { logout } from "./befehle/logout.js";
36
+ import { kurs } from "./befehle/kurs.js";
36
37
  import { projektListe } from "./befehle/projekt-liste.js";
37
38
  import { projektNeu } from "./befehle/projekt-neu.js";
38
- import { skillDatei, skillInstall } from "./befehle/skill-install.js";
39
+ import { skillDatei, skillInstallBefehl } from "./befehle/skill-install.js";
39
40
  import { wache, wacheSchalten } from "./befehle/wache.js";
41
+ import { zeigenAuswerten, zeigenBild, zeigenStatus, zeigenStopp } from "./befehle/zeigen.js";
42
+ import { zeigenStart } from "./befehle/zeigen-start.js";
43
+ import { zeigenEinrichten } from "./befehle/zeigen-einrichten.js";
40
44
  /** Eine Meldung pro Programmlauf -- s. "Einmal-Riegel" im Block darunter. */
41
45
  let schonGemeldet = false;
42
46
  /**
@@ -480,9 +484,10 @@ async function fuehreAus(name, rest) {
480
484
  switch (name) {
481
485
  case "login": return allein ? login() : null;
482
486
  case "logout": return allein ? logout() : null;
483
- case "skill install": return allein ? skillInstall() : null;
487
+ case "skill install": return allein ? skillInstallBefehl() : null;
484
488
  case "projekt neu": return projektNeu(rest);
485
489
  case "projekt liste": return allein ? projektListe() : null;
490
+ case "kurs": return allein ? kurs() : null;
486
491
  // ⚠️ Rest wird durchgereicht, nicht auf Gleichheit geprueft: `firma daten --firma X` gehoert dazu.
487
492
  case "firma daten": return firmaDaten(rest);
488
493
  case "einrichten": return einrichten(rest);
@@ -491,6 +496,13 @@ async function fuehreAus(name, rest) {
491
496
  case "kontext runter": return kontextRunter(rest);
492
497
  case "kontext hoch": return kontextHoch(rest);
493
498
  case "kontext fragen": return kontextFragen(rest);
499
+ // `kimal3 zeigen` (Spec 2026-10-18-k3zeigen-design.md).
500
+ case "zeigen einrichten": return zeigenEinrichten(rest);
501
+ case "zeigen start": return zeigenStart(rest);
502
+ case "zeigen stopp": return zeigenStopp(rest);
503
+ case "zeigen auswerten": return zeigenAuswerten(rest);
504
+ case "zeigen bild": return zeigenBild(rest);
505
+ case "zeigen status": return zeigenStatus(rest);
494
506
  case "wache an": return allein ? wacheSchalten(true) : null;
495
507
  case "wache aus": return allein ? wacheSchalten(false) : null;
496
508
  case "wache":
@@ -2,6 +2,7 @@ import { cpSync, existsSync, readdirSync, readFileSync, renameSync, rmSync, writ
2
2
  import { homedir } from "node:os";
3
3
  import { basename, dirname, join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
+ import { EINRICHTEN_TEXTE } from "./texte/einrichten.js";
5
6
  /**
6
7
  * Legt den Plugin-Katalog mit dem Logo-Mod in `~/.kimal3/claude-plugins` ab und setzt dort die
7
8
  * Sprache des Kontos. Claude Code liest den Mod aus genau diesem Ordner (Katalog `kimal3`,
@@ -34,8 +35,9 @@ export function mitSprache(quelltext, sprache) {
34
35
  * 🔑 Der weggeschobene Ordner bekommt bei JEDEM Lauf einen frischen Namen (Durchsicht 2, Funde 2 und 4):
35
36
  * Ein Rest, den Windows festhält, blockiert so keinen späteren Lauf, und zurückgeholt wird nur, was
36
37
  * DIESER Lauf weggeschoben hat -- nie ein veralteter Rest von früher.
37
- * Lässt sich der alte nicht wegschieben (Claude hält ihn manchmal fest), bleibt er unversehrt stehen und
38
- * gilt weiter: ein Erfolg mit `alterStand`, den `kimal3 einrichten` in einer Zeile nennt.
38
+ * Lässt sich der alte nicht wegschieben, bleibt er unversehrt stehen und gilt weiter: ein Erfolg mit `stand: "alt"`,
39
+ * den der Aufrufer in einer Zeile nennt. Unter Windows hält ihn ein Programm fest, dessen Arbeitsordner darin liegt;
40
+ * Claude selbst tut es nicht (gemessen 18.10. bei acht laufenden Claude-Prozessen, Spec 2026-10-18, Abschnitt 1.2).
39
41
  */
40
42
  export function logoAblegen(sprache) {
41
43
  // `dist/logo-ablegen.js` -> `../claude-plugins` im installierten Paket (`files` in package.json).
@@ -51,14 +53,14 @@ export function logoAblegen(sprache) {
51
53
  // Auch im Normalfall aufräumen, samt einem halb gebauten `….neu`: sonst blieben Reste für immer (Durchsicht 3/4).
52
54
  rmSync(neu, { recursive: true, force: true });
53
55
  resteWegraeumen(ziel);
54
- return { ok: true, ordner: ziel };
56
+ return { ok: true, ordner: ziel, stand: "gleich" };
55
57
  }
56
58
  rmSync(neu, { recursive: true, force: true });
57
59
  cpSync(quelle, neu, { recursive: true });
58
60
  writeFileSync(modDatei(neu), text, "utf8");
59
61
  if (!existsSync(ziel)) {
60
62
  renameSync(neu, ziel);
61
- return { ok: true, ordner: ziel };
63
+ return { ok: true, ordner: ziel, stand: "neu" };
62
64
  }
63
65
  const alt = `${ziel}.alt-${Date.now()}`; // kein-anzeigetext: Ordnername
64
66
  try {
@@ -66,7 +68,7 @@ export function logoAblegen(sprache) {
66
68
  }
67
69
  catch {
68
70
  rmSync(neu, { recursive: true, force: true });
69
- return { ok: true, ordner: ziel, alterStand: true };
71
+ return { ok: true, ordner: ziel, stand: "alt" };
70
72
  }
71
73
  try {
72
74
  renameSync(neu, ziel);
@@ -76,12 +78,30 @@ export function logoAblegen(sprache) {
76
78
  return { ok: false, detail: e.message };
77
79
  }
78
80
  resteWegraeumen(ziel);
79
- return { ok: true, ordner: ziel };
81
+ return { ok: true, ordner: ziel, stand: "neu" };
80
82
  }
81
83
  catch (e) {
82
84
  return { ok: false, detail: e.message };
83
85
  }
84
86
  }
87
+ /**
88
+ * Für `login` und `skill install` (Spec 2026-10-18, Abschnitt 1.2): ein VORHANDENES Logo auffrischen (Update,
89
+ * Sprachwechsel), nie eines anlegen -- das darf nur `einrichten`, wie beim Coach (`frischeCoachAuf`). Wer das Logo nie
90
+ * eingerichtet hat, hört nichts und bekommt keinen Ordner (L-2). Eine Zeile nur, wenn getauscht wurde, das alte bleiben
91
+ * musste oder etwas scheiterte; sonst Stille. Wirft nie und ändert den Rückgabewert des Befehls nicht (L-6).
92
+ */
93
+ export function frischeLogoAuf(s) {
94
+ if (!existsSync(katalogOrdner()))
95
+ return;
96
+ const ablage = logoAblegen(s);
97
+ const t = EINRICHTEN_TEXTE[s];
98
+ if (!ablage.ok)
99
+ console.log(t.logoNotWritten(ablage.detail));
100
+ else if (ablage.stand === "neu")
101
+ console.log(t.logoRefreshed);
102
+ else if (ablage.stand === "alt")
103
+ console.log(t.logoNotRefreshed);
104
+ }
85
105
  /** Gleiche Dateien, gleicher Inhalt -- der Mod mit der Sprache des Kontos, alles andere wie im Paket. */
86
106
  function stehtSchonDa(quelle, ziel, modText) {
87
107
  if (!existsSync(ziel))
@@ -1,6 +1,7 @@
1
1
  export const SLASH_PAARE = [
2
2
  { de: "k3", en: "k3" },
3
3
  { de: "k3start", en: "k3start" },
4
+ { de: "k3zeigen", en: "k3show" }, // kein-anzeigetext: Befehlsname (Spec 2026-10-18-k3zeigen-design.md)
4
5
  { de: "k3feierabend", en: "k3wrapup" }, // kein-anzeigetext: Befehlsname (Spec Teil 4, Abschnitt 6)
5
6
  { de: "k3kontext", en: "k3context" }, // kein-anzeigetext: Befehlsname
6
7
  { de: "k3projekt", en: "k3project" }, // kein-anzeigetext: Befehlsname
@@ -0,0 +1,27 @@
1
+ import { EINRICHTEN_MARKEN } from "./einrichten-marken.js";
2
+ const M = EINRICHTEN_MARKEN;
3
+ const de = {
4
+ setUp: (pfad) => ` ${M.de.coach} eingerichtet (${pfad}).`,
5
+ upToDate: ` ${M.de.coach} ist aktuell.`,
6
+ updated: ` ${M.de.coach} aktualisiert — deine gelernten Regeln sind geblieben.`,
7
+ foreign: (pfad) => ` ${M.de.coach} Unter ${pfad} liegt schon eine Datei, die nicht von KImal3 stammt — ich lasse sie, wie sie ist.`,
8
+ noSeparator: (pfad, neu) => ` ${M.de.coach} nicht aktualisiert — in ${pfad} fehlt die Zeile, ab der deine gelernten Regeln stehen. Die neue Fassung liegt unter ${neu}.`,
9
+ failed: (grund) => ` ${M.de.coach} konnte nicht abgelegt werden — ${grund}`,
10
+ // Der Grund zu `failed`, wenn der Vorlage im Programm selbst die Trenn-Marke fehlt (ein Paketfehler, `coach-rechnung.ts`).
11
+ templateWithoutSeparator: "der Vorlage im Programm fehlt die Zeile, ab der die gelernten Regeln stehen. Das ist ein Fehler in kimal3 — bitte melde ihn uns.",
12
+ // Die Zeile spricht immer die Sprache, in die umgestellt wurde -- deshalb steht der Sprachname fest im Satz.
13
+ languageSwitched: "✓ Dein Coach ist jetzt auf Deutsch — deine gelernten Regeln sind geblieben.",
14
+ oldCourseCoach: (pfad, ablage) => ` ${M.de.alterKursCoach} Du hast im alten Mini-Kurs schon einmal einen Coach eingerichtet (${pfad}). Jetzt gibt es einen neuen, und zwei gleichzeitig würden sich widersprechen. Soll ich den alten beiseitelegen? Du findest ihn danach unter ${ablage}.`,
15
+ };
16
+ const en = {
17
+ setUp: (pfad) => ` ${M.en.coach} set up (${pfad}).`,
18
+ upToDate: ` ${M.en.coach} up to date.`,
19
+ updated: ` ${M.en.coach} updated — your learned rules are still there.`,
20
+ foreign: (pfad) => ` ${M.en.coach} There's already a file at ${pfad} that doesn't come from KImal3 — I'll leave it as it is.`,
21
+ noSeparator: (pfad, neu) => ` ${M.en.coach} not updated — ${pfad} is missing the line your learned rules start below. The new version is at ${neu}.`,
22
+ failed: (grund) => ` ${M.en.coach} couldn't be put in place — ${grund}`,
23
+ templateWithoutSeparator: "the program's template is missing the line your learned rules start below. That's a bug in kimal3 — please tell us.",
24
+ languageSwitched: "✓ Your coach is now in English — your learned rules are still there.",
25
+ oldCourseCoach: (pfad, ablage) => ` ${M.en.alterKursCoach} You set up a coach in the old mini course (${pfad}). There's a new one now, and two at once would contradict each other. Shall I put the old one aside? You'll find it at ${ablage} afterwards.`,
26
+ };
27
+ export const COACH_TEXTE = { de, en };
@@ -4,6 +4,6 @@
4
4
  * Programm druckt sie, die Anleitung nennt sie, `check:kurs` haelt beide gleich.
5
5
  */
6
6
  export const EINRICHTEN_MARKEN = {
7
- de: { code: "Anmelde-Code:", adresse: "Adresse:", arbeitsplatz: "Arbeitsplatz:", werkbank: "Werkbank:", angemeldet: "Angemeldet als", plugins: "Plugins:" },
8
- en: { code: "Sign-in code:", adresse: "Address:", arbeitsplatz: "Workplace:", werkbank: "Workbench:", angemeldet: "Signed in as", plugins: "Plugins:" },
7
+ de: { code: "Anmelde-Code:", adresse: "Adresse:", arbeitsplatz: "Arbeitsplatz:", werkbank: "Werkbank:", angemeldet: "Angemeldet als", plugins: "Plugins:", naechster: "Als Nächstes:", coach: "Coach:", alterKursCoach: "Alter Kurs-Coach:" },
8
+ en: { code: "Sign-in code:", adresse: "Address:", arbeitsplatz: "Workplace:", werkbank: "Workbench:", angemeldet: "Signed in as", plugins: "Plugins:", naechster: "Next:", coach: "Coach:", alterKursCoach: "Old course coach:" },
9
9
  };
@@ -5,11 +5,36 @@ const de = {
5
5
  addressLine: (url) => ` ${M.de.adresse} ${url}`,
6
6
  browserOpened: " Ich öffne die Seite gerade in deinem Browser. Bestätige dort nur, wenn derselbe Code dasteht.",
7
7
  browserNotOpened: " Öffne die Adresse oben in deinem Browser. Bestätige dort nur, wenn derselbe Code dasteht.",
8
- help: "\n kimal3 einrichten [--firma \"Name\" | --firma-id \"…\"]\n\n Meldet dich an (der Browser öffnet sich mit deinem Code), legt deinen\n KI-Arbeitsplatz in deinem Benutzerordner an, richtet die /k3-Befehle und\n die Wache ein und hakt die Schritte im Kurs ab. Ein zweiter Lauf ergänzt\n nur, was fehlt.\n",
8
+ help: "\n kimal3 einrichten [--firma \"Name\" | --firma-id \"…\"] [--arbeitsplatz \"<pfad>\"] [--werkbank <name>]\n\n Meldet dich an (der Browser öffnet sich mit deinem Code), sucht deinen\n KI-Arbeitsplatz oder legt ihn in deinem Benutzerordner an, richtet die\n /k3-Befehle und die Wache ein und hakt die Schritte im Kurs ab. Ein\n vorhandener Arbeitsplatz wird benutzt, nicht verändert.\n\n --arbeitsplatz wo dein Arbeitsplatz liegt oder neu entstehen soll\n --werkbank welche Werkbank darin deine ist\n",
9
9
  start: "\nIch richte deinen KI-Arbeitsplatz ein.",
10
10
  filesWritten: (neu, schonDa) => `\n✓ ${neu} Dateien angelegt, ${schonDa} lagen schon da.`,
11
11
  workplaceLine: (pfad) => ` ${M.de.arbeitsplatz} ${pfad}`,
12
12
  workbenchLine: (name) => ` ${M.de.werkbank} ${name}`,
13
+ // Was Sabine in der nächsten Sitzung schreibt (Spec 2026-10-16, Z-15): Steht die Anleitung für die erste
14
+ // Sitzung noch in ihrer Werkbank, der Startsatz der Vorlage; sonst der Befehl für jeden weiteren Tag.
15
+ nextLine: (offen) => ` ${M.de.naechster} ${offen ? "„Lass uns einrichten“" : "/k3start"}`,
16
+ // Vorhandener Arbeitsplatz (Spec 2026-10-16, „Neue Sätze“). Jede Rückfrage endet mit fertigen Befehlen.
17
+ foundWorkplace: (pfad) => `\nDein Arbeitsplatz liegt schon unter ${pfad} — ich benutze diesen.`,
18
+ severalFound: "\nIch habe mehrere Arbeitsplätze gefunden. Welchen soll ich benutzen?",
19
+ foreignFolder: (pfad) => `\nUnter ${pfad} liegt schon ein Ordner, der nicht von KImal3 stammt. Ich lege dort nichts ab.`,
20
+ searchIncomplete: "\nIch konnte nicht überall nachsehen. Hast du schon einen Arbeitsplatz?",
21
+ rememberedGone: (pfad) => `\nDein Arbeitsplatz lag unter ${pfad}, dort ist er nicht mehr. Wo liegt er jetzt?`,
22
+ noMatchingWorkbench: (pfad) => `\nIn ${pfad} finde ich keine Werkbank für dich.`,
23
+ confirmWorkbench: (name) => `\nIst ${name} deine Werkbank?`,
24
+ noWorkbenchInWorkplace: (pfad) => `\nIn ${pfad} gibt es noch keine Werkbank. Leg deine an und starte die Einrichtung danach noch einmal:`,
25
+ // Die Überschriften über den Befehlen der Rückfragen.
26
+ existingWorkplace: " Er liegt hier (Pfad einsetzen):",
27
+ newWorkplace: " Leg einen neuen an:",
28
+ otherPlace: " Nimm einen anderen Ort, leer oder mit deinem Arbeitsplatz:",
29
+ yes: " Ja:",
30
+ noOther: " Nein, es ist eine andere:",
31
+ oneOfThese: " Ist eine davon deine:",
32
+ ownWorkbench: " Noch keine eigene? Leg sie an und starte die Einrichtung danach noch einmal:",
33
+ pathPlaceholder: "<pfad>",
34
+ // Ein mitkopierter Platzhalter in `--arbeitsplatz` -- Claude fragt dann nach dem echten Ort.
35
+ placeholderPath: (wert) => `\n${wert} ist ein Platzhalter, kein Ordner. Setz dort den echten Pfad deines Arbeitsplatzes ein; ich habe nichts angelegt.`,
36
+ commandLine: (rest) => ` kimal3 ${rest}`,
37
+ cdLine: (pfad) => ` cd ${pfad}`,
13
38
  courseMarked: "✓ Im Kurs abgehakt.",
14
39
  courseNotMarked: " Die Haken im Kurs konnte ich gerade nicht setzen — der nächste Lauf holt das nach.",
15
40
  done: "\n✓ Fertig eingerichtet.",
@@ -25,22 +50,48 @@ const de = {
25
50
  settingsInvalid: "deine Claude-Einstellungen (~/.claude/settings.json) sind kein gültiges JSON. Ich habe sie nicht angefasst.",
26
51
  settingsForeign: "in deinen Claude-Einstellungen (~/.claude/settings.json) steht etwas in einer Form, die ich nicht kenne. Ich habe sie nicht angefasst.",
27
52
  settingsFailed: (ursache) => `deine Claude-Einstellungen (~/.claude/settings.json): ${ursache}.`,
28
- // Logo (Durchsicht 2, Funde 1 und 3): Scheitert der Ordner, kommt superpowers trotzdem; hält Claude ihn fest, gilt die alte Fassung.
53
+ // Logo (Durchsicht 2, Funde 1 und 3): Scheitert der Ordner, kommt superpowers trotzdem; hält ein anderes Programm ihn fest, bleibt die alte Fassung (`logoOldVersion`).
29
54
  logoNotWritten: (detail) => ` Den Ordner für das KImal3-Logo konnte ich nicht anlegen oder erneuern (${detail}).`,
30
55
  // Ohne Git kein superpowers (Durchsicht 3, Fund 5); die Anleitung zitiert den Anfang dieser Zeile.
31
56
  superpowersNeedsGit: " superpowers braucht Git — es kommt mit dem nächsten `kimal3 einrichten`, sobald Git da ist.",
32
- logoOldVersion: " Das KImal3-Logo bleibt vorerst in der bisherigen Fassung, weil Claude den Ordner gerade benutzt. Beende Claude ganz und starte danach `kimal3 einrichten` noch einmal.",
57
+ // Die Sperre setzt ein anderes Programm mit Arbeitsordner im Logo-Ordner, nicht Claude -- deshalb kein Rat, Claude zu
58
+ // beenden (für App-Nutzer ein Kreis; Spec 2026-10-18, Abschnitt 1.2).
59
+ logoOldVersion: " Das Logo konnte gerade nicht aufgefrischt werden, weil ein anderes Programm seinen Ordner benutzt. Es kommt beim nächsten `kimal3 einrichten`.",
60
+ // Auffrischen bei `login` und `skill install` (`frischeLogoAuf`); scheitert es, sagt es `logoNotWritten`.
61
+ logoRefreshed: " Das Logo über dem Eingabefeld ist aufgefrischt. Ist es eingeschaltet, siehst du es nach dem nächsten Neustart von Claude.",
62
+ logoNotRefreshed: " Das Logo konnte gerade nicht aufgefrischt werden, weil ein anderes Programm seinen Ordner benutzt. Es kommt beim nächsten `kimal3 skill install`.",
33
63
  };
34
64
  const en = {
35
65
  codeLine: (code) => `\n ${M.en.code} ${code}`,
36
66
  addressLine: (url) => ` ${M.en.adresse} ${url}`,
37
67
  browserOpened: " Opening the page in your browser now. Only confirm there if it shows the same code.",
38
68
  browserNotOpened: " Open the address above in your browser. Only confirm there if it shows the same code.",
39
- help: "\n kimal3 setup [--company \"Name\" | --company-id \"…\"]\n\n Signs you in (your browser opens with your code), creates your AI Workplace\n in your user folder, sets up the /k3 commands and the watch, and ticks off\n the course steps. A second run only adds what is missing.\n",
69
+ help: "\n kimal3 setup [--company \"Name\" | --company-id \"…\"] [--workplace \"<path>\"] [--workbench <name>]\n\n Signs you in (your browser opens with your code), finds your AI Workplace\n or creates it in your user folder, sets up the /k3 commands and the watch,\n and ticks off the course steps. An existing workplace is used, not changed.\n\n --workplace where your workplace is, or where a new one should go\n --workbench which workbench in it is yours\n",
40
70
  start: "\nSetting up your AI Workplace.",
41
71
  filesWritten: (neu, schonDa) => `\n✓ ${neu} files created, ${schonDa} were already there.`,
42
72
  workplaceLine: (pfad) => ` ${M.en.arbeitsplatz} ${pfad}`,
43
73
  workbenchLine: (name) => ` ${M.en.werkbank} ${name}`,
74
+ // The start sentence of the English template (workbench-your-name/CLAUDE.md, anleitung-en.ts) -- exactly that one.
75
+ nextLine: (offen) => ` ${M.en.naechster} ${offen ? "“Let's get set up”" : "/k3start"}`,
76
+ foundWorkplace: (pfad) => `\nYour workplace already exists at ${pfad} — I'll use that one.`,
77
+ severalFound: "\nI found more than one workplace. Which one should I use?",
78
+ foreignFolder: (pfad) => `\nThere's already a folder at ${pfad} that doesn't come from KImal3. I won't put anything there.`,
79
+ searchIncomplete: "\nI couldn't look everywhere. Do you already have a workplace?",
80
+ rememberedGone: (pfad) => `\nYour workplace was at ${pfad} and isn't there anymore. Where is it now?`,
81
+ noMatchingWorkbench: (pfad) => `\nI can't find a workbench for you in ${pfad}.`,
82
+ confirmWorkbench: (name) => `\nIs ${name} your workbench?`,
83
+ noWorkbenchInWorkplace: (pfad) => `\nThere's no workbench in ${pfad} yet. Create yours, then run the setup again:`,
84
+ existingWorkplace: " It's here (fill in the path):",
85
+ newWorkplace: " Create a new one:",
86
+ otherPlace: " Choose another place, empty or with your workplace in it:",
87
+ yes: " Yes:",
88
+ noOther: " No, it's another one:",
89
+ oneOfThese: " If one of these is yours:",
90
+ ownWorkbench: " None of your own yet? Create it, then run the setup again:",
91
+ pathPlaceholder: "<path>",
92
+ placeholderPath: (wert) => `\n${wert} is a placeholder, not a folder. Put the real path of your workplace there; I haven't created anything.`,
93
+ commandLine: (rest) => ` kimal3 ${rest}`,
94
+ cdLine: (pfad) => ` cd ${pfad}`,
44
95
  courseMarked: "✓ Ticked off in the course.",
45
96
  courseNotMarked: " I couldn't tick off the course steps just now — the next run will catch up.",
46
97
  done: "\n✓ All set up.",
@@ -55,6 +106,8 @@ const en = {
55
106
  settingsFailed: (ursache) => `your Claude settings (~/.claude/settings.json): ${ursache}.`,
56
107
  logoNotWritten: (detail) => ` I couldn't create or renew the folder for the KImal3 logo (${detail}).`,
57
108
  superpowersNeedsGit: " superpowers needs Git — it comes with the next `kimal3 setup` once Git is there.",
58
- logoOldVersion: " The KImal3 logo stays on its previous version for now, because Claude is using the folder. Quit Claude completely, then run `kimal3 setup` again.",
109
+ logoOldVersion: " The logo couldn't be refreshed just now, because another program is using its folder. It comes with the next `kimal3 setup`.",
110
+ logoRefreshed: " The logo above the prompt is refreshed. If it is switched on, you'll see it after the next restart of Claude.",
111
+ logoNotRefreshed: " The logo couldn't be refreshed just now, because another program is using its folder. It comes with the next `kimal3 skill install`.",
59
112
  };
60
113
  export const EINRICHTEN_TEXTE = { de, en };
@@ -0,0 +1,21 @@
1
+ const de = {
2
+ beatFertig: (nummer) => `Beat ${nummer} ✓`,
3
+ beatTeil: (nummer, erledigt, gesamt) => `Beat ${nummer} — ${erledigt} von ${gesamt}`,
4
+ uebersicht: (beats) => `Kurs: ${beats}`,
5
+ alleErledigt: (anzahl) => `Kurs: abgeschlossen ✓ — alle ${anzahl} Schritte erledigt.`,
6
+ naechster: (text, claude) => `Als Nächstes: ${text} (${claude ? "setzt Claude" : "du hakst ab"})`,
7
+ nochOffen: "Noch offen:",
8
+ offenZeile: (beat, text, claude) => ` ○ Beat ${beat}: ${text} (${claude ? "setzt Claude" : "du hakst ab"})`,
9
+ imBrowser: (url) => `Im Browser: ${url}/kurs`,
10
+ };
11
+ const en = {
12
+ beatFertig: (nummer) => `Part ${nummer} ✓`,
13
+ beatTeil: (nummer, erledigt, gesamt) => `Part ${nummer} — ${erledigt} of ${gesamt}`,
14
+ uebersicht: (beats) => `Course: ${beats}`,
15
+ alleErledigt: (anzahl) => `Course: complete ✓ — all ${anzahl} steps done.`,
16
+ naechster: (text, claude) => `Next: ${text} (${claude ? "Claude sets it" : "you tick it off"})`,
17
+ nochOffen: "Still open:",
18
+ offenZeile: (beat, text, claude) => ` ○ Part ${beat}: ${text} (${claude ? "Claude sets it" : "you tick it off"})`,
19
+ imBrowser: (url) => `In the browser: ${url}/kurs`,
20
+ };
21
+ export const KURS_TEXTE = { de, en };