strom-research 1.2.0 → 1.3.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.
package/README.md CHANGED
@@ -61,6 +61,9 @@ npm: `npm install -g strom-research@latest`.
61
61
  read the result — or on and on (`strom run --loop`) while a condition of
62
62
  yours allows it: a gate plugin, e.g. `claude-usage 10` (your Claude
63
63
  subscription's daily ration, 10 points in hand), or one of your own (`strom gate list`)
64
+ - Hear what it finds as it finds it: a hook plugin of yours is told of every
65
+ save — a person added, a session closed — and can send it to your phone
66
+ (`strom hook on <name>`, the interface in `plugins/hooks/README.md`)
64
67
  - Several agents can work on one family tree side by side, each on its own task
65
68
 
66
69
  **Evidence first**
@@ -59,7 +59,7 @@
59
59
  "ui.menu.start": "Začít výzkum s agentem",
60
60
  "ui.menu.run": "Nechat agenta pracovat samotného",
61
61
  "ui.menu.waitlist": "Co čeká na vás",
62
- "ui.menu.settings": "Nastavení",
62
+ "ui.menu.settings": "Nastavení: agent, samostatná práce, zprávy, archivy, kontrola",
63
63
  "ui.menu.doctor": "Kontrola instalace",
64
64
  "ui.menu.trees": "Jiný rodokmen",
65
65
  "ui.menu.newtree": "Založit rodokmen",
@@ -415,9 +415,7 @@
415
415
  "ui.card.partner": "Partner: {name}",
416
416
  "ui.card.unknown": "zatím neznámý",
417
417
  "ui.card.children": "Děti: {names}",
418
- "ui.card.story": "Vyprávění ({status}):",
419
- "ui.card.story.draft": "koncept",
420
- "ui.card.story.final": "schválené",
418
+ "ui.card.story": "Vyprávění:",
421
419
  "ui.stats.title": "{name} – přehled výzkumu",
422
420
  "ui.stats.counts": "Osoby: {persons} · rodiny: {families} · záznamy z pramenů: {sources} · snímky: {images} · místa: {places}",
423
421
  "ui.stats.facts": "Údaje: doložené {proven} · pravděpodobné {probable} · možné {possible} · jen stopy {lead}",
@@ -429,7 +427,7 @@
429
427
  "ui.stats.sessions": "Sezení agenta: {n} · poslední {last}",
430
428
  "ui.stats.cost": " · dosavadní cena {cost}",
431
429
  "ui.stats.cost.partial": " (bez přerušených sezení, která cenu neřekla: {n})",
432
- "ui.stats.stories": "Vyprávění: {n} (schválená {final})",
430
+ "ui.stats.stories": "Vyprávění: {n}",
433
431
  "ui.ped.noparents": "rodiče zatím neznámí",
434
432
  "ui.ped.nofather": "otec zatím neznámý",
435
433
  "ui.ped.nomother": "matka zatím neznámá",
@@ -446,6 +444,20 @@
446
444
  "ui.recent.sessions": "Co dělal agent:",
447
445
  "ui.recent.more": "… a další: {n}",
448
446
  "ui.browse.plan": "Co agent udělá dál",
447
+ "ui.review.new": "{name} — nových úkolů: {n}",
448
+ "ui.review.nothing": "{name} — nic nového k revizi",
449
+ "ui.review.would": " přidal by: {level} · {what}",
450
+ "ui.review.dry": "(zkouška nanečisto — nic se nezapsalo)",
451
+ "ui.review.covered": " {name}: už to pokrývá {task} ({state}) — {what}",
452
+ "ui.review.wake": " pokračovat v něm: strom task wake {task}",
453
+ "ui.review.exhausted": " {name}: hledáno bez výsledku ({tasks}) — co dál, rozhodnete vy",
454
+ "ui.review.open": "Otevřených úkolů v {research}: {n}, asi tolik sezení",
455
+ "ui.review.cost": " — sezení tu stojí v průměru ${cost}",
456
+ "ui.review.next": "dál: strom run --research {research} (agent sám) · nebo v rozhovoru: strom session start --research {research}",
457
+ "ui.review.state.open": "ve frontě",
458
+ "ui.review.state.doing": "rozpracovaný",
459
+ "ui.review.state.parked": "odložený",
460
+ "ui.review.state.waiting": "čeká na vás",
449
461
  "ui.plan.title": "Co agent udělá dál – {name}:",
450
462
  "ui.plan.now": "právě teď",
451
463
  "ui.plan.images": " (nejdřív potřebuje snímky)",
@@ -489,5 +501,149 @@
489
501
  "ui.consent.gate.set": "Nechat podmínku „{name}“ rozhodovat, kdy agent pracující sám pokračuje?",
490
502
  "ui.consent.gate.unset": "Odebrat podmínku „{name}“ — agent pracující sám se jí už nebude ptát?",
491
503
  "ui.consent.gate.skip": "Nechat agenta pracovat samotného bez podmínky „{name}“?",
492
- "ui.run.others": "⚠ V tomto rodokmenu už pracuje jiný běh (od {since}): tento si vezme jiné úkoly – náklady se sčítají."
504
+ "ui.consent.remote": "Spouštět sezení Claude Code, která strom otevírá, se vzdáleným ovládáním (Remote Control), abyste je mohli sledovat a řídit z claude.ai nebo z aplikace Claude v telefonu?",
505
+ "ui.consent.hook.on": "Nechat hook „{name}“, aby se dozvídal všechno, co se uloží do vašich výzkumů? Je to program na tomto počítači a udělá s tím, k čemu byl napsán.",
506
+ "ui.consent.hook.off": "Přestat hooku „{name}“ hlásit, co se ukládá?",
507
+ "ui.run.others": "⚠ V tomto rodokmenu už pracuje jiný běh (od {since}): tento si vezme jiné úkoly – náklady se sčítají.",
508
+ "ui.menu.more": "Rozšířit výzkum: podklady, nový směr, revize osoby",
509
+ "ui.more.title": "Rozšířit výzkum",
510
+ "ui.more.intake": "Přidat podklady: dokumenty, fotky, rodokmen z jiného programu, co víte",
511
+ "ui.more.research": "Nový směr výzkumu: předkové nebo potomci někoho dalšího, nebo jedna otázka",
512
+ "ui.intake.what": "Co přinášíte?",
513
+ "ui.intake.files": "Soubory nebo složku z počítače",
514
+ "ui.intake.text": "Co víte – jména, data, místa, rodinné vzpomínky",
515
+ "ui.intake.write": "Napište, co víte (Enter nebo 0 vrátí zpět)",
516
+ "ui.intake.path": "Složka nebo soubor – můžete je sem přetáhnout myší (Enter nebo 0 vrátí zpět)",
517
+ "ui.intake.missing": "Nenašel jsem: {path} – zkontrolujte cestu, nebo složku přetáhněte myší.",
518
+ "ui.intake.scans": "Ve složce {folder} je {n} obrázků. Jsou to rodinné dokumenty a fotky? (ne: skeny matriky nebo jiné knihy)",
519
+ "ui.intake.book": "{folder}: skeny matriky nebo jiné knihy patří k té knize – řekněte agentovi v rozhovoru, odkud jsou, a zaeviduje si je.",
520
+ "ui.intake.known": "Tyhle podklady už ve výzkumu jsou – nic nepřibylo.",
521
+ "ui.intake.done": "✓ Přidáno do výzkumu: {n}. Agent to projde při další práci.",
522
+ "ui.intake.chat": "Projít to s agentem hned?",
523
+ "ui.intake.say": "Do výzkumu jsem přidal(a) nové podklady – pojďme je projít.",
524
+ "ui.research.kind": "Co chcete zkoumat?",
525
+ "ui.research.ancestors": "Předky jedné osoby",
526
+ "ui.research.descendants": "Potomky jedné osoby",
527
+ "ui.research.question": "Jednu otázku (třeba: kdo byl otec Marie?)",
528
+ "ui.research.ask": "Jaká je otázka? (Enter nebo 0 vrátí zpět)",
529
+ "ui.research.whom": "Koho se to týká?",
530
+ "ui.research.known": "Někoho, kdo už je v rodokmenu",
531
+ "ui.research.newperson": "Někoho nového",
532
+ "ui.research.name": "Jméno a příjmení (třeba Jan Novák; 0 vrátí zpět)",
533
+ "ui.research.sex": "Muž, nebo žena?",
534
+ "ui.research.male": "Muž",
535
+ "ui.research.female": "Žena",
536
+ "ui.research.unknown": "Nevím",
537
+ "ui.research.title": "Jak výzkum pojmenovat?",
538
+ "ui.research.title.ancestors": "Předci: {name}",
539
+ "ui.research.title.descendants": "Potomci: {name}",
540
+ "ui.research.knows": "Co o tom víte? Data, místa a rodinné historky agentovi pomohou (Enter: nic)",
541
+ "ui.research.done": "✓ Výzkum „{name}“ je založený.",
542
+ "ui.research.chat": "Začít na něm s agentem hned?",
543
+ "ui.research.say": "Založil(a) jsem nový výzkum „{name}“ – pojďme s ním začít.",
544
+ "ui.settings.title": "Nastavení (na tomto počítači)",
545
+ "ui.settings.wizard": "Jazyk, agent, model, co smí agent sám, příběhy… (průvodce nastavením)",
546
+ "ui.settings.alone": "Samostatná práce agenta: {minutes} min na úkol · podmínka: {gate}",
547
+ "ui.settings.gate.none": "žádná",
548
+ "ui.settings.hooks": "Zprávy o tom, co se uloží (hooky): {state}",
549
+ "ui.settings.on": "zapnuto",
550
+ "ui.settings.off": "vypnuto",
551
+ "ui.settings.remote": "Sledovat agenta z telefonu (Remote Control): {state}",
552
+ "ui.settings.remote.about": "Když je zapnuté, můžete sezení Claude Code, která strom spustí – rozhovory i samostatnou práci – sledovat a řídit z claude.ai nebo z aplikace Claude v telefonu.",
553
+ "ui.settings.remote.on": "Zapnout?",
554
+ "ui.settings.remote.off": "Vypnout?",
555
+ "ui.settings.archives": "Archivy: vaše přihlášení, souhlas se stahováním",
556
+ "ui.alone.title": "Samostatná práce agenta",
557
+ "ui.alone.minutes": "Čas na jeden úkol: {minutes} min",
558
+ "ui.alone.minutes.ask": "Kolik minut smí trvat jeden úkol? (5–600; 0 vrátí zpět)",
559
+ "ui.alone.minutes.bad": "Napište prosím počet minut od 5 do 600.",
560
+ "ui.alone.gate": "Práce pořád dál pod podmínkou: {gate}",
561
+ "ui.alone.gate.about": "Podmínka se ptá před každým sezením, když agent pracuje pořád dál sám; menu to nabídne, jen když je nastavená. Úkoly, které spustíte sami, jsou vaše volba.",
562
+ "ui.alone.gate.pick": "Jaká podmínka?",
563
+ "ui.alone.gate.claude": "O kolik bodů má týdenní spotřeba vašeho předplatného Claude zaostávat za uplynulou částí týdne? (den ≈ 14,3; 0: jen nepředbíhat týden)",
564
+ "ui.alone.gate.args": "Co jí předat (Enter: nic)",
565
+ "ui.alone.test": "Co by podmínka řekla teď?",
566
+ "ui.alone.asking": "Ptám se podmínky…",
567
+ "ui.alone.said.go": "Teď by se začalo{reason}",
568
+ "ui.alone.said.wait": "Čekalo by se do {at}{reason}",
569
+ "ui.alone.said.stop": "Skončilo by se{reason}",
570
+ "ui.alone.said.error": "Podmínka neodpověděla, jak má{reason}",
571
+ "ui.hooks.title": "Hooky – číslo ho zapne nebo vypne:",
572
+ "ui.hooks.on": "{name}: zapnuto",
573
+ "ui.hooks.off": "{name}: vypnuto",
574
+ "ui.hooks.none": "Zatím tu žádné hooky nejsou. Hook je váš vlastní program, kterému strom hlásí, co se uloží (třeba zpráva do telefonu) – jak na to: {readme}",
575
+ "ui.archives.title": "Stahovače archivů na tomto počítači:",
576
+ "ui.archives.empty": "Zatím tu žádné stahovače archivů nejsou – agent si ho vytvoří, až bude výzkum archiv potřebovat.",
577
+ "ui.archives.login.saved": "vaše přihlášení uložené {date}",
578
+ "ui.archives.login.none": "umí použít váš účet – přihlášení neuložené",
579
+ "ui.archives.consent": "Stahovače se vás ptají, než začnou: {state}",
580
+ "ui.archives.consent.about": "Vypnuto (obvyklé): stahovače běží samy – pomalu a jen do svého archivu. Zapnuto: každý nejdřív potřebuje vaše ano, tady v terminálu, a stejně tak každý archiv, kam se připojí.",
581
+ "ui.archives.consent.on": "Zapnout?",
582
+ "ui.archives.consent.off": "Vypnout?",
583
+ "ui.hooks.nothing": "žádné",
584
+ "ui.menu.noagent": "Na počítači zatím není žádný AI agent – výzkum dělá on. Volba 1 ho nainstaluje.",
585
+ "ui.menu.getagent": "Nainstalovat nebo vybrat AI agenta",
586
+ "ui.menu.update.where": "Vyšla nová verze stromu: {version} – aktualizovat ji můžete v Nastavení (volba {key}).",
587
+ "ui.more.noagent": "Agent se do toho pustí, až bude na počítači (volba 1 v menu).",
588
+ "ui.menu.noagent.chosen": "AI agent, kterého výzkum používá, na počítači není – volba 1 vybere jiného.",
589
+ "task.answer": "Odpověď uživatele (na: {asked}): {answer}",
590
+ "ui.waiting.title": "Agent od vás potřebuje ({n}):",
591
+ "ui.waiting.do": "Co udělat: {what}",
592
+ "ui.waiting.ask": "agent vám to řekne v rozhovoru",
593
+ "ui.waiting.images": "Uložit ručně: snímky {images} z {book}",
594
+ "ui.waiting.more": "…a další ({n}) – agent je s vámi projde v rozhovoru.",
595
+ "ui.waiting.pick": "Máte to? Vyberte číslo a napište, co jste zjistili:",
596
+ "ui.waiting.answer": "Odpovědět k {k}: {what}",
597
+ "ui.waiting.folder": "Otevřít složku pro snímky k {k}",
598
+ "ui.waiting.opened": "Složka: {dir} – až tam snímky budou, agent si je při další práci převezme sám.",
599
+ "ui.waiting.write": "Vaše odpověď – odkaz, číslo knihy, co jste zjistili (Enter nebo 0 vrátí zpět)",
600
+ "ui.waiting.back": "✓ Úkol se vrátil agentovi i s vaší odpovědí.",
601
+ "ui.waiting.chat": "Pokračovat s agentem hned?",
602
+ "ui.waiting.say": "Odpověděl(a) jsem na to, co jste ode mě potřebovali: {what} – pojďme na to.",
603
+ "ui.intake.empty": "Není v tom nic, co by se dalo přidat.",
604
+ "ui.intake.ours": "{path} je složka samotného stromu (výzkumu), ne rodinné podklady.",
605
+ "ui.research.exists": "Takový výzkum už je: „{name}“ – agent v něm pokračuje.",
606
+ "ui.alone.gate.bad": "Napište prosím počet bodů od 0 do 100 (třeba 10).",
607
+ "ui.waiting.long": "Na odpověď sem je to dlouhé (nejvýš {n} znaků) – stačí odkaz nebo věta, zbytek řekněte agentovi v rozhovoru.",
608
+ "ui.settings.remote.chats": "rozhovory ano, samostatná práce ne",
609
+ "ui.settings.remote.own": "Rozhovory s agentem už z telefonu sledovat můžete – zapíná to sám Claude Code (jeho vlastní nastavení). Samostatnou práci agenta (volba 2 v menu) až když zapnete i tohle.",
610
+ "ui.settings.remote.both": "rozhovory i samostatná práce",
611
+ "ui.settings.remote.onalone": "Zapnout to i pro samostatnou práci?",
612
+ "ui.archives.login.nobody": "Žádný z nich přihlášení nepotřebuje – archivy jsou volně přístupné. Přihlášení se tu objeví jen u stahovače portálu s účtem (třeba placeným).",
613
+ "ui.archives.login.how": "Přihlášení napíšete tady a zůstane jen na tomto počítači; strom ho vkládá do požadavků stahovače – stahovač ani agent ho neuvidí.",
614
+ "ui.archives.login.save": "Uložit přihlášení do {title}",
615
+ "ui.archives.login.change": "Změnit přihlášení do {title}",
616
+ "ui.home.what": "Výzkum je ve složce {from} (rodokmeny: {trees}) i se sdílenou složkou – stahovače, hooky, schránka na snímky, velké snímky. Přesune se do {to} celý.",
617
+ "ui.home.sure": "Přesunout ho tam?",
618
+ "ui.home.moved": "✓ Výzkum je teď ve složce {to}.",
619
+ "ui.home.copied": "✓ Výzkum je zkopírovaný do {to} (jiný disk) a pracuje se v něm odtud. Původní složka {from} zůstala, jak byla – až uvidíte, že je vše v pořádku, můžete ji smazat.",
620
+ "ui.home.stays": "Výzkum zůstává ve složce {from}.",
621
+ "ui.home.inside": "{to} je uvnitř složky výzkumu {from} (nebo naopak) – vyberte složku mimo ni.",
622
+ "ui.home.notEmpty": "Ve složce {to} už něco je – výzkum se přesune jen do prázdné nebo nové složky.",
623
+ "ui.home.busy": "V rodokmenu {trees} teď někdo pracuje (agent, samostatná práce nebo živé sledování v aplikaci Strom) – výzkum půjde přesunout, až skončí.",
624
+ "ui.home.failed": "Přesunout se nepodařilo ({reason}) – nic se nezměnilo.",
625
+ "ui.app.notinstalled": "Aplikace Strom na tomto počítači ještě není nainstalovaná. Nainstalovat ji teď jako aplikaci z prohlížeče (zdarma; strom ukáže, kam kliknout)?",
626
+ "ui.browser.agent": "{names}: stahuje se přes prohlížeč – to umí jen Claude Code (rozšíření Claude in Chrome); výzkum teď dělá {agent}. Snímky z těchto archivů uložte ručně, nebo výzkum svěřte Claude Code (strom agents use claude).",
627
+ "ui.browser.noext": "{names}: stahuje se přes prohlížeč – Chrome k tomu potřebuje rozšíření Claude in Chrome přihlášené ke stejnému účtu jako Claude Code; tady ho v žádném prohlížeči nevidím: {url}",
628
+ "ui.doc.browser": "prohlížeč (Claude in Chrome)",
629
+ "ui.doc.browser.ok": "rozšíření v {browsers} – při práci agenta musí Chrome běžet",
630
+ "ui.doc.browser.noext": "rozšíření není nainstalované (potřebuje ho {names})",
631
+ "ui.doc.browser.agent": "{names} stahují přes prohlížeč – to umí jen Claude Code (teď: {agent})",
632
+ "ui.archives.via.direct": "snímky přímo, strom hlídá tempo",
633
+ "ui.archives.via.browser": "snímky přes váš prohlížeč",
634
+ "ui.archives.via.manual": "snímky se ukládají ručně (archiv automatické stahování nedovoluje)",
635
+ "ui.archives.browser.ok": "Přes prohlížeč: rozšíření Claude in Chrome je v {browsers}; při práci agenta musí Chrome běžet a rozšíření být přihlášené ke stejnému účtu jako Claude Code.",
636
+ "ui.archives.to.browser": "{title}: stahovat raději přes váš prohlížeč",
637
+ "ui.archives.to.direct": "{title}: stahovat raději přímo",
638
+ "ui.archives.browser.about": "Přes prohlížeč stahuje agent snímky ve vašem vlastním Chrome (kde jste do archivu přihlášení), s rozšířením Claude in Chrome – to umí jen Claude Code. Strom dál plánuje a hlídá tempo každého požadavku.",
639
+ "ui.archives.direct.about": "Přímo stahuje snímky strom sám, v tempu, bez prohlížeče – zvládne to každý agent.",
640
+ "ui.archives.switch": "Přepnout?",
641
+ "ui.archives.now.browser": "✓ {title}: odteď přes váš prohlížeč.",
642
+ "ui.archives.now.direct": "✓ {title}: odteď přímo.",
643
+ "ui.setup.home.again": "Kam ukládat výzkum (0 ho nechá, kde je)",
644
+ "ui.home.env": "Složku výzkumu {from} určuje nastavení zvenčí (STROM_HOME) – zůstává; změňte ji tam.",
645
+ "ui.menu.failed": "Tohle se nepovedlo: {reason}",
646
+ "ui.review.next.human": "Agent se do nich pustí v rozhovoru nebo při samostatné práci.",
647
+ "ui.review.wake.human": " pokud v něm chcete pokračovat, řekněte to agentovi v rozhovoru",
648
+ "ui.waiting.gone": "Tohle už na vás nečeká – agent se toho mezitím ujal."
493
649
  }
