thoth-agents 0.1.19 → 0.2.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.
@@ -0,0 +1,53 @@
1
+ import { type ClaudeCodeModel, isClaudeCodeModel } from '../harness/writers/claude-code-subagent';
2
+ import type { ClaudeCodeInstallScope, ClaudeCodeResolvedTargets, ClaudeCodeRoleName } from './claude-code-paths';
3
+ import { type ManagedModelState } from './managed-state-io';
4
+ export { CLAUDE_CODE_ROLE_NAMES } from './claude-code-paths';
5
+ export declare const CLAUDE_CODE_MANAGED_MODEL_STATE_VERSION = 1;
6
+ export declare const CLAUDE_CODE_MODEL_ALIASES: readonly ["sonnet", "opus", "haiku", "inherit"];
7
+ export type ClaudeCodeSetupAction = 'write-plugin-file' | 'write-managed-model-state';
8
+ export type ClaudeCodeTargetKind = 'plugin-manifest' | 'subagent' | 'mcp-config' | 'hook' | 'skill' | 'plugin-asset' | 'managed-model-state';
9
+ export interface ClaudeCodeInstallConfig {
10
+ dryRun?: boolean;
11
+ reset: boolean;
12
+ scope: ClaudeCodeInstallScope;
13
+ projectRoot: string;
14
+ homeDir?: string;
15
+ packageRoot?: string;
16
+ }
17
+ export interface ClaudeCodeSetupPlanItem {
18
+ kind: ClaudeCodeTargetKind;
19
+ action: ClaudeCodeSetupAction;
20
+ targetPath: string;
21
+ description: string;
22
+ requiresBackup: boolean;
23
+ content: string;
24
+ role?: ClaudeCodeRoleName;
25
+ }
26
+ export interface ClaudeCodeSetupPlan {
27
+ dryRun: boolean;
28
+ reset: boolean;
29
+ items: ClaudeCodeSetupPlanItem[];
30
+ diagnostics: string[];
31
+ disclaimers: string[];
32
+ pluginRoot: string;
33
+ }
34
+ export interface ClaudeCodeApplyResult {
35
+ success: boolean;
36
+ changed: string[];
37
+ diagnostics: string[];
38
+ error?: string;
39
+ }
40
+ export interface ClaudeCodeManagedModelOverride {
41
+ role: ClaudeCodeRoleName;
42
+ model: ClaudeCodeModel;
43
+ }
44
+ export declare const isClaudeCodeModelAlias: typeof isClaudeCodeModel;
45
+ export declare function parseSubagentModel(content: string): string | undefined;
46
+ export declare function replaceSubagentModel(content: string, model: string): string;
47
+ export declare function parseManagedModelStateJson(text: string | undefined): ManagedModelState;
48
+ export declare function readManagedModelState(path: string): ManagedModelState;
49
+ export declare function buildClaudeCodeSetupPlan(config: ClaudeCodeInstallConfig): ClaudeCodeSetupPlan;
50
+ export declare function applyClaudeCodeSetup(plan: ClaudeCodeSetupPlan): ClaudeCodeApplyResult;
51
+ export declare function applyClaudeCodeManagedModelOverrides(config: ClaudeCodeInstallConfig, overrides: ClaudeCodeManagedModelOverride[]): ClaudeCodeApplyResult;
52
+ export declare function formatClaudeCodeSetupPlan(plan: ClaudeCodeSetupPlan): string;
53
+ export type { ClaudeCodeResolvedTargets };
@@ -0,0 +1,31 @@
1
+ export type ClaudeCodeInstallScope = 'project' | 'user';
2
+ export type ClaudeCodeRoleName = 'explorer' | 'librarian' | 'oracle' | 'designer' | 'quick' | 'deep';
3
+ export declare const CLAUDE_CODE_ROLE_NAMES: readonly ["explorer", "librarian", "oracle", "designer", "quick", "deep"];
4
+ export interface ClaudeCodeTargetResolverOptions {
5
+ scope: ClaudeCodeInstallScope;
6
+ projectRoot: string;
7
+ homeDir?: string;
8
+ }
9
+ export interface ClaudeCodeResolvedTargets {
10
+ scope: ClaudeCodeInstallScope;
11
+ pluginRoot: string;
12
+ pluginManifestPath: string;
13
+ agentPaths: {
14
+ role: ClaudeCodeRoleName;
15
+ path: string;
16
+ }[];
17
+ mcpPath: string;
18
+ hooksPath: string;
19
+ skillsDir: string;
20
+ managedModelsPath: string;
21
+ }
22
+ /**
23
+ * Resolve the on-disk Claude Code plugin package targets. Claude Code plugins
24
+ * installed as a "skills-directory plugin": a folder under a Claude Code skills
25
+ * directory (`~/.claude/skills/<name>` for user scope, `<project>/.claude/skills/<name>`
26
+ * for project scope) that contains `.claude-plugin/plugin.json` is auto-loaded
27
+ * as `<name>@skills-dir` on the next session — no marketplace, no install step,
28
+ * discovered in place rather than copied to the `~/.claude/plugins/cache`.
29
+ * Only `plugin.json` sits in `.claude-plugin/`; components are plugin-root siblings.
30
+ */
31
+ export declare function resolveClaudeCodeTargets(options: ClaudeCodeTargetResolverOptions): ClaudeCodeResolvedTargets;
@@ -1,4 +1,5 @@
1
1
  import type { CodexInstallScope, CodexRoleName } from './codex-paths';
