hmgr 0.0.4 → 0.0.5
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.
- package/dist/adapter/claude-code.js +21 -17
- package/dist/adapter/dateisystem.js +105 -5
- package/dist/adapter/git.js +96 -10
- package/dist/adapter/hermes.js +163 -10
- package/dist/adapter/skill-md.js +94 -18
- package/dist/adapter/terminal.js +1 -1
- package/dist/adapter/zustand-json.js +4 -0
- package/dist/cli/hilfe.js +129 -26
- package/dist/cli/main.js +268 -20
- package/dist/gui/icons.js +114 -0
- package/dist/gui/main.js +481 -0
- package/dist/gui/oeffnen.js +33 -0
- package/dist/gui/preload.cjs +55 -0
- package/dist/gui/renderer/fonts/Inter-LICENSE.txt +92 -0
- package/dist/gui/renderer/fonts/InterVariable.woff2 +0 -0
- package/dist/gui/renderer/fonts/JetBrainsMono-Medium.woff2 +0 -0
- package/dist/gui/renderer/fonts/JetBrainsMono-OFL.txt +93 -0
- package/dist/gui/renderer/fonts/JetBrainsMono-Regular.woff2 +0 -0
- package/dist/gui/renderer/index.html +491 -0
- package/dist/gui/renderer/renderer.js +2611 -0
- package/dist/gui/renderer/styles.css +638 -0
- package/dist/kern/anwendungsfaelle.js +688 -65
- package/dist/kern/modell.js +159 -0
- package/dist/ports/harness.js +13 -0
- package/dist/ports/zustand.js +1 -1
- package/package.json +5 -2
package/dist/adapter/skill-md.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Name eines Skills
|
|
1
|
+
// Name, Beschreibung und Besonderheiten eines Skills aus dem Frontmatter der SKILL.md (E32, E39, E55).
|
|
2
2
|
import { parse } from 'yaml';
|
|
3
3
|
export const SKILL_DATEI = 'SKILL.md';
|
|
4
4
|
/** Der Block zwischen der ersten Zeile `---` und der nächsten Zeile `---`. Fehlt er, undefined. */
|
|
@@ -12,38 +12,114 @@ function frontmatter(inhalt) {
|
|
|
12
12
|
return undefined;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* Verzeichnisname. Ein Name mit Pfadtrenner gilt nicht, aus ihm würde im Ziel kein Eintrag,
|
|
18
|
-
* sondern ein Pfad.
|
|
15
|
+
* Das Frontmatter als Objekt, einmal geparst für alle Felder. Fehlt der Block, ist das YAML
|
|
16
|
+
* kaputt oder liest es sich nicht als Objekt, gibt es kein Ergebnis (E32).
|
|
19
17
|
*/
|
|
20
|
-
|
|
18
|
+
function frontmatterDaten(skillMdInhalt) {
|
|
21
19
|
if (skillMdInhalt === undefined)
|
|
22
|
-
return
|
|
20
|
+
return undefined;
|
|
23
21
|
const block = frontmatter(skillMdInhalt);
|
|
24
22
|
if (block === undefined)
|
|
25
|
-
return
|
|
23
|
+
return undefined;
|
|
26
24
|
let daten;
|
|
27
25
|
try {
|
|
28
26
|
daten = parse(block);
|
|
29
27
|
}
|
|
30
28
|
catch {
|
|
31
|
-
return
|
|
29
|
+
return undefined;
|
|
32
30
|
}
|
|
33
31
|
if (typeof daten !== 'object' || daten === null || Array.isArray(daten))
|
|
34
|
-
return
|
|
35
|
-
|
|
32
|
+
return undefined;
|
|
33
|
+
return daten;
|
|
34
|
+
}
|
|
35
|
+
/** Ein Textfeld, getrimmt, leer heißt „nicht vorhanden" (E39). */
|
|
36
|
+
function textFeld(daten, feld) {
|
|
37
|
+
const roh = daten?.[feld];
|
|
36
38
|
if (typeof roh !== 'string')
|
|
37
|
-
return
|
|
38
|
-
const
|
|
39
|
-
|
|
39
|
+
return undefined;
|
|
40
|
+
const wert = roh.trim();
|
|
41
|
+
return wert.length === 0 ? undefined : wert;
|
|
42
|
+
}
|
|
43
|
+
/** Ein boolesches Feld mit dem genannten erwarteten Wert, sonst „nicht vorhanden" (E55). */
|
|
44
|
+
function boolFeld(daten, feld, erwartet) {
|
|
45
|
+
return daten?.[feld] === erwartet ? true : undefined;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Ein Feld, das vorhanden und nicht leer sein muss, unabhängig von seiner Art (E55: hooks,
|
|
49
|
+
* allowed-tools). Leere Liste, leeres Objekt, leerer Text und `false` heißen „nicht vorhanden":
|
|
50
|
+
* beides sind Arten zu sagen, dass es nichts gibt, und die Marke behauptete sonst etwas
|
|
51
|
+
* Sicherheitsrelevantes, das nicht dasteht.
|
|
52
|
+
*/
|
|
53
|
+
function vorhandenFeld(daten, feld) {
|
|
54
|
+
const roh = daten?.[feld];
|
|
55
|
+
if (roh === undefined || roh === null || roh === false)
|
|
56
|
+
return undefined;
|
|
57
|
+
if (typeof roh === 'string')
|
|
58
|
+
return roh.trim().length > 0 ? true : undefined;
|
|
59
|
+
if (Array.isArray(roh))
|
|
60
|
+
return roh.length > 0 ? true : undefined;
|
|
61
|
+
if (typeof roh === 'object')
|
|
62
|
+
return Object.keys(roh).length > 0 ? true : undefined;
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Der Verzeichnisname ist nur Konvention, das Frontmatter ist die Aussage des Autors (E18, E32).
|
|
67
|
+
* Ohne Frontmatter, ohne YAML-Objekt, bei kaputtem YAML oder ohne nicht leeren `name` gilt der
|
|
68
|
+
* Verzeichnisname. Ein Name mit Pfadtrenner gilt nicht, aus ihm würde im Ziel kein Eintrag,
|
|
69
|
+
* sondern ein Pfad.
|
|
70
|
+
*/
|
|
71
|
+
function nameAus(daten, verzeichnisname) {
|
|
72
|
+
const name = textFeld(daten, 'name');
|
|
73
|
+
if (name === undefined || name === '.' || name === '..')
|
|
40
74
|
return verzeichnisname;
|
|
41
75
|
if (name.includes('/') || name.includes('\\'))
|
|
42
76
|
return verzeichnisname;
|
|
43
77
|
return name;
|
|
44
78
|
}
|
|
45
|
-
/**
|
|
46
|
-
export function
|
|
47
|
-
|
|
48
|
-
|
|
79
|
+
/** Name eines Skills aus dem Frontmatter, sonst der Verzeichnisname (E32). */
|
|
80
|
+
export function skillName(verzeichnisname, skillMdInhalt) {
|
|
81
|
+
return nameAus(frontmatterDaten(skillMdInhalt), verzeichnisname);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Beschreibung eines Skills aus dem Feld `description` im Frontmatter (E39), analog zur
|
|
85
|
+
* Namensregel E32: fehlendes Frontmatter, kein YAML-Objekt, kaputtes YAML oder kein nicht leerer
|
|
86
|
+
* Text ⇒ keine Beschreibung, nichts bricht ab.
|
|
87
|
+
*/
|
|
88
|
+
export function skillBeschreibung(skillMdInhalt) {
|
|
89
|
+
return textFeld(frontmatterDaten(skillMdInhalt), 'description');
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Skill aus seinem Pfad in der Quelle: Name nach `skillName`, Beschreibung nach
|
|
93
|
+
* `skillBeschreibung`, Besonderheiten aus dem Frontmatter (E55), jedes Feld nur gesetzt, wenn
|
|
94
|
+
* etwas da ist. Das Frontmatter wird dafür einmal geparst, nicht je Feld: der Katalog einer Quelle
|
|
95
|
+
* geht über alle ihre Skills. `ersatzname` greift nur, wenn der Pfad kein Segment hergibt.
|
|
96
|
+
*/
|
|
97
|
+
export function skillAusPfad(pfad, skillMdInhalt, ersatzname) {
|
|
98
|
+
const verzeichnisname = pfad.split('/').filter((t) => t.length > 0).at(-1) ?? ersatzname ?? pfad;
|
|
99
|
+
const daten = frontmatterDaten(skillMdInhalt);
|
|
100
|
+
const skill = { name: nameAus(daten, verzeichnisname), pfad };
|
|
101
|
+
const beschreibung = textFeld(daten, 'description');
|
|
102
|
+
if (beschreibung !== undefined)
|
|
103
|
+
skill.beschreibung = beschreibung;
|
|
104
|
+
// `disable-model-invocation: true`: lädt erst bei `/name`. `user-invocable: false`: kein `/name`.
|
|
105
|
+
if (boolFeld(daten, 'disable-model-invocation', true))
|
|
106
|
+
skill.nurPerBefehl = true;
|
|
107
|
+
if (boolFeld(daten, 'user-invocable', false))
|
|
108
|
+
skill.nichtPerBefehl = true;
|
|
109
|
+
if (vorhandenFeld(daten, 'hooks'))
|
|
110
|
+
skill.registriertHooks = true;
|
|
111
|
+
if (vorhandenFeld(daten, 'allowed-tools'))
|
|
112
|
+
skill.werkzeugeErlaubt = true;
|
|
113
|
+
const kompatibilitaet = textFeld(daten, 'compatibility');
|
|
114
|
+
if (kompatibilitaet !== undefined)
|
|
115
|
+
skill.kompatibilitaet = kompatibilitaet;
|
|
116
|
+
const modell = textFeld(daten, 'model');
|
|
117
|
+
if (modell !== undefined)
|
|
118
|
+
skill.modell = modell;
|
|
119
|
+
if (textFeld(daten, 'context') === 'fork')
|
|
120
|
+
skill.eigenerKontext = true;
|
|
121
|
+
const argumentHinweis = textFeld(daten, 'argument-hint');
|
|
122
|
+
if (argumentHinweis !== undefined)
|
|
123
|
+
skill.argumentHinweis = argumentHinweis;
|
|
124
|
+
return skill;
|
|
49
125
|
}
|
package/dist/adapter/terminal.js
CHANGED
|
@@ -14,7 +14,7 @@ export class TerminalRueckfrage {
|
|
|
14
14
|
return false;
|
|
15
15
|
const leser = createInterface({ input: process.stdin, output: process.stdout });
|
|
16
16
|
try {
|
|
17
|
-
const antwort = await leser.question(`${frage} `);
|
|
17
|
+
const antwort = await leser.question(`${frage} [j/N] `);
|
|
18
18
|
return JA.has(antwort.trim().toLowerCase());
|
|
19
19
|
}
|
|
20
20
|
finally {
|
|
@@ -16,6 +16,10 @@ export class ZustandJson {
|
|
|
16
16
|
quellen: (daten.quellen ?? []),
|
|
17
17
|
arbeitsverzeichnisse: (daten.arbeitsverzeichnisse ?? []),
|
|
18
18
|
bindungen: (daten.bindungen ?? []),
|
|
19
|
+
// Fehlt das Feld (state.json vor E38), gilt der bisherige Ist-Zustand: nur claude-code aktiv.
|
|
20
|
+
aktiveHarnesses: (daten.aktiveHarnesses ?? ['claude-code']),
|
|
21
|
+
// Fehlt das Feld (state.json vor E43), gilt: nichts ignoriert.
|
|
22
|
+
ignorierteEintraege: (daten.ignorierteEintraege ?? []),
|
|
19
23
|
};
|
|
20
24
|
}
|
|
21
25
|
async schreiben(zustand) {
|
package/dist/cli/hilfe.js
CHANGED
|
@@ -9,23 +9,31 @@ geklontes Vorhaben holt seinen Stand mit hmgr sync.
|
|
|
9
9
|
|
|
10
10
|
hmgr <kommando> [schalter]
|
|
11
11
|
|
|
12
|
-
source add <url|pfad>
|
|
13
|
-
source
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
dir
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
plugin
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
12
|
+
source add <url|pfad> Quelle hinzufügen (URL wird geklont, Pfad bleibt Arbeitskopie)
|
|
13
|
+
source rename <url|pfad> <name> Anzeigename der Quelle ändern
|
|
14
|
+
source remove <url|pfad> Quelle vergessen, Checkouts und Links bleiben liegen
|
|
15
|
+
source list Quellen zeigen
|
|
16
|
+
dir add <pfad> Arbeitsverzeichnis merken und an seinen Zeiger binden
|
|
17
|
+
dir forget <pfad> Arbeitsverzeichnis und Bindung vergessen, Links bleiben
|
|
18
|
+
dir list Arbeitsverzeichnisse mit ihrer Bindung zeigen
|
|
19
|
+
link <skill> Skill in ein Ziel verlinken
|
|
20
|
+
unlink <skill> Link entfernen
|
|
21
|
+
adopt [name] Fremde Links im Ziel durch eigene hmgr-Links ersetzen
|
|
22
|
+
plugin add <name> Plugin in ein Ziel legen (installieren oder Skills verlinken)
|
|
23
|
+
plugin remove <name> Plugin aus einem Ziel entfernen
|
|
24
|
+
plugin list Plugins der Marketplaces aller Quellen
|
|
25
|
+
sync [pfad] Ziel auf den Stand seines Zeigers bringen
|
|
26
|
+
update Alle Checkouts aktualisieren
|
|
27
|
+
status Ist-Zustand der Ziele
|
|
28
|
+
harness list Harness-Typen mit Stand aktiv/inaktiv und vorhanden
|
|
29
|
+
harness enable <name> Harness-Typ aktivieren, hmgr richtet ihn künftig ein
|
|
30
|
+
harness disable <name> Harness-Typ deaktivieren, mit Angebot zum Säubern
|
|
31
|
+
harness skills-dir <name> Verwalteten Skill-Ordner zeigen, festlegen oder entfernen
|
|
26
32
|
|
|
27
33
|
hmgr help <kommando> zeigt Schalter, Beispiele und Zusammenhänge.`;
|
|
28
|
-
const SOURCE = `hmgr source add <url|pfad>
|
|
34
|
+
const SOURCE = `hmgr source add <url|pfad> [--name <name>]
|
|
35
|
+
hmgr source rename <url|pfad> <name>
|
|
36
|
+
hmgr source remove <url|pfad>
|
|
29
37
|
hmgr source list
|
|
30
38
|
|
|
31
39
|
Eine Quelle ist ein Git-Repo mit Skills. source add prüft, ob sie erreichbar ist, liest ihre Skills
|
|
@@ -35,21 +43,45 @@ dort schon liegt, und wird von hmgr nicht verändert.
|
|
|
35
43
|
|
|
36
44
|
Welche Quelle gemeint ist, hängt an Host, Besitzer und Repo, nicht an der Schreibweise der URL. Ein
|
|
37
45
|
Repo in SSH- und in HTTPS-Form ist dieselbe Quelle, mit und ohne .git-Suffix ebenso. Gefetcht wird
|
|
38
|
-
unter der Schreibweise, die beim ersten source add stand.
|
|
46
|
+
unter der Schreibweise, die beim ersten source add stand. source remove trifft dieselbe Quelle auch
|
|
47
|
+
in anderer Schreibweise (E36).
|
|
48
|
+
|
|
49
|
+
Jede Quelle trägt einen Anzeigenamen (E59): ohne --name schlägt hmgr den Repo-Namen vor (letztes
|
|
50
|
+
Pfadsegment, bei einer lokalen Quelle der Ordnername) und speichert ihn. Namen sind eindeutig, trägt
|
|
51
|
+
eine andere geführte Quelle schon denselben, bricht source add ab. source rename ändert den Namen
|
|
52
|
+
später; die Identität der Quelle bleibt dabei ihre URL bzw. ihr Pfad, nicht der Name. Bei einer schon
|
|
53
|
+
bekannten Quelle (source add trifft sie erneut) bleibt ihr Name unverändert.
|
|
54
|
+
|
|
55
|
+
source remove vergisst die Quelle nur aus dem Zustand (E54), wie dir forget das
|
|
56
|
+
Arbeitsverzeichnis (E26): Checkouts und Links bleiben liegen, bestehende Links gelten danach als
|
|
57
|
+
„Link ohne bekannte Quelle" und tauchen so in hmgr status auf, hmgr update prüft sie nicht mehr. Ein
|
|
58
|
+
erneutes source add derselben Quelle macht sie wieder zu normalen Links.
|
|
59
|
+
|
|
60
|
+
Danach bietet hmgr als eigene Rückfrage an, die Skills dieser Quelle komplett vom Rechner zu löschen
|
|
61
|
+
(E58): alle ihre Links in allen Zielen und alle ihre Checkouts, alles oder nichts. Über die
|
|
62
|
+
Harness-CLI installierte Plugins deinstalliert hmgr dabei nicht, sie werden nur genannt, ebenso
|
|
63
|
+
Zeiger-Einträge (E57). Ohne Links und ohne Checkouts kommt die Rückfrage gar nicht erst. Ablehnen
|
|
64
|
+
lässt alles liegen wie bisher.
|
|
39
65
|
|
|
40
|
-
Schalter:
|
|
66
|
+
Schalter:
|
|
67
|
+
--name <name> nur bei add: Anzeigename statt des abgeleiteten Vorschlags
|
|
41
68
|
|
|
42
69
|
Beispiele:
|
|
43
70
|
hmgr source add https://github.com/tim/skills.git
|
|
44
|
-
hmgr source add ~/.skills/tim-skills
|
|
71
|
+
hmgr source add ~/.skills/tim-skills --name tim-skills
|
|
72
|
+
hmgr source rename https://github.com/tim/skills.git meine-skills
|
|
73
|
+
hmgr source remove https://github.com/tim/skills.git
|
|
45
74
|
hmgr source list
|
|
46
75
|
|
|
47
76
|
Häufige Fälle:
|
|
48
77
|
„Skill … liegt in keiner Quelle": die Quelle fehlt, erst source add, dann link.
|
|
49
78
|
Neue Commits einer bekannten Quelle holt hmgr update, nicht source add.
|
|
50
79
|
„Quelle ist schon bekannt": dasselbe Repo steht schon im Zustand, hier in anderer Schreibweise.
|
|
80
|
+
„Quelle … ist nicht bekannt": source remove und source rename kennen nur geführte Quellen,
|
|
81
|
+
hmgr source list zeigt sie.
|
|
82
|
+
„Name … ist schon vergeben": einen anderen Namen wählen, mit --name bzw. source rename.
|
|
51
83
|
|
|
52
|
-
Siehe auch: hmgr help link, hmgr help plugin, hmgr help update`;
|
|
84
|
+
Siehe auch: hmgr help link, hmgr help plugin, hmgr help update, hmgr help status`;
|
|
53
85
|
const DIR = `hmgr dir add <pfad> [--composer <pfad>]
|
|
54
86
|
hmgr dir forget <pfad>
|
|
55
87
|
hmgr dir list
|
|
@@ -57,7 +89,8 @@ hmgr dir list
|
|
|
57
89
|
Ein Arbeitsverzeichnis ist ein Verzeichnis, in dem ein Harness gestartet wird. dir add merkt es und
|
|
58
90
|
bindet es an seinen Zeiger, also an die composer.json, in deren extra-Abschnitt Quellen, Skills und
|
|
59
91
|
Plugins des Vorhabens stehen. Ohne Zeiger bleibt das Verzeichnis gemerkt und jeder Link dort lokal
|
|
60
|
-
(E26). dir forget löst Bindung und Eintrag, die gelegten Links bleiben liegen.
|
|
92
|
+
(E26). dir forget löst Bindung und Eintrag, die gelegten Links bleiben liegen. Gebunden wird nur für
|
|
93
|
+
Harnesses, die hmgr verwaltet: standardmäßig nur claude-code (E38).
|
|
61
94
|
|
|
62
95
|
Schalter:
|
|
63
96
|
--composer <pfad> nur bei add: composer.json wählen, wenn unter dem Verzeichnis mehrere in
|
|
@@ -74,13 +107,16 @@ Häufige Fälle:
|
|
|
74
107
|
link --ort dir:<pfad> merkt das Verzeichnis von selbst. dir add braucht es vorher nur, wenn die
|
|
75
108
|
composer.json mehrdeutig ist.
|
|
76
109
|
|
|
77
|
-
Siehe auch: hmgr help link, hmgr help sync`;
|
|
110
|
+
Siehe auch: hmgr help link, hmgr help sync, hmgr help harness`;
|
|
78
111
|
const LINK = `hmgr link <skill> [schalter]
|
|
79
112
|
|
|
80
113
|
Legt im Ziel einen Symlink auf den Skill an, der aus einer bekannten Quelle stammt, und trägt ihn
|
|
81
114
|
in den Zeiger des Ziels ein, damit hmgr sync ihn anderswo reproduzieren kann. Einen Zeiger gibt es
|
|
82
115
|
nur für ein Arbeitsverzeichnis mit composer.json, an Home und Profil bleibt jeder Link lokal.
|
|
83
116
|
|
|
117
|
+
Das Schreiben in einen Zeiger ist gesperrt, bis das Composer-Thema entschieden ist (E57): an einem
|
|
118
|
+
Arbeitsverzeichnis mit Zeiger bricht link ohne --local ab, der Link wird nicht gelegt.
|
|
119
|
+
|
|
84
120
|
Schalter:
|
|
85
121
|
--harness <name> claude-code, hermes oder agents, Standard claude-code
|
|
86
122
|
--ort <ort> home, dir:<pfad> oder profil:<name>, Standard home. profil kennt nur hermes
|
|
@@ -108,6 +144,9 @@ const UNLINK = `hmgr unlink <skill> [schalter]
|
|
|
108
144
|
Entfernt den Link aus dem Ziel und, wenn das Ziel an einen Zeiger gebunden ist, den Skill aus dem
|
|
109
145
|
Zeiger. Der Checkout unter ~/.hmgr bleibt liegen, Links anderer Ziele bleiben unberührt.
|
|
110
146
|
|
|
147
|
+
Das Schreiben in einen Zeiger ist gesperrt, bis das Composer-Thema entschieden ist (E57): an einem
|
|
148
|
+
Arbeitsverzeichnis mit Zeiger bricht unlink ohne --local ab, der Link bleibt liegen.
|
|
149
|
+
|
|
111
150
|
Schalter:
|
|
112
151
|
--harness <name> claude-code, hermes oder agents, Standard claude-code
|
|
113
152
|
--ort <ort> home, dir:<pfad> oder profil:<name>, Standard home. profil kennt nur hermes
|
|
@@ -130,6 +169,10 @@ ein Link stammt, nimmt deren remote.origin.url als Quelle, legt einen Checkout a
|
|
|
130
169
|
und verlinkt den Skill daraus. Ohne Namen laufen alle fremden Einträge des Ziels durch, mit Namen
|
|
131
170
|
nur dieser eine. Was sich nicht auflösen lässt, bleibt liegen und wird mit Grund gemeldet.
|
|
132
171
|
|
|
172
|
+
Das Schreiben in einen Zeiger ist gesperrt, bis das Composer-Thema entschieden ist (E57): an einem
|
|
173
|
+
Arbeitsverzeichnis mit Zeiger bricht adopt ohne --local ab, bevor etwas übernommen wird. Der
|
|
174
|
+
Probelauf bleibt frei, er schreibt ohnehin nichts.
|
|
175
|
+
|
|
133
176
|
Schalter:
|
|
134
177
|
--harness <name> claude-code, hermes oder agents, Standard claude-code
|
|
135
178
|
--ort <ort> home, dir:<pfad> oder profil:<name>, Standard home. profil kennt nur hermes
|
|
@@ -159,6 +202,10 @@ Plugin von dessen CLI installieren, sonst verlinkt es die flache Skill-Liste des
|
|
|
159
202
|
seinen Abhängigkeiten. In den Zeiger kommt das Plugin, nicht seine Einzelskills. plugin list zeigt
|
|
160
203
|
die Marketplaces aller bekannten Quellen mit ihren Plugins.
|
|
161
204
|
|
|
205
|
+
Das Schreiben in einen Zeiger ist gesperrt, bis das Composer-Thema entschieden ist (E57): an einem
|
|
206
|
+
Arbeitsverzeichnis mit Zeiger brechen add und remove ohne --local ab, nichts wird installiert,
|
|
207
|
+
verlinkt oder entfernt.
|
|
208
|
+
|
|
162
209
|
Schalter (add und remove):
|
|
163
210
|
--harness <name> claude-code, hermes oder agents, Standard claude-code
|
|
164
211
|
--ort <ort> home, dir:<pfad> oder profil:<name>, Standard home. profil kennt nur hermes
|
|
@@ -185,7 +232,8 @@ Bringt ein Arbeitsverzeichnis auf den Stand seines Zeigers: fehlende Quellen üb
|
|
|
185
232
|
Links legen, Links auf einen anderen Ref umlegen, Plugins herstellen. Ohne Pfad gilt das aktuelle
|
|
186
233
|
Verzeichnis. Das ist der Befehl nach einem frischen Clone eines Vorhabens und nach jeder Änderung
|
|
187
234
|
am Zeiger. Eigene Links, die im Zeiger fehlen, werden als abweichend gemeldet und nicht entfernt,
|
|
188
|
-
fremde Einträge bleiben unberührt.
|
|
235
|
+
fremde Einträge bleiben unberührt. Eingerichtet wird nur für Harnesses, die hmgr verwaltet:
|
|
236
|
+
standardmäßig nur claude-code (E38).
|
|
189
237
|
|
|
190
238
|
Schalter: keine.
|
|
191
239
|
|
|
@@ -200,7 +248,7 @@ Häufige Fälle:
|
|
|
200
248
|
hmgr unlink <skill> --ort dir:<pfad> --local entfernen.
|
|
201
249
|
„Kein Harness auf diesem Rechner": weder ~/.claude noch ~/.hermes noch ~/.agents ist angelegt.
|
|
202
250
|
|
|
203
|
-
Siehe auch: hmgr help dir, hmgr help link, hmgr help update`;
|
|
251
|
+
Siehe auch: hmgr help dir, hmgr help link, hmgr help update, hmgr help harness`;
|
|
204
252
|
const UPDATE = `hmgr update
|
|
205
253
|
|
|
206
254
|
Holt für jeden Checkout unter ~/.hmgr den neuesten Stand seines Refs und zieht bei Harnesses mit
|
|
@@ -232,9 +280,11 @@ Siehe auch: hmgr help sync, hmgr help status`;
|
|
|
232
280
|
const STATUS = `hmgr status
|
|
233
281
|
|
|
234
282
|
Liest den Ist-Zustand vom Dateisystem: je Ziel eines vorhandenen Harness die Einträge mit Quelle
|
|
235
|
-
und Ref, davor die Versionseinschränkung, falls der Zeiger eine nennt.
|
|
236
|
-
|
|
237
|
-
|
|
283
|
+
und Ref, davor die Versionseinschränkung, falls der Zeiger eine nennt. Dahinter steht der
|
|
284
|
+
abgeleitete Grund des Links: das Plugin, zu dem er gehört, oder „über Zeiger", von Hand gelegte
|
|
285
|
+
Links bleiben ohne Zusatz. Fremde Einträge und Links ohne bekannte Quelle sind eigens
|
|
286
|
+
gekennzeichnet, dazu kommen die Plugins des Ziels. Am Ende stehen die Harnesses, die auf diesem
|
|
287
|
+
Rechner nicht liegen.
|
|
238
288
|
|
|
239
289
|
Schalter: keine.
|
|
240
290
|
|
|
@@ -249,6 +299,58 @@ Häufige Fälle:
|
|
|
249
299
|
überspringt seine Ziele.
|
|
250
300
|
|
|
251
301
|
Siehe auch: hmgr help adopt, hmgr help sync`;
|
|
302
|
+
const HARNESS = `hmgr harness list
|
|
303
|
+
hmgr harness enable <name>
|
|
304
|
+
hmgr harness disable <name>
|
|
305
|
+
hmgr harness skills-dir <name> [--profil <name>]
|
|
306
|
+
hmgr harness skills-dir <name> add <pfad> [--profil <name>]
|
|
307
|
+
hmgr harness skills-dir <name> remove [--profil <name>]
|
|
308
|
+
|
|
309
|
+
Welche Harness-Typen hmgr verwaltet, ist eine Einstellung, kein gescannter Zustand: nur für aktive
|
|
310
|
+
Harnesses richten dir add und sync Ziele ein, standardmäßig nur claude-code (E38). harness list zeigt
|
|
311
|
+
alle bekannten Harness-Typen mit ihrem Stand: aktiv oder inaktiv, dazu vorhanden oder nicht vorhanden
|
|
312
|
+
(auf diesem Rechner installiert oder nicht). enable und disable sind idempotent, ein zweites Mal
|
|
313
|
+
ändert nichts und ist kein Fehler.
|
|
314
|
+
|
|
315
|
+
disable säubert nicht von selbst: liegen noch eigene Links oder eine harness-eigene Konfiguration wie
|
|
316
|
+
Hermes' external_dirs-Eintrag, fragt hmgr, ob sie entfernt werden sollen. Ohne Terminal, etwa in einem
|
|
317
|
+
Script, gilt Nein und die Konfiguration bleibt liegen. Ein Link mit ausdrücklich genanntem --harness
|
|
318
|
+
(hmgr link, hmgr plugin add) legt weiterhin an jedem vorhandenen Harness an, aktiv oder nicht, das ist
|
|
319
|
+
Sache des Nutzers.
|
|
320
|
+
|
|
321
|
+
skills-dir zeigt, legt fest oder entfernt den Ordner, aus dem Hermes externe Skills liest
|
|
322
|
+
(skills.external_dirs in seiner config.yaml, E13, E56). hmgr verwaltet je Ziel (Home oder ein Profil
|
|
323
|
+
mit --profil) genau einen Eintrag, den ersten unterhalb des Hermes-Home, ohne Hermes' eigenen Ordner
|
|
324
|
+
„skills"; alle anderen Einträge der config.yaml rührt hmgr nicht an. add erlaubt nur einen Pfad
|
|
325
|
+
unterhalb des Hermes-Home und legt ihn an, falls er fehlt; ein zweiter add ohne vorheriges remove ist
|
|
326
|
+
ein Fehler. remove löscht nur den Eintrag aus der config.yaml, der Ordner bleibt liegen; danach fragt
|
|
327
|
+
hmgr (mit Inhaltsangabe), ob der Ordner samt Inhalt gelöscht werden soll. Ohne Terminal, etwa in einem
|
|
328
|
+
Script, gilt Nein und der Ordner bleibt liegen, ohne weitere Meldung. Ohne verwalteten Eintrag richtet
|
|
329
|
+
das nächste hmgr link wieder den Standard-Ordner external-skills ein (E13). Hermes übernimmt eine
|
|
330
|
+
Änderung an external_dirs ohne Neustart.
|
|
331
|
+
|
|
332
|
+
Schalter (nur skills-dir):
|
|
333
|
+
--profil <name> Ziel ist das genannte Profil statt Home
|
|
334
|
+
|
|
335
|
+
Beispiele:
|
|
336
|
+
hmgr harness list
|
|
337
|
+
hmgr harness enable hermes
|
|
338
|
+
hmgr harness disable hermes
|
|
339
|
+
hmgr harness skills-dir hermes
|
|
340
|
+
hmgr harness skills-dir hermes add ~/.hermes/external-skills
|
|
341
|
+
hmgr harness skills-dir hermes remove --profil researcher
|
|
342
|
+
|
|
343
|
+
Häufige Fälle:
|
|
344
|
+
„ist kein bekannter Harness-Typ": hmgr harness list zeigt die bekannten Namen.
|
|
345
|
+
Konfiguration bleibt nach disable liegen, wenn die Rückfrage mit Nein oder ohne Terminal beantwortet
|
|
346
|
+
wird. Ein erneutes hmgr harness disable <name> bietet das Säubern wieder an.
|
|
347
|
+
„kennt keinen verwalteten Skill-Ordner": skills-dir kennt heute nur hermes.
|
|
348
|
+
„ist schon ein Skill-Ordner verwaltet": erst hmgr harness skills-dir <name> remove, dann add.
|
|
349
|
+
„ist kein Skill-Ordner verwaltet": remove kennt nur einen vorhandenen Eintrag, add legt ihn fest.
|
|
350
|
+
„liegt nicht unterhalb des Hermes-Home" oder „ist Hermes' eigener Skill-Ordner": einen anderen
|
|
351
|
+
Pfad unter ~/.hermes (bzw. dem Profil-Ordner) nennen, nicht „skills" selbst.
|
|
352
|
+
|
|
353
|
+
Siehe auch: hmgr help dir, hmgr help sync, hmgr help status`;
|
|
252
354
|
/** Ebene 2, je Kommandofamilie ein Text. Unterkommandos teilen sich die Hilfe ihrer Familie. */
|
|
253
355
|
const THEMEN = new Map([
|
|
254
356
|
['source', SOURCE],
|
|
@@ -260,6 +362,7 @@ const THEMEN = new Map([
|
|
|
260
362
|
['sync', SYNC],
|
|
261
363
|
['update', UPDATE],
|
|
262
364
|
['status', STATUS],
|
|
365
|
+
['harness', HARNESS],
|
|
263
366
|
['help', HILFE],
|
|
264
367
|
]);
|
|
265
368
|
/** Hilfetext zu einem Kommando, undefined für ein unbekanntes Thema. */
|