@@ -59,7 +59,7 @@
59
59
  "ui.menu.start": "Die Forschung mit dem Agenten beginnen",
60
60
  "ui.menu.run": "Den Agenten allein arbeiten lassen",
61
61
  "ui.menu.waitlist": "Was auf Sie wartet",
62
- "ui.menu.settings": "Einstellungen",
62
+ "ui.menu.settings": "Einstellungen: Agent, allein arbeiten, Nachrichten, Archive, Prüfung",
63
63
  "ui.menu.doctor": "Installation prüfen",
64
64
  "ui.menu.trees": "Anderer Stammbaum",
65
65
  "ui.menu.newtree": "Stammbaum anlegen",
@@ -415,9 +415,7 @@
415
415
  "ui.card.partner": "Partner: {name}",
416
416
  "ui.card.unknown": "noch unbekannt",
417
417
  "ui.card.children": "Kinder: {names}",
418
- "ui.card.story": "Geschichte ({status}):",
419
- "ui.card.story.draft": "Entwurf",
420
- "ui.card.story.final": "freigegeben",
418
+ "ui.card.story": "Geschichte:",
421
419
  "ui.stats.title": "{name} – die Forschung im Überblick",
422
420
  "ui.stats.counts": "Personen: {persons} · Familien: {families} · Einträge aus Quellen: {sources} · Scans: {images} · Orte: {places}",