2
+ import { type ManagedModelState } from './managed-state-io';
2
3
  export { CODEX_ROLE_NAMES } from './codex-paths';
3
4
  export type CodexSetupAction = 'merge-managed-block' | 'write-role-toml' | 'write-managed-model-state' | 'refresh-package' | 'merge-marketplace' | 'merge-toml' | 'diagnose-only';
4
5
  export type CodexTargetKind = 'root-instructions' | 'role-subagent-toml' | 'managed-model-state' | 'user-config' | 'plugin-package' | 'personal-plugin-source' | 'personal-marketplace' | 'diagnostic';
@@ -37,11 +38,6 @@ export interface CodexApplyResult {
37
38
  error?: string;
38
39
  }
39
40
  export declare const MANAGED_MODEL_STATE_VERSION = 1;
40
- interface ManagedModelState {
41
- version: typeof MANAGED_MODEL_STATE_VERSION;
42
- models: Record<string, string>;
43
- configuredModels?: Record<string, string>;
44
- }
45
41
  export declare function readManagedModelState(path: string): ManagedModelState;
46
42
  export declare function parseRoleTomlModel(content: string): string | undefined;
47
43
  export declare function replaceRoleTomlModel(content: string, model: string): string;
@@ -5,5 +5,5 @@ export declare function formatHarnessList(harnesses: readonly OperationHarnessMe
5
5
  export declare function formatOperationPlan(plan: OperationPlan): string;
6
6
  export declare function formatOperationApplyResult(result: OperationApplyResult): string;
7
7
  export declare function printHelp(): void;
8
- export declare function printCodexGeneration(args: GenerateArgs): number;
8
+ export declare function printHarnessGeneration(args: GenerateArgs): number;
9
9
  export declare function runCliCommand(parsed: CliParseResult): Promise<number>;
package/dist/cli/index.js CHANGED
@@ -2,15 +2,22 @@
2
2
  import {
3
3
  getOpenCodePath,
4
4
  getOpenCodeVersion,
5
- isOpenCodeInstalled
6
- } from "../chunk-DYGVRAMS.js";
5
+ isOpenCodeInstalled,
6
+ opencodeAdapter
7
+ } from "../chunk-4WYCZ5Z7.js";
7
8
  import {
8
9
  CODEX_ROLE_NAMES,
9
10
  RECOMMENDED_SKILLS,
10
11
  SUPPORTED_OPERATION_HARNESSES,
12
+ applyClaudeCodePlan,
13
+ applyClaudeCodeSetup,
11
14
  applyCodexPlan,
12
15
  applyCodexSetup,
13
16
  applyOpenCodePlan,
17
+ buildClaudeCodeModelPlan,
18
+ buildClaudeCodeSetupPlan,
19
+ buildClaudeCodeSyncPlan,
20
+ buildClaudeCodeUpdatePlan,
14
21
  buildCodexModelPlan,
15
22
  buildCodexSetupPlan,
16
23
  buildCodexSyncPlan,
@@ -18,14 +25,18 @@ import {
18
25
  buildOpenCodeModelPlan,
19
26
  buildOpenCodeSyncPlan,
20
27
  buildOpenCodeUpdatePlan,
28
+ claudeCodeAdapter,
21
29
  codexAdapter,
30
+ defaultClaudeCodeModelRoles,
31
+ formatClaudeCodeSetupPlan,
22
32
  formatCodexSetupPlan,
33
+ getClaudeCodeStatus,
23
34
  getCodexStatus,
24
35
  getOpenCodeStatus,
25
36
  getOperationHarness,
26
37
  installRecommendedSkill,
27
38
  listOperationHarnesses
28
- } from "../chunk-7CTSLCEU.js";
39
+ } from "../chunk-WH3F3GWE.js";
29
40
  import {
30
41
  ALL_AGENT_NAMES,
31
42
  CUSTOM_SKILLS,
@@ -37,11 +48,22 @@ import {
37
48
  getExistingLiteConfigPath,
38
49
  installCustomSkills,
39
50
  writeLiteConfig
40
- } from "../chunk-2SGSRR6L.js";
51
+ } from "../chunk-3NOVCFN7.js";
41
52
 
42
53
  // src/cli/index.ts
43
54
  import { pathToFileURL } from "url";
44
55
 
56
+ // src/harness/registry.ts
57
+ var HARNESS_ADAPTERS = {
58
+ opencode: opencodeAdapter,
59
+ codex: codexAdapter,
60
+ claude: claudeCodeAdapter
61
+ };
62
+ var SUPPORTED_HARNESSES = Object.keys(HARNESS_ADAPTERS);
63
+ function getHarnessAdapter(harness) {
64
+ return HARNESS_ADAPTERS[harness];
65
+ }
66
+
45
67
  // src/cli/install.ts
46
68
  import { existsSync } from "fs";
47
69
  import { homedir } from "os";
@@ -311,6 +333,26 @@ async function install(args) {
311
333
  );
312
334
  return 0;
313
335
  }
336
+ if (config.agent === "claude") {
337
+ const plan = buildClaudeCodeSetupPlan({
338
+ dryRun: config.dryRun,
339
+ reset: config.reset,
340
+ scope: "user",
341
+ projectRoot: cwd(),
342
+ homeDir: homedir()
343
+ });
344
+ console.log(formatClaudeCodeSetupPlan(plan));
345
+ const result = applyClaudeCodeSetup(plan);
346
+ for (const diagnostic of result.diagnostics) printInfo(diagnostic);
347
+ if (!result.success) {
348
+ printError(`Claude Code install failed: ${result.error}`);
349
+ return 1;
350
+ }
351
+ printSuccess(
352
+ config.dryRun ? "Claude Code dry-run complete; no files written" : "Claude Code plugin installed as thoth-agents@skills-dir (restart Claude Code or run /reload-plugins to activate)"
353
+ );
354
+ return 0;
355
+ }
314
356
  return runInstall(config);
315
357
  }
316
358
 
@@ -446,7 +488,7 @@ Usage: thoth-agents [COMMAND] [OPTIONS]
446
488
 
447
489
  Commands:
448
490
  (no command) Open the interactive TUI in a TTY; fall back to OpenCode install in CI/non-TTY
449
- install Install OpenCode or Codex agent assets
491
+ install Install OpenCode, Codex, or Claude Code agent assets
450
492
  generate Generate harness-specific artifacts
451
493
  status Show managed install status
452
494
  list List managed surfaces and actions
@@ -460,11 +502,13 @@ Options:
460
502
  --no-tui Non-interactive mode
461
503
  --dry-run Simulate install without writing files
462
504
  --reset Repair managed installer-owned targets
463
- --agent=opencode|codex Select OpenCode plugin install (default) or Codex agent-pack setup
505
+ --agent=opencode|codex|claude
506
+ Select OpenCode plugin install (default), Codex agent-pack, or Claude Code plugin setup
507
+ --harness=... Select harness for status/update/sync/model (opencode|codex|claude)
464
508
  -h, --help Show this help message
465
509
 
466
510
  Generate options:
467
- --harness=codex Explicitly select Codex artifact generation
511
+ --harness=codex|claude Select Codex or Claude Code artifact generation
468
512
  --output-root=PATH Override generation root metadata
469
513
 
470
514
  OpenCode plugin config and the npm binary are separate surfaces.
@@ -490,10 +534,13 @@ Examples:
490
534
  pnpm dlx thoth-agents@latest install --agent=opencode
491
535
  pnpm dlx thoth-agents@latest install --agent=codex
492
536
  pnpm dlx thoth-agents@latest install --agent=codex --dry-run
537
+ pnpm dlx thoth-agents@latest install --agent=claude
538
+ pnpm dlx thoth-agents@latest install --agent=claude --dry-run
493
539
  pnpm dlx thoth-agents install --no-tui --tmux=no --skills=yes
494
540
  pnpm dlx thoth-agents install --dry-run
495
541
  pnpm dlx thoth-agents install --reset
496
542
  pnpm dlx thoth-agents generate --harness=codex --dry-run