423
421
  "ui.stats.facts": "Angaben: belegt {proven} · wahrscheinlich {probable} · möglich {possible} · nur Hinweise {lead}",
@@ -429,7 +427,7 @@
429
427
  "ui.stats.sessions": "Sitzungen des Agenten: {n} · die letzte {last}",
430
428
  "ui.stats.cost": " · Kosten bisher {cost}",
431
429
  "ui.stats.cost.partial": " (ohne abgebrochene Sitzungen, die ihre Kosten nicht nannten: {n})",
432
- "ui.stats.stories": "Geschichten: {n} (freigegeben {final})",
430
+ "ui.stats.stories": "Geschichten: {n}",
433
431
  "ui.ped.noparents": "Eltern noch unbekannt",
434
432
  "ui.ped.nofather": "Vater noch unbekannt",
435
433
  "ui.ped.nomother": "Mutter noch unbekannt",
@@ -446,6 +444,20 @@
446
444
  "ui.recent.sessions": "Was der Agent tat:",
447
445
  "ui.recent.more": "… und {n} weitere",
448
446
  "ui.browse.plan": "Was der Agent als Nächstes tut",
447
+ "ui.review.new": "{name} — neue Aufgaben: {n}",
448
+ "ui.review.nothing": "{name} — nichts Neues zu prüfen",
449
+ "ui.review.would": " würde hinzufügen: {level} · {what}",
450
+ "ui.review.dry": "(Probelauf — nichts geschrieben)",
451
+ "ui.review.covered": " {name}: schon abgedeckt durch {task} ({state}) — {what}",
452
+ "ui.review.wake": " um daran weiterzuarbeiten: strom task wake {task}",
453
+ "ui.review.exhausted": " {name}: vergeblich gesucht ({tasks}) — wie es weitergeht, entscheiden Sie",
454
+ "ui.review.open": "Offene Aufgaben in {research}: {n}, etwa so viele Sitzungen",
455
+ "ui.review.cost": " — eine Sitzung kostet hier im Schnitt ${cost}",
456
+ "ui.review.next": "weiter: strom run --research {research} (der Agent allein) · oder im Gespräch: strom session start --research {research}",
457
+ "ui.review.state.open": "in der Warteschlange",
458
+ "ui.review.state.doing": "in Arbeit",
459
+ "ui.review.state.parked": "zurückgestellt",
460
+ "ui.review.state.waiting": "wartet auf Sie",
449
461
  "ui.plan.title": "Was der Agent als Nächstes tut – {name}:",
450
462
  "ui.plan.now": "gerade jetzt",
451
463
  "ui.plan.images": " (braucht zuerst die Scans)",
@@ -489,5 +501,149 @@
489
501
  "ui.consent.gate.set": "Die Bedingung „{name}“ entscheiden lassen, wann der allein arbeitende Agent weitermacht?",
490
502
  "ui.consent.gate.unset": "Die Bedingung „{name}“ entfernen — der allein arbeitende Agent fragt sie nicht mehr?",
491
503
  "ui.consent.gate.skip": "Den Agenten ohne die Bedingung „{name}“ allein arbeiten lassen?",
492
- "ui.run.others": "⚠ In diesem Stammbaum arbeitet schon ein anderer Lauf (seit {since}): dieser nimmt andere Aufgaben – die Kosten addieren sich."
504
+ "ui.consent.remote": "Die Claude-Code-Sitzungen, die strom öffnet, mit Remote Control starten, damit Sie sie auf claude.ai oder in der Claude-App auf dem Telefon verfolgen und steuern können?",
505
+ "ui.consent.hook.on": "Den Hook „{name}“ über alles informieren, was in Ihre Forschungen gespeichert wird? Er ist ein Programm auf diesem Computer und tut damit, wofür er geschrieben wurde.",
506
+ "ui.consent.hook.off": "Dem Hook „{name}“ nicht mehr melden, was gespeichert wird?",
507
+ "ui.run.others": "⚠ In diesem Stammbaum arbeitet schon ein anderer Lauf (seit {since}): dieser nimmt andere Aufgaben – die Kosten addieren sich.",
508
+ "ui.menu.more": "Die Forschung erweitern: Unterlagen, eine neue Richtung, eine Person prüfen",
509
+ "ui.more.title": "Die Forschung erweitern",
510
+ "ui.more.intake": "Unterlagen der Familie: Dokumente, Fotos, ein Stammbaum aus einem anderen Programm, was Sie wissen",
511
+ "ui.more.research": "Eine neue Richtung: die Vorfahren oder Nachkommen einer weiteren Person, oder eine Frage",
512
+ "ui.intake.what": "Was bringen Sie mit?",
513
+ "ui.intake.files": "Dateien oder einen Ordner von diesem Computer",
514
+ "ui.intake.text": "Was Sie wissen – Namen, Daten, Orte, Erinnerungen der Familie",
515
+ "ui.intake.write": "Schreiben Sie, was Sie wissen (Enter oder 0 geht zurück)",
516
+ "ui.intake.path": "Der Ordner oder die Datei – Sie können sie in dieses Fenster ziehen (Enter oder 0 geht zurück)",
517
+ "ui.intake.missing": "Nicht gefunden: {path} – prüfen Sie den Pfad oder ziehen Sie den Ordner hinein.",
518
+ "ui.intake.scans": "Im Ordner {folder} sind {n} Bilder. Sind es Dokumente und Fotos der Familie? (nein: Scans eines Kirchenbuchs oder eines anderen Buchs)",
519
+ "ui.intake.book": "{folder}: Scans eines Kirchenbuchs oder eines anderen Buchs gehören zu diesem Buch – sagen Sie dem Agenten im Gespräch, woher sie stammen, er erfasst sie.",
520
+ "ui.intake.known": "Diese Unterlagen sind schon in der Forschung – nichts hinzugefügt.",
521
+ "ui.intake.done": "✓ Zur Forschung hinzugefügt: {n}. Der Agent sieht es bei der nächsten Arbeit durch.",
522
+ "ui.intake.chat": "Jetzt mit dem Agenten durchgehen?",
523
+ "ui.intake.say": "Ich habe der Forschung neue Unterlagen hinzugefügt – gehen wir sie durch.",
524
+ "ui.research.kind": "Was möchten Sie erforschen?",
525
+ "ui.research.ancestors": "Die Vorfahren einer Person",
526
+ "ui.research.descendants": "Die Nachkommen einer Person",
527
+ "ui.research.question": "Eine Frage (z. B.: Wer war Marias Vater?)",
528
+ "ui.research.ask": "Die Frage (Enter oder 0 geht zurück)",
529
+ "ui.research.whom": "Um wen geht es?",
530
+ "ui.research.known": "Jemanden, der schon im Stammbaum ist",
531
+ "ui.research.newperson": "Jemand Neues",
532
+ "ui.research.name": "Vor- und Nachname (z. B. Johann Müller; 0 geht zurück)",
533
+ "ui.research.sex": "Ein Mann oder eine Frau?",
534
+ "ui.research.male": "Ein Mann",
535
+ "ui.research.female": "Eine Frau",
536
+ "ui.research.unknown": "Weiß ich nicht",
537
+ "ui.research.title": "Wie soll die Forschung heißen?",
538
+ "ui.research.title.ancestors": "Vorfahren: {name}",
539
+ "ui.research.title.descendants": "Nachkommen: {name}",
540
+ "ui.research.knows": "Was wissen Sie darüber? Daten, Orte und Familiengeschichten helfen dem Agenten (Enter: nichts)",
541
+ "ui.research.done": "✓ Die Forschung „{name}“ ist angelegt.",
542
+ "ui.research.chat": "Jetzt mit dem Agenten beginnen?",
543
+ "ui.research.say": "Ich habe eine neue Forschung angelegt, „{name}“ – fangen wir damit an.",
544
+ "ui.settings.title": "Einstellungen (auf diesem Computer)",
545
+ "ui.settings.wizard": "Sprache, Agent, Modell, was der Agent allein darf, Geschichten… (die Einrichtung)",
546
+ "ui.settings.alone": "Der Agent allein: {minutes} Min. je Aufgabe · Bedingung: {gate}",
547
+ "ui.settings.gate.none": "keine",
548
+ "ui.settings.hooks": "Nachrichten über das Gespeicherte (Hooks): {state}",
549
+ "ui.settings.on": "an",
550
+ "ui.settings.off": "aus",
551
+ "ui.settings.remote": "Den Agenten vom Telefon verfolgen (Remote Control): {state}",
552
+ "ui.settings.remote.about": "Eingeschaltet können Sie die Claude-Code-Sitzungen, die strom startet – Gespräche und allein arbeiten –, auf claude.ai oder in der Claude-App auf dem Telefon verfolgen und steuern.",
553
+ "ui.settings.remote.on": "Einschalten?",
554
+ "ui.settings.remote.off": "Ausschalten?",
555
+ "ui.settings.archives": "Archive: Ihre Anmeldungen, Zustimmung zum Herunterladen",
556
+ "ui.alone.title": "Der Agent allein",
557
+ "ui.alone.minutes": "Zeit für eine Aufgabe: {minutes} Min.",
558
+ "ui.alone.minutes.ask": "Wie viele Minuten darf eine Aufgabe dauern? (5–600; 0 geht zurück)",
559
+ "ui.alone.minutes.bad": "Bitte eine Zahl von Minuten zwischen 5 und 600.",
560
+ "ui.alone.gate": "Immer weiter unter einer Bedingung: {gate}",
561
+ "ui.alone.gate.about": "Eine Bedingung wird vor jeder Sitzung gefragt, während der Agent von selbst immer weiterarbeitet; das Menü bietet das nur mit einer an. Aufgaben, die Sie selbst starten, sind Ihre Wahl.",
562
+ "ui.alone.gate.pick": "Welche Bedingung?",
563
+ "ui.alone.gate.claude": "Um wie viele Punkte soll der Wochenverbrauch Ihres Claude-Abos hinter dem vergangenen Teil der Woche bleiben? (ein Tag ≈ 14,3; 0: nur der Woche nicht voraus)",
564
+ "ui.alone.gate.args": "Was ihr mitgeben (Enter: nichts)",
565
+ "ui.alone.test": "Was würde die Bedingung jetzt sagen?",
566
+ "ui.alone.asking": "Ich frage die Bedingung…",
567
+ "ui.alone.said.go": "Jetzt würde es beginnen{reason}",
568
+ "ui.alone.said.wait": "Es würde bis {at} warten{reason}",
569
+ "ui.alone.said.stop": "Es würde aufhören{reason}",
570
+ "ui.alone.said.error": "Keine richtige Antwort{reason}",
571
+ "ui.hooks.title": "Hooks – eine Zahl schaltet einen ein oder aus:",
572
+ "ui.hooks.on": "{name}: an",
573
+ "ui.hooks.off": "{name}: aus",
574
+ "ui.hooks.none": "Noch keine Hooks hier. Ein Hook ist Ihr eigenes Programm, dem strom meldet, was gespeichert wird (z. B. eine Nachricht aufs Telefon) – wie: {readme}",
575
+ "ui.archives.title": "Downloader der Archive auf diesem Computer:",
576
+ "ui.archives.empty": "Noch keine Downloader hier – der Agent baut einen, wenn die Forschung ein Archiv braucht.",
577
+ "ui.archives.login.saved": "Ihre Anmeldung gespeichert {date}",
578
+ "ui.archives.login.none": "kann Ihr Konto nutzen – keine Anmeldung gespeichert",
579
+ "ui.archives.consent": "Downloader fragen Sie, bevor sie laufen: {state}",
580
+ "ui.archives.consent.about": "Aus (üblich): Downloader laufen von selbst – langsam und nur zu ihrem Archiv. An: Jeder braucht erst Ihr Ja, hier im Terminal, und ebenso jedes Archiv, das er erreicht.",
581
+ "ui.archives.consent.on": "Einschalten?",
582
+ "ui.archives.consent.off": "Ausschalten?",
583
+ "ui.hooks.nothing": "keine",
584
+ "ui.menu.noagent": "Auf dem Computer ist noch kein KI-Agent – die Forschung ist seine Arbeit. Punkt 1 installiert einen.",
585
+ "ui.menu.getagent": "Den KI-Agenten installieren oder wählen",
586
+ "ui.menu.update.where": "Eine neue Version von strom ist da: {version} – aktualisieren können Sie sie in den Einstellungen (Punkt {key}).",
587
+ "ui.more.noagent": "Der Agent nimmt es auf, sobald er auf dem Computer ist (Punkt 1 im Menü).",
588
+ "ui.menu.noagent.chosen": "Der KI-Agent dieser Forschung ist nicht auf dem Computer – Punkt 1 wählt einen anderen.",
589
+ "task.answer": "Antwort des Nutzers (auf: {asked}): {answer}",
590
+ "ui.waiting.title": "Der Agent braucht Sie ({n}):",
591
+ "ui.waiting.do": "Was zu tun ist: {what}",
592
+ "ui.waiting.ask": "der Agent sagt es Ihnen im Gespräch",
593
+ "ui.waiting.images": "Von Hand speichern: Bilder {images} aus {book}",
594
+ "ui.waiting.more": "…und {n} weitere – der Agent geht sie im Gespräch mit Ihnen durch.",
595
+ "ui.waiting.pick": "Haben Sie es? Wählen Sie die Nummer und schreiben Sie, was Sie gefunden haben:",
596
+ "ui.waiting.answer": "Antwort zu {k}: {what}",
597
+ "ui.waiting.folder": "Den Ordner für die Bilder zu {k} öffnen",
598
+ "ui.waiting.opened": "Der Ordner: {dir} – sobald die Bilder dort sind, übernimmt der Agent sie bei der nächsten Arbeit von selbst.",
599
+ "ui.waiting.write": "Ihre Antwort – ein Link, die Nummer eines Buchs, was Sie herausgefunden haben (Enter oder 0 geht zurück)",
600
+ "ui.waiting.back": "✓ Die Aufgabe geht mit Ihrer Antwort an den Agenten zurück.",
601
+ "ui.waiting.chat": "Jetzt mit dem Agenten weitermachen?",
602
+ "ui.waiting.say": "Ich habe beantwortet, was Sie von mir brauchten: {what} – machen wir weiter.",
603
+ "ui.intake.empty": "Darin ist nichts, was sich hinzufügen ließe.",
604
+ "ui.intake.ours": "{path} ist ein Ordner von strom selbst (der Forschung), keine Unterlagen der Familie.",
605
+ "ui.research.exists": "Diese Forschung gibt es schon: „{name}“ – der Agent arbeitet daran weiter.",
606
+ "ui.alone.gate.bad": "Bitte eine Zahl von Punkten zwischen 0 und 100 (z. B. 10).",
607
+ "ui.waiting.long": "Das ist für eine Antwort hier zu lang (höchstens {n} Zeichen) – ein Link oder ein Satz; das Übrige sagen Sie dem Agenten im Gespräch.",
608
+ "ui.settings.remote.chats": "Gespräche ja, allein arbeiten nein",
609
+ "ui.settings.remote.own": "Gespräche mit dem Agenten können Sie schon vom Telefon verfolgen – das macht Claude Code selbst (seine eigene Einstellung). Die Arbeit des Agenten allein (Punkt 2 im Menü) erst, wenn Sie auch dies einschalten.",
610
+ "ui.settings.remote.both": "Gespräche und allein arbeiten",
611
+ "ui.settings.remote.onalone": "Auch für das Arbeiten allein einschalten?",
612
+ "ui.archives.login.nobody": "Keiner braucht eine Anmeldung – die Archive sind frei zugänglich. Eine Anmeldung erscheint hier nur bei einem Downloader eines Portals mit Konto (etwa einem bezahlten).",
613
+ "ui.archives.login.how": "Die Anmeldung geben Sie hier ein, sie bleibt nur auf diesem Computer; strom setzt sie in die Anfragen des Downloaders – weder der Downloader noch der Agent sehen sie.",
614
+ "ui.archives.login.save": "Anmeldung bei {title} speichern",
615
+ "ui.archives.login.change": "Anmeldung bei {title} ändern",
616
+ "ui.home.what": "Die Forschung liegt in {from} (Stammbäume: {trees}), mit dem gemeinsamen Ordner – Downloader, Hooks, Eingang, große Bilder. Sie zieht als Ganzes nach {to} um.",
617
+ "ui.home.sure": "Dorthin verschieben?",
618
+ "ui.home.moved": "✓ Die Forschung liegt jetzt in {to}.",
619
+ "ui.home.copied": "✓ Die Forschung ist nach {to} kopiert (anderes Laufwerk) und wird von dort bearbeitet. Der alte Ordner {from} bleibt, wie er war – löschen Sie ihn, wenn alles in Ordnung ist.",
620
+ "ui.home.stays": "Die Forschung bleibt in {from}.",
621
+ "ui.home.inside": "{to} liegt im Ordner der Forschung {from} (oder umgekehrt) – wählen Sie einen Ordner daneben.",
622
+ "ui.home.notEmpty": "In {to} liegt schon etwas – die Forschung zieht nur in einen leeren oder neuen Ordner.",
623
+ "ui.home.busy": "Im Stammbaum {trees} arbeitet gerade jemand (ein Agent, ein Lauf oder die Strom-App live) – die Forschung kann umziehen, wenn das fertig ist.",
624
+ "ui.home.failed": "Das Verschieben ging nicht ({reason}) – nichts wurde geändert.",
625
+ "ui.app.notinstalled": "Die Strom-App ist auf diesem Computer noch nicht installiert. Jetzt als App aus dem Browser installieren (kostenlos; strom zeigt, wo Sie klicken)?",
626
+ "ui.browser.agent": "{names}: wird über den Browser geladen – das kann nur Claude Code (die Erweiterung Claude in Chrome); die Forschung macht jetzt {agent}. Speichern Sie diese Bilder von Hand, oder überlassen Sie die Forschung Claude Code (strom agents use claude).",
627
+ "ui.browser.noext": "{names}: wird über den Browser geladen – Chrome braucht dafür die Erweiterung Claude in Chrome, angemeldet beim Konto von Claude Code; hier ist sie in keinem Browser: {url}",
628
+ "ui.doc.browser": "Browser (Claude in Chrome)",
629
+ "ui.doc.browser.ok": "die Erweiterung in {browsers} – Chrome muss laufen, während der Agent arbeitet",
630
+ "ui.doc.browser.noext": "die Erweiterung ist nicht installiert (gebraucht von {names})",
631
+ "ui.doc.browser.agent": "{names} laden über den Browser – das kann nur Claude Code (jetzt: {agent})",
632
+ "ui.archives.via.direct": "Bilder direkt, strom achtet aufs Tempo",
633
+ "ui.archives.via.browser": "Bilder über Ihren Browser",
634
+ "ui.archives.via.manual": "Bilder werden von Hand gespeichert (das Archiv erlaubt kein automatisches Laden)",
635
+ "ui.archives.browser.ok": "Über den Browser: die Erweiterung Claude in Chrome ist in {browsers}; Chrome muss laufen, während der Agent arbeitet, angemeldet beim Konto von Claude Code.",
636
+ "ui.archives.to.browser": "{title}: lieber über Ihren Browser laden",
637
+ "ui.archives.to.direct": "{title}: lieber direkt laden",
638
+ "ui.archives.browser.about": "Über den Browser lädt der Agent die Bilder in Ihrem eigenen Chrome (wo Sie beim Archiv angemeldet sind), mit der Erweiterung Claude in Chrome – das kann nur Claude Code. strom plant weiter jede Anfrage und achtet aufs Tempo.",
639
+ "ui.archives.direct.about": "Direkt lädt strom die Bilder selbst, im Tempo, ohne Browser – das kann jeder Agent.",
640
+ "ui.archives.switch": "Umstellen?",
641
+ "ui.archives.now.browser": "✓ {title}: ab jetzt über Ihren Browser.",
642
+ "ui.archives.now.direct": "✓ {title}: ab jetzt direkt.",
643
+ "ui.setup.home.again": "Wo die Forschung liegen soll (0 lässt sie, wo sie ist)",
644
+ "ui.home.env": "Der Ordner der Forschung {from} ist von außen gesetzt (STROM_HOME) – er bleibt; ändern Sie ihn dort.",
645
+ "ui.menu.failed": "Das ging nicht: {reason}",
646
+ "ui.review.next.human": "Der Agent nimmt sie im Gespräch oder bei der Arbeit allein auf.",
647
+ "ui.review.wake.human": " wenn es weitergehen soll, sagen Sie es dem Agenten im Gespräch",
648
+ "ui.waiting.gone": "Das wartet nicht mehr auf Sie – der Agent hat es inzwischen übernommen."
493
649
  }