543
+ pnpm dlx thoth-agents generate --harness=claude --dry-run
497
544
  `);
498
545
  }
499
546
  function operationContext() {
@@ -505,9 +552,11 @@ function selectedHarness(args, fallback = "opencode") {
505
552
  function statusReports(args) {
506
553
  const harnesses = args.all || !args.harness ? SUPPORTED_OPERATION_HARNESSES : [args.harness];
507
554
  const context = operationContext();
508
- return harnesses.map(
509
- (harness) => harness === "opencode" ? getOpenCodeStatus(context) : getCodexStatus(context)
510
- );
555
+ return harnesses.map((harness) => {
556
+ if (harness === "opencode") return getOpenCodeStatus(context);
557
+ if (harness === "claude") return getClaudeCodeStatus(context);
558
+ return getCodexStatus(context);
559
+ });
511
560
  }
512
561
  function buildOperationPlan(command, args) {
513
562
  const harness = selectedHarness(args);
@@ -515,6 +564,9 @@ function buildOperationPlan(command, args) {
515
564
  if (harness === "opencode") {
516
565
  return command === "update" ? buildOpenCodeUpdatePlan(context) : buildOpenCodeSyncPlan(context);
517
566
  }
567
+ if (harness === "claude") {
568
+ return command === "update" ? buildClaudeCodeUpdatePlan(context) : buildClaudeCodeSyncPlan(context);
569
+ }
518
570
  return command === "update" ? buildCodexUpdatePlan(context) : buildCodexSyncPlan(context);
519
571
  }
520
572
  function defaultModelRoles(harness) {
@@ -524,6 +576,9 @@ function defaultModelRoles(harness) {
524
576
  model: "openai/gpt-5.4-mini"
525
577
  }));
526
578
  }
579
+ if (harness === "claude") {
580
+ return defaultClaudeCodeModelRoles();
581
+ }
527
582
  return ALL_AGENT_NAMES.map((role) => ({
528
583
  role,
529
584
  model: DEFAULT_MODELS[role] ?? "openai/gpt-5.4"
@@ -553,10 +608,14 @@ function buildModelPlan(args) {
553
608
  dryRun: true,
554
609
  roles: modelRoles(harness, args.roles)
555
610
  };
556
- return harness === "opencode" ? buildOpenCodeModelPlan(input, context) : buildCodexModelPlan(input, context);
611
+ if (harness === "opencode") return buildOpenCodeModelPlan(input, context);
612
+ if (harness === "claude") return buildClaudeCodeModelPlan(input, context);
613
+ return buildCodexModelPlan(input, context);
557
614
  }
558
615
  function applyOperationPlan(plan) {
559
- return plan.harness === "opencode" ? applyOpenCodePlan(plan) : applyCodexPlan(plan);
616
+ if (plan.harness === "opencode") return applyOpenCodePlan(plan);
617
+ if (plan.harness === "claude") return applyClaudeCodePlan(plan);
618
+ return applyCodexPlan(plan);
560
619
  }
561
620
  function printPlanOrApply(plan, args) {
562
621
  if (args.apply && args.dryRun) {
@@ -586,19 +645,18 @@ function runOperationCommand(command, args) {
586
645
  if (!plan) return printModelGuidance();
587
646
  return printPlanOrApply(plan, args);
588
647
  }
589
- function printCodexGeneration(args) {
648
+ function printHarnessGeneration(args) {
590
649
  if (!args.dryRun) {
591
- console.error(
592
- "Codex generation is dry-run only in this MVP. Pass --dry-run."
593
- );
650
+ console.error("Generation is dry-run only in this MVP. Pass --dry-run.");
594
651
  return 1;
595
652
  }
596
- const result = codexAdapter.render({
653
+ const adapter = getHarnessAdapter(args.harness);
654
+ const result = adapter.render({
597
655
  projectRoot: process.cwd(),
598
656
  options: {
599
657
  dryRun: true,
600
658
  outputRoot: args.outputRoot,
601
- targetHarness: "codex"
659
+ targetHarness: args.harness
602
660
  }
603
661
  });
604
662
  console.log(JSON.stringify(result, null, 2));
@@ -609,7 +667,7 @@ async function runCliCommand(parsed) {
609
667
  return install(parsed.installArgs);
610
668
  }
611
669
  if (parsed.command === "generate") {
612
- return printCodexGeneration(parsed.generateArgs);
670
+ return printHarnessGeneration(parsed.generateArgs);
613
671
  }
614
672
  if (parsed.command === "help") {
615
673
  printHelp();
@@ -678,9 +736,9 @@ function parseBooleanArg(name, value) {
678
736
  return value;
679
737
  }
680
738
  function parseOperationHarness(value) {
681
- if (value !== "opencode" && value !== "codex") {
739
+ if (value !== "opencode" && value !== "codex" && value !== "claude") {
682
740
  throw new Error(
683
- `Unsupported operation harness: ${value}. Supported harnesses: opencode, codex.`
741
+ `Unsupported operation harness: ${value}. Supported harnesses: opencode, codex, claude.`
684
742
  );
685
743
  }
686
744
  return value;
@@ -772,9 +830,9 @@ function parseInstallArgs(args) {
772
830
  result.reset = true;
773
831
  } else if (arg.startsWith("--agent=")) {
774
832
  const agent = arg.split("=")[1];
775
- if (agent !== "opencode" && agent !== "codex") {
833
+ if (agent !== "opencode" && agent !== "codex" && agent !== "claude") {
776
834
  throw new Error(
777
- `Unsupported install agent: ${agent}. Supported agents: opencode, codex.`
835
+ `Unsupported install agent: ${agent}. Supported agents: opencode, codex, claude.`
778
836
  );
779
837
  }
780
838
  result.agent = agent;
@@ -789,10 +847,10 @@ function parseGenerateArgs(args) {
789
847
  for (const arg of args) {
790
848
  if (arg.startsWith("--harness=")) {
791
849
  const harness = arg.split("=")[1];
792
- if (harness !== "codex") {
850
+ if (harness !== "codex" && harness !== "claude") {
793
851
  return {
794
852
  command: "error",
795
- message: `Unsupported generate harness: ${harness}.`
853
+ message: `Unsupported generate harness: ${harness}. Supported harnesses: codex, claude.`
796
854
  };
797
855
  }
798
856
  result.harness = harness;
@@ -802,10 +860,10 @@ function parseGenerateArgs(args) {
802
860
  result.outputRoot = arg.split("=")[1];
803
861
  }
804
862
  }
805
- if (result.harness !== "codex") {
863
+ if (result.harness !== "codex" && result.harness !== "claude") {
806
864
  return {
807
865
  command: "error",
808
- message: "Codex generation requires --harness=codex."
866
+ message: "Generation requires --harness=codex or --harness=claude."
809
867
  };
810
868
  }
811
869
  return {
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Harness-agnostic helpers shared by the Codex and Claude Code installers for
3
+ * managed file writes and managed-model-state JSON bookkeeping.
4
+ */
5
+ export declare function writeTextWithBackup(path: string, content: string): boolean;
6
+ export declare function stableJson(value: unknown): string;
7
+ export declare function uniqueMessages(messages: string[]): string[];
8
+ export declare function stringRecord(value: unknown): Record<string, string>;
9
+ export interface ManagedModelState {
10
+ version: number;
11
+ models: Record<string, string>;
12
+ configuredModels?: Record<string, string>;
13
+ }
14
+ export declare function emptyManagedModelState(version: number): ManagedModelState;
15
+ export declare function parseManagedModelStateJson(text: string | undefined, version: number): ManagedModelState;
16
+ export declare function readManagedModelState(path: string, version: number): ManagedModelState;
@@ -0,0 +1,21 @@
1
+ import type { ClaudeCodeInstallScope } from '../claude-code-paths';
2
+ import type { HarnessAction, HarnessStatusReport, ModelConfigInput, ModelRoleInput, OperationApplyResult, OperationContext, OperationPlan } from './types';
3
+ export interface ClaudeCodeOperationContext extends OperationContext {
4
+ scope?: ClaudeCodeInstallScope;
5
+ homeDir?: string;
6
+ packageRoot?: string;
7
+ }
8
+ export declare const claudeCodeOperationAdapter: {
9
+ readonly id: "claude";
10
+ readonly displayName: "Claude Code";
11
+ readonly available: true;
12
+ readonly description: "Claude Code plugin package and managed subagent surfaces.";
13
+ readonly actions: HarnessAction[];
14
+ };
15
+ export declare function getClaudeCodeStatus(context?: ClaudeCodeOperationContext): HarnessStatusReport;
16
+ export declare function buildClaudeCodeInstallPlan(context?: ClaudeCodeOperationContext): OperationPlan;
17
+ export declare function buildClaudeCodeUpdatePlan(context?: ClaudeCodeOperationContext): OperationPlan;
18
+ export declare function buildClaudeCodeSyncPlan(context?: ClaudeCodeOperationContext): OperationPlan;
19
+ export declare function buildClaudeCodeModelPlan(input: ModelConfigInput, context?: ClaudeCodeOperationContext): OperationPlan;
20
+ export declare function applyClaudeCodePlan(plan: OperationPlan): OperationApplyResult;
21
+ export declare function defaultClaudeCodeModelRoles(): ModelRoleInput[];
@@ -1,7 +1,14 @@
1
1
  import {
2
+ CLAUDE_CODE_ROLE_NAMES,
2
3
  CODEX_ROLE_NAMES,
4
+ applyClaudeCodePlan,
3
5
  applyCodexPlan,
4
6
  applyOpenCodePlan,
7
+ buildClaudeCodeInstallPlan,
8
+ buildClaudeCodeModelPlan,
9
+ buildClaudeCodeSetupPlan,
10
+ buildClaudeCodeSyncPlan,
11
+ buildClaudeCodeUpdatePlan,
5
12
  buildCodexInstallPlan,
6
13
  buildCodexModelPlan,
7
14
  buildCodexSetupPlan,
@@ -11,17 +18,20 @@ import {
11
18
  buildOpenCodeModelPlan,
12
19
  buildOpenCodeSyncPlan,
13
20
  buildOpenCodeUpdatePlan,
21
+ defaultClaudeCodeModelRoles,
22
+ getClaudeCodeStatus,
14
23
  getCodexStatus,
15
24
  getOpenCodeStatus,
16
25
  listOperationHarnesses,
17
- parseRoleTomlModel
18
- } from "../../chunk-7CTSLCEU.js";
26
+ parseRoleTomlModel,
27
+ parseSubagentModel
28
+ } from "../../chunk-WH3F3GWE.js";
19
29
  import {
20
30
  ALL_AGENT_NAMES,
21
31
  DEFAULT_MODELS,
22
32
  getExistingLiteConfigPath,
23
33
  parseConfig
24
- } from "../../chunk-2SGSRR6L.js";
34
+ } from "../../chunk-3NOVCFN7.js";
25
35
 
26
36
  // src/cli/tui/index.tsx
27
37
  import { render } from "ink";
@@ -173,7 +183,7 @@ function ModelScreen({
173
183
  actions
174
184
  }) {
175
185
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
176
- /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: harness === "codex" ? "Codex writes generated subagent model lines only." : "OpenCode writes role model overrides in thoth-agents config." }),
186
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: harness === "codex" ? "Codex writes generated subagent model lines only." : harness === "claude" ? "Claude Code writes subagent frontmatter model lines (sonnet, opus, haiku, inherit)." : "OpenCode writes role model overrides in thoth-agents config." }),
177
187
  harness === "codex" ? CODEX_MODEL_CATALOG_NOTE.map((note) => /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: note }, note)) : null,
178
188
  roles.map((role, index) => /* @__PURE__ */ jsxs4(
179
189
  Text4,
@@ -575,8 +585,19 @@ function getModelsDevCatalog() {
575
585
  return [];
576
586
  }
577
587
  }
588
+ var CLAUDE_CODE_MODEL_OPTIONS = [
589
+ { id: "sonnet", label: "sonnet", provider: "anthropic" },
590
+ { id: "opus", label: "opus", provider: "anthropic" },
591
+ { id: "haiku", label: "haiku", provider: "anthropic" },
592
+ {
593
+ id: "inherit",
594
+ label: "inherit (main session model)",
595
+ provider: "anthropic"
596
+ }
597
+ ];
578
598
  function getModelOptions(harness) {
579
599
  if (harness === "codex") return getModelsDevCatalog();
600
+ if (harness === "claude") return CLAUDE_CODE_MODEL_OPTIONS;
580
601
  try {
581
602
  const invocation = getOpenCodeModelsInvocation();
582
603
  const output = execFileSync(
@@ -593,6 +614,10 @@ function getModelOptions(harness) {
593
614
  // src/cli/tui/operations.ts
594
615
  var context = { cwd: process.cwd() };
595
616
  var codexContext = { cwd: process.cwd() };
617
+ var claudeCodeContext = {
618
+ cwd: process.cwd(),
619
+ scope: "user"
620
+ };
596
621
  var opencodeModelRoles = ALL_AGENT_NAMES.map(
597
622
  (role) => ({
598
623
  role,
@@ -636,6 +661,27 @@ function getCodexModelRoles(source = codexContext) {
636
661
  return codexModelRoles.map((role) => ({ ...role }));
637
662
  }
638
663
  }
664
+ function getClaudeCodeModelRoles(source = claudeCodeContext) {
665
+ try {
666
+ const plan = buildClaudeCodeSetupPlan({
667
+ dryRun: true,
668
+ reset: false,
669
+ scope: source.scope ?? "user",
670
+ projectRoot: source.cwd,
671
+ homeDir: source.homeDir,
672
+ packageRoot: source.packageRoot
673
+ });
674
+ return CLAUDE_CODE_ROLE_NAMES.map((role) => {
675
+ const item = plan.items.find(
676
+ (candidate) => candidate.kind === "subagent" && candidate.role === role
677
+ );
678
+ const model = item?.content ? parseSubagentModel(item.content) : void 0;
679
+ return { role, model: model ?? "inherit" };
680
+ });
681
+ } catch {
682
+ return defaultClaudeCodeModelRoles();
683
+ }
684
+ }
639
685
  function readRoleModel(config, role) {
640
686
  if (!config || typeof config !== "object" || Array.isArray(config)) {
641
687
  return void 0;
@@ -659,14 +705,31 @@ function getOpenCodeModelRoles() {
659
705
  }));
660
706
  }
661
707
  function buildTuiModelPlan(harness, roles) {
662
- return harness === "opencode" ? buildOpenCodeModelPlan({ harness, dryRun: true, roles }, context) : buildCodexModelPlan({ harness, dryRun: true, roles }, codexContext);
708
+ if (harness === "opencode") {
709
+ return buildOpenCodeModelPlan({ harness, dryRun: true, roles }, context);
710
+ }
711
+ if (harness === "claude") {
712
+ return buildClaudeCodeModelPlan(
713
+ { harness, dryRun: true, roles },
714
+ claudeCodeContext
715
+ );
716
+ }
717
+ return buildCodexModelPlan({ harness, dryRun: true, roles }, codexContext);
663
718
  }
664
719
  var defaultTuiOperations = {
665
720
  status(harness) {
666
- return harness === "opencode" ? getOpenCodeStatus(context) : getCodexStatus(codexContext);
721
+ if (harness === "opencode") return getOpenCodeStatus(context);
722
+ if (harness === "claude") {
723
+ return getClaudeCodeStatus(claudeCodeContext);
724
+ }
725
+ return getCodexStatus(codexContext);
667
726
  },
668
727
  modelRoles(harness) {
669
- return harness === "opencode" ? getOpenCodeModelRoles() : getCodexModelRoles(codexContext);
728
+ if (harness === "opencode") return getOpenCodeModelRoles();
729
+ if (harness === "claude") {
730
+ return getClaudeCodeModelRoles(claudeCodeContext);
731
+ }
732
+ return getCodexModelRoles(codexContext);
670
733
  },
671
734
  modelOptions(harness) {
672
735
  return getModelOptions(harness);
@@ -678,6 +741,19 @@ var defaultTuiOperations = {
678
741
  if (action === "sync") return buildOpenCodeSyncPlan(context);
679
742
  return buildTuiModelPlan(harness, getOpenCodeModelRoles());
680
743
  }
744
+ if (harness === "claude") {
745
+ if (action === "install") {
746
+ return buildClaudeCodeInstallPlan(claudeCodeContext);
747
+ }
748
+ if (action === "update") {
749
+ return buildClaudeCodeUpdatePlan(claudeCodeContext);
750
+ }
751
+ if (action === "sync") return buildClaudeCodeSyncPlan(claudeCodeContext);
752
+ return buildTuiModelPlan(
753
+ harness,
754
+ getClaudeCodeModelRoles(claudeCodeContext)
755
+ );
756
+ }
681
757
  if (action === "install") return buildCodexInstallPlan(codexContext);
682
758
  if (action === "update") return buildCodexUpdatePlan(codexContext);
683
759
  if (action === "sync") return buildCodexSyncPlan(codexContext);
@@ -687,7 +763,9 @@ var defaultTuiOperations = {
687
763
  return buildTuiModelPlan(harness, roles);
688
764
  },
689
765
  apply(plan) {
690
- return plan.harness === "opencode" ? applyOpenCodePlan(plan) : applyCodexPlan(plan);
766
+ if (plan.harness === "opencode") return applyOpenCodePlan(plan);
767
+ if (plan.harness === "claude") return applyClaudeCodePlan(plan);
768
+ return applyCodexPlan(plan);
691
769
  }
692
770
  };
693
771
 
@@ -1185,7 +1263,7 @@ function App({
1185
1263
  /* @__PURE__ */ jsx8(
1186
1264
  Header,
1187
1265
  {
1188
- title: `${modelHarness === "codex" ? "Codex" : "OpenCode"} Models`,
1266
+ title: `${modelHarness === "codex" ? "Codex" : modelHarness === "claude" ? "Claude Code" : "OpenCode"} Models`,
1189
1267
  subtitle: "Enter edits a role. Dirty rows are marked with *."
1190
1268
  }
1191
1269
  ),
@@ -1,4 +1,5 @@
1
1
  import type { HarnessId } from '../../harness/types';
2
+ import { type ClaudeCodeOperationContext } from '../operations/claude-code';
2
3
  import { type CodexOperationContext } from '../operations/codex';
3
4
  import type { HarnessStatusReport, ModelRoleInput, OperationApplyResult, OperationPlan } from '../operations/types';
4
5
  import { type ModelOption } from './model-catalog';
@@ -14,5 +15,6 @@ export interface TuiOperations {
14
15
  export declare const opencodeModelRoles: ModelRoleInput[];
15
16
  export declare const codexModelRoles: ModelRoleInput[];
16
17
  export declare function getCodexModelRoles(source?: CodexOperationContext): ModelRoleInput[];
18
+ export declare function getClaudeCodeModelRoles(source?: ClaudeCodeOperationContext): ModelRoleInput[];
17
19
  export declare function getOpenCodeModelRoles(): ModelRoleInput[];
18
20
  export declare const defaultTuiOperations: TuiOperations;
@@ -1,5 +1,5 @@
1
1
  export type BooleanArg = 'yes' | 'no';
2
- export type InstallAgent = 'opencode' | 'codex';
2
+ export type InstallAgent = 'opencode' | 'codex' | 'claude';
3
3
  export interface InstallArgs {
4
4
  tui: boolean;
5
5
  agent?: InstallAgent;
@@ -9,11 +9,11 @@ export interface InstallArgs {
9
9
  reset?: boolean;
10
10
  }
11
11
  export interface GenerateArgs {
12
- harness: 'codex';
12
+ harness: 'codex' | 'claude';
13
13
  dryRun?: boolean;
14
14
  outputRoot?: string;
15
15
  }
16
- export type OperationHarnessArg = 'opencode' | 'codex';
16
+ export type OperationHarnessArg = 'opencode' | 'codex' | 'claude';
17
17
  export interface CliModelRoleArg {
18
18
  role: string;
19
19
  model: string;
@@ -2,4 +2,4 @@ export * from './constants';
2
2
  export { loadAgentPrompt, loadPluginConfig } from './loader';
3
3
  export type { ThothConfig } from './schema';
4
4
  export * from './schema';
5
- export { getAgentOverride } from './utils';
5
+ export { getAgentOverride, getPrimaryModelId } from './utils';
@@ -143,6 +143,12 @@ export declare const CodexGenerationConfigSchema: z.ZodObject<{
143
143
  dryRun: z.ZodDefault<z.ZodBoolean>;
144
144
  }, z.core.$strip>;
145
145
  export type CodexGenerationConfig = z.infer<typeof CodexGenerationConfigSchema>;
146
+ export declare const ClaudeCodeGenerationConfigSchema: z.ZodObject<{
147
+ enabled: z.ZodDefault<z.ZodBoolean>;
148
+ outputRoot: z.ZodOptional<z.ZodString>;
149
+ dryRun: z.ZodDefault<z.ZodBoolean>;
150
+ }, z.core.$strip>;
151
+ export type ClaudeCodeGenerationConfig = z.infer<typeof ClaudeCodeGenerationConfigSchema>;
146
152
  export declare const FailoverConfigSchema: z.ZodObject<{
147
153
  enabled: z.ZodDefault<z.ZodBoolean>;
148
154
  timeoutMs: z.ZodDefault<z.ZodNumber>;
@@ -275,6 +281,11 @@ export declare const PluginConfigSchema: z.ZodObject<{
275
281
  outputRoot: z.ZodOptional<z.ZodString>;
276
282
  dryRun: z.ZodDefault<z.ZodBoolean>;
277
283
  }, z.core.$strip>>;
284
+ claudeCode: z.ZodOptional<z.ZodObject<{
285
+ enabled: z.ZodDefault<z.ZodBoolean>;
286
+ outputRoot: z.ZodOptional<z.ZodString>;
287
+ dryRun: z.ZodDefault<z.ZodBoolean>;
288
+ }, z.core.$strip>>;
278
289
  }, z.core.$strip>;
279
290
  export type PluginConfig = z.infer<typeof PluginConfigSchema>;
280
291
  export type { AgentName } from './constants';