@@ -10,6 +10,9 @@ it one folder per plugin. The folder's name is the plugin's name.
10
10
  gates/ conditions on the agent working alone (strom run)
11
11
  README.md their interface (version 1)
12
12
  claude-usage/ one gate: gate.json and its program
13
+ hooks/ your programs told of what is saved into a research
14
+ README.md their interface (version 1)
15
+ my-hook/ one hook: hook.json and its program
13
16
 
14
17
  **Install** a plugin by copying its folder in: `strom connector list` shows it
15
18
  and it can run at once, paced by strom and only to the hosts it names. To be
@@ -24,7 +27,11 @@ plugin whose code goes round strom always needs your yes, in your terminal
24
27
  **Gates** decide whether the agent working alone goes on: `strom config set
25
28
  run.gate <name>` (only you), `strom gate test`, `strom run --loop`.
26
29
 
30
+ **Hooks** are told of what is saved into a research — a person found, a
31
+ session closed — and do with it what you want (a message to your phone, a
32
+ log): `strom hook on <name>` (only you), `strom hook test <name>`.
33
+
27
34
  Plugins are programs on this computer, put here by you: the `.gitignore` here
28
35
  keeps them out of any repository. strom writes this file, the `.gitignore`,
29
- `connectors/README.md`, `gates/README.md` and the gates it ships, and keeps them
36
+ `connectors/README.md`, `gates/README.md`, `hooks/README.md` and the gates it ships, and keeps them
30
37
  up to date.
@@ -0,0 +1,91 @@
1
+ # strom hooks — interface 1
2
+
3
+ A hook is a program of yours that strom tells what was saved into a research:
4
+ a person added to the family tree, a fact found, a task done, a session
5
+ closed. What it does with it is up to you — a message to your phone, a line
6
+ in a log, a backup. strom starts it in the background after each save and
7
+ never waits for it: a hook that is slow or fails never holds up or breaks the
8
+ research.
9
+
10
+ plugins/hooks/
11
+ README.md this interface
12
+ my-hook/ one hook: hook.json and its program
13
+ hook.log what it printed (strom keeps it)
14
+
15
+ **Turn one on**: `strom hook on <name>` — only you (an agent asks you in a
16
+ window of the system). A folder alone does nothing: an agent may build a hook
17
+ for you, but it runs only once you turn it on. `strom hook off <name>`,
18
+ `strom hook list`. **Try it**: `strom hook test <name>` runs it now on the last
19
+ operations saved in the research you are in, waits and shows what it printed
20
+ (`--op person.add --target P0001`: one operation you name).
21
+
22
+ ## hook.json
23
+
24
+ {
25
+ "interface": 1,
26
+ "title": "My phone",
27
+ "command": ["node", "hook.ts"],
28
+ "events": ["person.add", "family.child", "session.close"]
29
+ }
30
+
31
+ - `command`: the program and its arguments, run in the hook's folder. `node`
32
+ is strom's own Node (TypeScript runs as it is) — best on every system.
33
+ - `events`: the operations it wants — one (`person.add`), a kind
34
+ (`person.*`) or all (`*`, the default). Saves with none of them do not start
35
+ it.
36
+ - `timeout`: seconds `strom hook test` waits for it (default 60).
37
+
38
+ ## What it gets
39
+
40
+ One JSON document on stdin (also in the file `STROM_EVENT_FILE`): one save
41
+ into one research, with the operations it saved that the hook wants.
42
+
43
+ {
44
+ "interface": 1,
45
+ "hook": "my-hook",
46
+ "tree": { "name": "Novákovi", "id": "…", "root": "/…/Novákovi", "lang": "en" },
47
+ "commit": "3f2a9c1…",
48
+ "at": "2026-10-02T14:03:11.000Z",
49
+ "events": [
50
+ { "op": "person.add", "targets": ["P0012"], "summary": "+P0012 Josef /Novák/ · E0031 BIRT 1851 …",
51
+ "at": "2026-10-02T14:03:10.412Z", "by": "N0007" }
52
+ ]
53
+ }
54
+
55
+ - `op`: what was done — `person.add` (a person in the family tree),
56
+ `family.add`, `family.child` (a child linked to parents), `event.add` (a
57
+ fact: birth, marriage, death…), `event.edit`, `person.merge`, `source.add`
58
+ (a record read), `media.add` (a scan), `task.add`, `task.done`, `task.wait`
59
+ (waiting for you), `story.set`, `session.start`, `session.close`… — the same
60
+ names as the research's history.
61
+ - `targets`: the records it concerns — read more of them through strom, as
62
+ the user would: `strom person card P0012`, `strom person show P0012 --json`,
63
+ `strom session show N0007`.
64
+ - `by`: the session that saved it (N0007), or `user`.
65
+ - `tree`: which research. A hook you turn on hears from all your researches;
66
+ to hear from some only, let it skip the others by `tree.name` or `tree.id`
67
+ (e.g. a list in a config file of its own).
68
+
69
+ Environment variables, besides the user's own: `STROM_HOOK` (its name),
70
+ `STROM_TREE` (the research's folder — run strom there), `STROM_LANG` (the
71
+ research language), `STROM_EVENT_FILE`. What the hook itself writes through
72
+ strom tells no hook again.
73
+
74
+ ## An example: a message to your phone (Telegram)
75
+
76
+ // hook.ts — the bot's token and your chat's id in config.json beside it
77
+ import fs from "node:fs";
78
+ import { execFileSync } from "node:child_process";
79
+ const cfg = JSON.parse(fs.readFileSync("config.json", "utf8"));
80
+ const save = JSON.parse(fs.readFileSync(0, "utf8"));
81
+ for (const e of save.events.filter((e) => e.op === "person.add")) {
82
+ const card = execFileSync("strom", ["person", "card", e.targets[0]], { cwd: save.tree.root, encoding: "utf8" });
83
+ await fetch(`https://api.telegram.org/bot${cfg.token}/sendMessage`, {
84
+ method: "POST",
85
+ headers: { "content-type": "application/json" },
86
+ body: JSON.stringify({ chat_id: cfg.chat, text: `${save.tree.name}: a new person\n\n${card}` }),
87
+ });
88
+ }
89
+
90
+ Keep secrets such as a token in the hook's own folder: the `.gitignore` of the
91
+ plugins folder keeps every plugin out of any repository.
@@ -80,6 +80,16 @@ const OPENCODE_STROM = "strom *";
80
80
  function opencodeDir(env) {
81
81
  return path.join(env.XDG_CONFIG_HOME ?? path.join(userHome(env), ".config"), "opencode");
82
82
  }
83
+ /** Claude Code starts its own conversations with Remote Control (its setting remoteControlAtStartup, the user's own). */
84
+ export function claudeRemoteAtStartup(env) {
85
+ try {
86
+ const file = path.join(env.CLAUDE_CONFIG_DIR ?? path.join(userHome(env), ".claude"), "settings.json");
87
+ return JSON.parse(fs.readFileSync(file, "utf8")).remoteControlAtStartup === true;
88
+ }
89
+ catch {
90
+ return false; // no settings, or not readable: not on
91
+ }
92
+ }
83
93
  export function globalTargets(env) {
84
94
  const home = userHome(env);
85
95
  return [
@@ -19,7 +19,7 @@ import { claudeArgs } from "../runners/claude.js";
19
19
  /** The command line of a conversation with this agent. */
20
20
  export function conversationArgs(agent, o) {
21
21
  if (agent === "claude")
22
- return claudeArgs({ interactive: true, kickoff: o.kickoff, permissions: o.level, settingsFile: o.settingsFile, ...(o.name ? { name: o.name } : {}), ...(o.model ? { model: o.model } : {}), ...(o.chrome !== undefined ? { chrome: o.chrome } : {}) });
22
+ return claudeArgs({ interactive: true, kickoff: o.kickoff, permissions: o.level, settingsFile: o.settingsFile, ...(o.name ? { name: o.name } : {}), ...(o.model ? { model: o.model } : {}), ...(o.chrome !== undefined ? { chrome: o.chrome } : {}), ...(o.remote ? { remote: true } : {}) });
23
23
  if (agent === "codex") {
24
24
  const args = o.level === "full"
25
25
  ? ["--dangerously-bypass-approvals-and-sandbox"]
package/dist/cli/main.js CHANGED
@@ -6,7 +6,10 @@ import { groupHelp, helpFor } from "./help.js";
6
6
  import { autoCommit } from "./commit.js";
7
7
  import { assertIntact } from "../core/integrity.js";
8
8
  import { resetCache } from "../core/git.js";
9
- import { VERSION } from "../core/tree.js";
9
+ import { Tree, VERSION } from "../core/tree.js";
10
+ import { fireHooks, HOOK_INTERFACE } from "../core/hooks.js";
11
+ import { prependPath } from "../runners/runner.js";
12
+ import { shimDir } from "../commands/session.js";
10
13
  import { isAgent } from "../core/which.js";
11
14
  import { noticeStromApp } from "../core/stromapp.js";
12
15
  import { isNewer } from "../core/update.js";
@@ -116,6 +119,19 @@ export async function main(argv, io, env, cwd) {
116
119
  const ctx = Context.fromOptions({ env, cwd, io, json, values: v });
117
120
  ran = ctx;
118
121
  command = def.path.join(" ");
122
+ // What is saved into a research, the user's hooks are told of (in the background).
123
+ Tree.onCommit = (tree, ops, commit) => {
124
+ if (!ctx.settings.config.hooks?.length || env.STROM_HOOK)
125
+ return;
126
+ // this strom on the hook's PATH: it reads more of what was saved (strom person card P0012)
127
+ fireHooks(ctx.settings.shared()?.value, ctx.settings.config.hooks, prependPath(env, shimDir(tree)), {
128
+ interface: HOOK_INTERFACE,
129
+ tree: { name: tree.config.name, id: tree.config.id, root: tree.root, lang: tree.lang },
130
+ commit,
131
+ at: new Date().toISOString(),
132
+ events: ops.map((o) => ({ op: o.op, targets: o.targets, summary: o.summary, at: o.at, by: o.by, ...(o.reason ? { reason: o.reason } : {}) })),
133
+ });
134
+ };
119
135
  // Started by the Strom app: remembered quietly (it is where the results go).
120
136
  if (env.STROM_APP)
121
137
  noticeStromApp(ctx.settings, env);