@powerhousedao/ph-clint-cli 0.1.0-dev.9 → 0.1.0-dev.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/cli.js +53 -11
  2. package/dist/codegen/actions.d.ts +46 -0
  3. package/dist/codegen/actions.js +424 -0
  4. package/dist/codegen/builders/agent-ts.d.ts +4 -4
  5. package/dist/codegen/builders/agent-ts.js +92 -2
  6. package/dist/codegen/builders/app-index-ts.d.ts +3 -10
  7. package/dist/codegen/builders/app-index-ts.js +30 -20
  8. package/dist/codegen/builders/cli-package-json.js +46 -14
  9. package/dist/codegen/builders/cli-ts.js +87 -49
  10. package/dist/codegen/builders/config-ts.d.ts +1 -1
  11. package/dist/codegen/builders/config-ts.js +2 -8
  12. package/dist/codegen/builders/demo-agent-ts.d.ts +8 -0
  13. package/dist/codegen/builders/demo-agent-ts.js +50 -0
  14. package/dist/codegen/builders/eslint-config-js.d.ts +1 -1
  15. package/dist/codegen/builders/eslint-config-js.js +7 -4
  16. package/dist/codegen/builders/framework-gen-ts.d.ts +11 -6
  17. package/dist/codegen/builders/framework-gen-ts.js +73 -21
  18. package/dist/codegen/builders/framework-ts.js +33 -7
  19. package/dist/codegen/builders/index.d.ts +10 -2
  20. package/dist/codegen/builders/index.js +30 -6
  21. package/dist/codegen/builders/manifest-json.d.ts +6 -0
  22. package/dist/codegen/builders/manifest-json.js +31 -0
  23. package/dist/codegen/builders/mastra-index-ts.d.ts +3 -0
  24. package/dist/codegen/builders/mastra-index-ts.js +47 -5
  25. package/dist/codegen/builders/publish-config-js.d.ts +8 -0
  26. package/dist/codegen/builders/publish-config-js.js +33 -0
  27. package/dist/codegen/builders/readme-md.js +7 -6
  28. package/dist/codegen/builders/root-package-json.js +11 -12
  29. package/dist/codegen/builders/smoke-test-ts.d.ts +2 -0
  30. package/dist/codegen/builders/smoke-test-ts.js +15 -0
  31. package/dist/codegen/exec.d.ts +0 -18
  32. package/dist/codegen/exec.js +0 -27
  33. package/dist/codegen/generated.d.ts +17 -0
  34. package/dist/codegen/generated.js +49 -0
  35. package/dist/codegen/index.d.ts +8 -36
  36. package/dist/codegen/index.js +6 -293
  37. package/dist/codegen/scaffold.d.ts +41 -3
  38. package/dist/codegen/scaffold.js +106 -16
  39. package/dist/commands/clint-project-build.d.ts +77 -1
  40. package/dist/commands/clint-project-build.js +11 -28
  41. package/dist/commands/clint-project-init.d.ts +130 -10
  42. package/dist/commands/clint-project-init.js +72 -47
  43. package/dist/commands/clint-project-publish.d.ts +78 -1
  44. package/dist/commands/clint-project-publish.js +6 -4
  45. package/dist/commands/clint-project-regen.d.ts +77 -1
  46. package/dist/commands/clint-project-regen.js +26 -2
  47. package/dist/commands/clint-skills-sync.d.ts +86 -0
  48. package/dist/commands/clint-skills-sync.js +56 -0
  49. package/dist/framework.d.ts +322 -60
  50. package/dist/framework.gen.d.ts +50 -10
  51. package/dist/framework.js +1 -5
  52. package/{prompts/agent-profiles/AgentBase.md → dist/gen/agent-profiles/PhClintDevAgent.md} +1 -1
  53. package/dist/gen/skills/cli-setup/.cli-docs.md +135 -0
  54. package/dist/gen/skills/cli-setup/SKILL.md +125 -0
  55. package/dist/gen/skills/cli-setup/references/00.assess-cli-needs.md +53 -0
  56. package/dist/gen/skills/cli-setup/references/01.define-config-schema.md +78 -0
  57. package/dist/gen/skills/cli-setup/references/02.wire-cli.md +141 -0
  58. package/dist/gen/skills/cli-setup/references/03.add-entrypoint.md +128 -0
  59. package/dist/gen/skills/cli-setup/references/expected-outcome.md +3 -0
  60. package/dist/gen/skills/command-definition/.cli-docs.md +84 -0
  61. package/dist/gen/skills/command-definition/SKILL.md +99 -0
  62. package/dist/gen/skills/command-definition/references/00.assess-requirements.md +58 -0
  63. package/dist/gen/skills/command-definition/references/01.define-schema.md +72 -0
  64. package/dist/gen/skills/command-definition/references/02.implement-execute.md +118 -0
  65. package/dist/gen/skills/command-definition/references/03.add-prompting.md +54 -0
  66. package/dist/gen/skills/command-definition/references/expected-outcome.md +3 -0
  67. package/dist/gen/skills/service-definition/.cli-docs.md +214 -0
  68. package/dist/gen/skills/service-definition/SKILL.md +148 -0
  69. package/dist/gen/skills/service-definition/references/00.assess-service.md +69 -0
  70. package/dist/gen/skills/service-definition/references/01.define-service.md +166 -0
  71. package/dist/gen/skills/service-definition/references/02.add-preflight.md +132 -0
  72. package/dist/gen/skills/service-definition/references/03.add-project-scanner.md +82 -0
  73. package/dist/gen/skills/service-definition/references/04.wire-events.md +120 -0
  74. package/dist/gen/skills/service-definition/references/expected-outcome.md +3 -0
  75. package/dist/main.js +0 -0
  76. package/dist/services/clint-project.js +21 -0
  77. package/dist/skills/sync.d.ts +40 -0
  78. package/dist/skills/sync.js +119 -0
  79. package/dist/spec/ensure-document.d.ts +17 -0
  80. package/dist/spec/ensure-document.js +56 -0
  81. package/dist/spec/file.d.ts +1 -4
  82. package/dist/spec/file.js +1 -34
  83. package/dist/spec/from-document.d.ts +4 -1
  84. package/dist/spec/from-document.js +4 -16
  85. package/dist/spec/types.d.ts +1 -62
  86. package/dist/spec/types.js +1 -112
  87. package/dist/triggers/publish-trigger.d.ts +81 -0
  88. package/dist/triggers/publish-trigger.js +137 -0
  89. package/dist/triggers/spec-change.d.ts +60 -18
  90. package/dist/triggers/spec-change.js +154 -101
  91. package/package.json +15 -20
  92. package/dist/codegen/builders/publish-config-ts.d.ts +0 -6
  93. package/dist/codegen/builders/publish-config-ts.js +0 -18
  94. package/dist/commands/init.d.ts +0 -57
  95. package/dist/commands/init.js +0 -168
  96. package/dist/commands/regen.d.ts +0 -18
  97. package/dist/commands/regen.js +0 -68
  98. package/prompts/skills-ext/.gitkeep +0 -0
  99. package/prompts/skills-tpl/.gitkeep +0 -0
@@ -6,23 +6,63 @@ export declare const registry: import("@powerhousedao/ph-clint").InferRegistry<r
6
6
  readonly version: 1;
7
7
  readonly reducer: import("document-model").Reducer<import("@powerhousedao/ph-clint-app").PhClintProjectPHState>;
8
8
  readonly actions: {
9
- enableRoutine: (input: import("@powerhousedao/ph-clint-app").EnableRoutineInput) => import("@powerhousedao/ph-clint-app").EnableRoutineAction;
10
- disableRoutine: (input: import("@powerhousedao/ph-clint-app").DisableRoutineInput) => import("@powerhousedao/ph-clint-app").DisableRoutineAction;
9
+ setAgentModel: (input: import("@powerhousedao/ph-clint-app").SetAgentModelInput) => import("@powerhousedao/ph-clint-app").SetAgentModelAction;
10
+ addAgentProfileRef: (input: import("@powerhousedao/ph-clint-app").AddAgentProfileRefInput) => import("@powerhousedao/ph-clint-app").AddAgentProfileRefAction;
11
+ removeAgentProfileRef: (input: import("@powerhousedao/ph-clint-app").RemoveAgentProfileRefInput) => import("@powerhousedao/ph-clint-app").RemoveAgentProfileRefAction;
12
+ reorderAgentProfileRefs: (input: import("@powerhousedao/ph-clint-app").ReorderAgentProfileRefsInput) => import("@powerhousedao/ph-clint-app").ReorderAgentProfileRefsAction;
13
+ addAgentSkill: (input: import("@powerhousedao/ph-clint-app").AddAgentSkillInput) => import("@powerhousedao/ph-clint-app").AddAgentSkillAction;
14
+ removeAgentSkill: (input: import("@powerhousedao/ph-clint-app").RemoveAgentSkillInput) => import("@powerhousedao/ph-clint-app").RemoveAgentSkillAction;
15
+ addAgentToolPattern: (input: import("@powerhousedao/ph-clint-app").AddAgentToolPatternInput) => import("@powerhousedao/ph-clint-app").AddAgentToolPatternAction;
16
+ removeAgentToolPattern: (input: import("@powerhousedao/ph-clint-app").RemoveAgentToolPatternInput) => import("@powerhousedao/ph-clint-app").RemoveAgentToolPatternAction;
17
+ addSubAgent: (input: import("@powerhousedao/ph-clint-app").AddSubAgentInput) => import("@powerhousedao/ph-clint-app").AddSubAgentAction;
18
+ removeSubAgent: (input: import("@powerhousedao/ph-clint-app").RemoveSubAgentInput) => import("@powerhousedao/ph-clint-app").RemoveSubAgentAction;
19
+ setSubAgentName: (input: import("@powerhousedao/ph-clint-app").SetSubAgentNameInput) => import("@powerhousedao/ph-clint-app").SetSubAgentNameAction;
20
+ setSubAgentDescription: (input: import("@powerhousedao/ph-clint-app").SetSubAgentDescriptionInput) => import("@powerhousedao/ph-clint-app").SetSubAgentDescriptionAction;
21
+ setMainAgentName: (input: import("@powerhousedao/ph-clint-app").SetMainAgentNameInput) => import("@powerhousedao/ph-clint-app").SetMainAgentNameAction;
22
+ setMainAgentDescription: (input: import("@powerhousedao/ph-clint-app").SetMainAgentDescriptionInput) => import("@powerhousedao/ph-clint-app").SetMainAgentDescriptionAction;
23
+ clearMainAgentDescription: (input: import("@powerhousedao/ph-clint-app").ClearMainAgentDescriptionInput) => import("@powerhousedao/ph-clint-app").ClearMainAgentDescriptionAction;
24
+ setMainAgentImage: (input: import("@powerhousedao/ph-clint-app").SetMainAgentImageInput) => import("@powerhousedao/ph-clint-app").SetMainAgentImageAction;
25
+ clearMainAgentImage: (input: import("@powerhousedao/ph-clint-app").ClearMainAgentImageInput) => import("@powerhousedao/ph-clint-app").ClearMainAgentImageAction;
26
+ addProfile: (input: import("@powerhousedao/ph-clint-app").AddProfileInput) => import("@powerhousedao/ph-clint-app").AddProfileAction;
27
+ updateProfile: (input: import("@powerhousedao/ph-clint-app").UpdateProfileInput) => import("@powerhousedao/ph-clint-app").UpdateProfileAction;
28
+ removeProfile: (input: import("@powerhousedao/ph-clint-app").RemoveProfileInput) => import("@powerhousedao/ph-clint-app").RemoveProfileAction;
29
+ reorderProfiles: (input: import("@powerhousedao/ph-clint-app").ReorderProfilesInput) => import("@powerhousedao/ph-clint-app").ReorderProfilesAction;
30
+ addModel: (input: import("@powerhousedao/ph-clint-app").AddModelInput) => import("@powerhousedao/ph-clint-app").AddModelAction;
31
+ removeModel: (input: import("@powerhousedao/ph-clint-app").RemoveModelInput) => import("@powerhousedao/ph-clint-app").RemoveModelAction;
11
32
  enableMastra: (input: import("@powerhousedao/ph-clint-app").EnableMastraInput) => import("@powerhousedao/ph-clint-app").EnableMastraAction;
12
33
  disableMastra: (input: import("@powerhousedao/ph-clint-app").DisableMastraInput) => import("@powerhousedao/ph-clint-app").DisableMastraAction;
13
- enablePowerhouse: (input: import("@powerhousedao/ph-clint-app").EnablePowerhouseInput) => import("@powerhousedao/ph-clint-app").EnablePowerhouseAction;
14
- setPowerhouseSwitchboard: (input: import("@powerhousedao/ph-clint-app").SetPowerhouseSwitchboardInput) => import("@powerhousedao/ph-clint-app").SetPowerhouseSwitchboardAction;
15
- setPowerhouseConnect: (input: import("@powerhousedao/ph-clint-app").SetPowerhouseConnectInput) => import("@powerhousedao/ph-clint-app").SetPowerhouseConnectAction;
16
- setPackageName: (input: import("@powerhousedao/ph-clint-app").SetPackageNameInput) => import("@powerhousedao/ph-clint-app").SetPackageNameAction;
17
- clearBin: (input: import("@powerhousedao/ph-clint-app").ClearBinInput) => import("@powerhousedao/ph-clint-app").ClearBinAction;
18
- setBin: (input: import("@powerhousedao/ph-clint-app").SetBinInput) => import("@powerhousedao/ph-clint-app").SetBinAction;
34
+ setEnableChat: (input: import("@powerhousedao/ph-clint-app").SetEnableChatInput) => import("@powerhousedao/ph-clint-app").SetEnableChatAction;
35
+ addSupportedResource: (input: import("@powerhousedao/ph-clint-app").AddSupportedResourceInput) => import("@powerhousedao/ph-clint-app").AddSupportedResourceAction;
36
+ removeSupportedResource: (input: import("@powerhousedao/ph-clint-app").RemoveSupportedResourceInput) => import("@powerhousedao/ph-clint-app").RemoveSupportedResourceAction;
37
+ setProxyEnabled: (input: import("@powerhousedao/ph-clint-app").SetProxyEnabledInput) => import("@powerhousedao/ph-clint-app").SetProxyEnabledAction;
38
+ setObservabilityEnabled: (input: import("@powerhousedao/ph-clint-app").SetObservabilityEnabledInput) => import("@powerhousedao/ph-clint-app").SetObservabilityEnabledAction;
39
+ importSpec: (input: import("@powerhousedao/ph-clint-app").ImportSpecInput) => import("@powerhousedao/ph-clint-app").ImportSpecAction;
40
+ bumpVersion: (input: import("@powerhousedao/ph-clint-app").BumpVersionInput) => import("@powerhousedao/ph-clint-app").BumpVersionAction;
41
+ publishDev: (input: import("@powerhousedao/ph-clint-app").PublishDevInput) => import("@powerhousedao/ph-clint-app").PublishDevAction;
42
+ publishStaging: (input: import("@powerhousedao/ph-clint-app").PublishStagingInput) => import("@powerhousedao/ph-clint-app").PublishStagingAction;
43
+ publishProduction: (input: import("@powerhousedao/ph-clint-app").PublishProductionInput) => import("@powerhousedao/ph-clint-app").PublishProductionAction;
44
+ setPublishStatus: (input: import("@powerhousedao/ph-clint-app").SetPublishStatusInput) => import("@powerhousedao/ph-clint-app").SetPublishStatusAction;
45
+ addExternalSkill: (input: import("@powerhousedao/ph-clint-app").AddExternalSkillInput) => import("@powerhousedao/ph-clint-app").AddExternalSkillAction;
46
+ removeExternalSkill: (input: import("@powerhousedao/ph-clint-app").RemoveExternalSkillInput) => import("@powerhousedao/ph-clint-app").RemoveExternalSkillAction;
47
+ setExternalSkillName: (input: import("@powerhousedao/ph-clint-app").SetExternalSkillNameInput) => import("@powerhousedao/ph-clint-app").SetExternalSkillNameAction;
48
+ setExternalSkillGithubUrl: (input: import("@powerhousedao/ph-clint-app").SetExternalSkillGithubUrlInput) => import("@powerhousedao/ph-clint-app").SetExternalSkillGithubUrlAction;
49
+ addPowerhousePackage: (input: import("@powerhousedao/ph-clint-app").AddPowerhousePackageInput) => import("@powerhousedao/ph-clint-app").AddPowerhousePackageAction;
50
+ removePowerhousePackage: (input: import("@powerhousedao/ph-clint-app").RemovePowerhousePackageInput) => import("@powerhousedao/ph-clint-app").RemovePowerhousePackageAction;
51
+ addPackageDocumentType: (input: import("@powerhousedao/ph-clint-app").AddPackageDocumentTypeInput) => import("@powerhousedao/ph-clint-app").AddPackageDocumentTypeAction;
52
+ removePackageDocumentType: (input: import("@powerhousedao/ph-clint-app").RemovePackageDocumentTypeInput) => import("@powerhousedao/ph-clint-app").RemovePackageDocumentTypeAction;
53
+ setPackageVersion: (input: import("@powerhousedao/ph-clint-app").SetPackageVersionInput) => import("@powerhousedao/ph-clint-app").SetPackageVersionAction;
54
+ enableRoutine: (input: import("@powerhousedao/ph-clint-app").EnableRoutineInput) => import("@powerhousedao/ph-clint-app").EnableRoutineAction;
55
+ disableRoutine: (input: import("@powerhousedao/ph-clint-app").DisableRoutineInput) => import("@powerhousedao/ph-clint-app").DisableRoutineAction;
56
+ setPowerhouseLevel: (input: import("@powerhousedao/ph-clint-app").SetPowerhouseLevelInput) => import("@powerhousedao/ph-clint-app").SetPowerhouseLevelAction;
19
57
  setDescription: (input: import("@powerhousedao/ph-clint-app").SetDescriptionInput) => import("@powerhousedao/ph-clint-app").SetDescriptionAction;
20
58
  setVersion: (input: import("@powerhousedao/ph-clint-app").SetVersionInput) => import("@powerhousedao/ph-clint-app").SetVersionAction;
21
- clearScope: (input: import("@powerhousedao/ph-clint-app").ClearScopeInput) => import("@powerhousedao/ph-clint-app").ClearScopeAction;
22
- setScope: (input: import("@powerhousedao/ph-clint-app").SetScopeInput) => import("@powerhousedao/ph-clint-app").SetScopeAction;
59
+ setPackageIdentifier: (input: import("@powerhousedao/ph-clint-app").SetPackageIdentifierInput) => import("@powerhousedao/ph-clint-app").SetPackageIdentifierAction;
23
60
  setName: (name: string | {
24
61
  name: string;
25
62
  }) => import("document-model").SetNameAction;
63
+ setPreferredEditor: (input: string | null | {
64
+ preferredEditor: string | null;
65
+ }) => import("document-model").SetPreferredEditorAction;
26
66
  undo: (count?: number, scope?: string) => import("document-model").UndoAction;
27
67
  redo: (count?: number, scope?: string) => import("document-model").RedoAction;
28
68
  prune: (start?: number, end?: number, scope?: string) => import("document-model").SchemaPruneAction;
package/dist/framework.js CHANGED
@@ -23,12 +23,8 @@ export const configSchema = z.object({
23
23
  .describe('Port reserved for the impl project (Service B) `pnpm dev`'),
24
24
  phVersion: z
25
25
  .string()
26
- .default('6.0.0-dev.170')
26
+ .default('latest')
27
27
  .describe('Pinned Powerhouse version used when emitting a new impl project'),
28
- projectDocumentId: z
29
- .string()
30
- .optional()
31
- .describe('ID of the powerhouse/ph-clint-project document that drives codegen (set on first regen; edit to switch projects)'),
32
28
  });
33
29
  export const secretsSchema = z.object({
34
30
  apiKey: z.string().optional().describe('Anthropic API key'),
@@ -1,6 +1,6 @@
1
1
  # Agent Base System Prompt
2
2
 
3
- You are {{agentName}}, an agent available through the {{cliName}} CLI.
3
+ You are PhClintDevAgent, an agent available through the CLI.
4
4
 
5
5
  ## Capabilities
6
6
 
@@ -0,0 +1,135 @@
1
+ ## API Reference: CLI Setup
2
+
3
+ ### `defineCli<TSchema, TSecrets>(options): Cli`
4
+
5
+ Factory function that creates a CLI from a declarative options object. Two generic type parameters:
6
+
7
+ - `TSchema extends z.ZodType` — config schema type (defaults to `Record<string, unknown>`)
8
+ - `TSecrets extends z.ZodType` — secrets schema type (defaults to `Record<string, unknown>`)
9
+
10
+ ### `CliOptions<TSchema, TSecrets>` Interface
11
+
12
+ ```typescript
13
+ interface CliOptions<TSchema, TSecrets> {
14
+ name: string; // CLI name (kebab-case, used for config files and env var prefix)
15
+ version: string; // Semantic version (shown in --version)
16
+ root?: string; // Absolute path to package root (resolves sibling packages)
17
+ description: Resolvable<string, Config>; // Static string or function of ({ config, workdir })
18
+ commands: Command<any, any, any>[]; // Array of command definitions
19
+ configSchema?: TSchema; // Zod schema for user-facing config
20
+ secretsSchema?: TSecrets; // Zod schema for sensitive config (API keys, tokens)
21
+ interactive?: InteractiveConfig<Config>; // REPL configuration
22
+ triggers?: Trigger<any, any, any>[]; // Routine loop triggers
23
+ routine?: RoutineConfig; // Routine loop timing & project scanner
24
+ services?: ServiceDefinition<Config>[]; // Background service definitions
25
+ events?: Record<string, (data: any, log: Logger) => void>; // Event handlers
26
+ workdir?: string; // Implementation-level workdir override (hides --workdir flag)
27
+ configDefaults?: Record<string, unknown>; // Layer 5 config defaults
28
+ prompts?: PromptsConfig; // Agent skills & profiles
29
+ }
30
+ ```
31
+
32
+ ### `InteractiveConfig<TConfig>` Interface
33
+
34
+ ```typescript
35
+ interface InteractiveConfig<TConfig> {
36
+ welcome: Resolvable<string, TConfig>; // Welcome message (static or dynamic)
37
+ outputWindow?: number; // Trailing output lines in REPL (default: 6)
38
+ }
39
+ ```
40
+
41
+ ### `Resolvable<T, TConfig>` Type
42
+
43
+ ```typescript
44
+ type Resolvable<T, TConfig> = T | ((ctx: { workdir: string; config: TConfig }) => T);
45
+ ```
46
+
47
+ Allows static values OR dynamic computation based on resolved workdir and config.
48
+
49
+ ### `Cli` Object Interface
50
+
51
+ Methods available on the object returned by `defineCli()`:
52
+
53
+ | Method | Signature | Description |
54
+ |--------|-----------|-------------|
55
+ | `run` | `(argv: string[], options?: RunOptions) => Promise<void>` | Main entry point — parse args, dispatch command or start REPL |
56
+ | `bootstrap` | `(opts?: BootstrapOptions) => Promise<BootstrapResult>` | Initialize runtime without dispatch — for programmatic access |
57
+ | `execute` | `(commandId, args, context?) => Promise<unknown>` | Execute a command directly (programmatic use) |
58
+ | `parseArgs` | `(commandId, argv) => Record<string, unknown>` | Parse CLI argv for a specific command |
59
+ | `getCommand` | `(id: string) => Command \| undefined` | Look up a registered command |
60
+ | `listCommands` | `() => Command[]` | List all registered commands |
61
+ | `generateHelp` | `() => string` | Generate CLI help text |
62
+ | `generateCommandHelp` | `(commandId: string) => string` | Generate help for a specific command |
63
+ | `generateCompletion` | `(shell: string) => string` | Generate shell completion script (bash/zsh/fish) |
64
+ | `configEnvVars` | `() => ConfigEnvVar[]` | List config env var mappings |
65
+ | `getMetadata` | `() => CliMetadata` | JSON-serializable CLI metadata |
66
+ | `configureAgent` | `(loader: AgentLoader<any>) => void` | Set the agent factory (lazy-loaded) |
67
+ | `configureReactor` | `(config: ReactorConfiguration) => void` | Set the reactor configuration (lazy-loaded) |
68
+
69
+ Properties:
70
+
71
+ | Property | Type | Description |
72
+ |----------|------|-------------|
73
+ | `name` | `string` | CLI name |
74
+ | `version` | `string` | CLI version |
75
+ | `description` | `string` | CLI description |
76
+ | `hasAgent` | `boolean` | True when `configureAgent()` has been called |
77
+ | `hasReactor` | `boolean` | True when `configureReactor()` has been called |
78
+
79
+ ### `RunOptions` Interface
80
+
81
+ ```typescript
82
+ interface RunOptions {
83
+ exit?: (code: number) => void; // Override process.exit (for testing)
84
+ stdout?: (message: string) => void; // Capture stdout
85
+ stderr?: (message: string) => void; // Capture stderr
86
+ interactiveInput?: AsyncIterable<string>; // Headless REPL input (for testing)
87
+ resume?: string; // Resume agent conversation by thread ID
88
+ workdir?: string; // Override workdir (for testing)
89
+ configFile?: string; // --config flag value
90
+ logLevel?: LogLevel; // Override log verbosity (default: 'info')
91
+ }
92
+ ```
93
+
94
+ ### `BootstrapOptions` & `BootstrapResult`
95
+
96
+ ```typescript
97
+ interface BootstrapOptions {
98
+ workdir?: string; // Explicit workdir (skips flag/cwd logic)
99
+ configFile?: string; // Config file override
100
+ logLevel?: LogLevel; // Log level (default: 'info')
101
+ stdout?: (text: string) => void;
102
+ stderr?: (text: string) => void;
103
+ }
104
+
105
+ interface BootstrapResult {
106
+ workdir: string;
107
+ config: Record<string, unknown>;
108
+ context: CommandContext;
109
+ getAgent(): Promise<AgentProvider | undefined>;
110
+ get mastraAgent(): Promise<unknown | undefined>;
111
+ }
112
+ ```
113
+
114
+ ### Built-in Commands (Auto-Injected)
115
+
116
+ | Command ID | Condition | Purpose |
117
+ |-----------|-----------|---------|
118
+ | `cli-docs` | Always | Show CLI help (also usable as agent tool) |
119
+ | `config` | When `configSchema` provided | View/modify configuration settings |
120
+ | `{service-id}-start` | Per service definition | Start a background service |
121
+ | `{service-id}-stop` | Per service definition | Stop a running service |
122
+ | `{service-id}-restart` | Per service definition | Restart a service |
123
+ | `{service-id}-ps` | Per service definition | Show service status |
124
+ | `{service-id}-logs` | Per service definition | Tail service logs |
125
+ | `{service-id}-manage` | Per service definition | Interactive management (REPL only) |
126
+ | `{service-id}-ls` | Per service + projectScanner | List discovered projects |
127
+
128
+ ### `readPackageInfo(importMetaUrl)`
129
+
130
+ Utility to read name and version from the nearest `package.json`:
131
+
132
+ ```typescript
133
+ import { readPackageInfo } from '@powerhousedao/ph-clint';
134
+ const { name, version } = readPackageInfo(import.meta.url);
135
+ ```
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: cli-setup
3
+ description: "Set up a new CLI with defineCli, config schemas, entrypoint, and interactive mode"
4
+ metadata:
5
+ author: Powerhouse
6
+ version: "1.0.0"
7
+ ---
8
+
9
+ === BEGIN SKILL BRIEFING ===
10
+
11
+ IMPORTANT: Don't take any action yet. You will be guided through your tasks after the briefing(s). Just process and confirm your understanding.
12
+
13
+ # CLI Setup - Skill Preamble
14
+
15
+ With this skill, you can scaffold or extend a `defineCli()` configuration — the composition root that wires commands, config, services, triggers, and integrations into a single CLI runtime. A single `defineCli()` call produces a CLI that works in command mode (`mycli cmd --arg val`), interactive REPL mode (`/cmd --arg val`), and as an MCP server — all from the same code.
16
+
17
+ ## Core Principles
18
+
19
+ ### defineCli Is Declarative
20
+
21
+ You describe _what_ the CLI has — the framework wires it up. The order of options doesn't matter, but understanding what triggers what does:
22
+
23
+ - `configSchema` present → auto-injects a `config` command for viewing/modifying settings
24
+ - `secretsSchema` present → fields merge into configSchema internally, but are censored in output
25
+ - `services` present → auto-injects per-service management commands (`{id}-start`, `{id}-stop`, etc.)
26
+ - `interactive` present → enables the `-i` flag for REPL mode
27
+ - `triggers` present → enables routine loop
28
+ - `cli-docs` command is always auto-injected (CLI help for the agent)
29
+
30
+ ### Resolvable Values
31
+
32
+ `description` and `interactive.welcome` accept either a static string or a function `({ config, workdir }) => string`. Use functions when the message depends on runtime state — e.g., showing "demo mode" vs "LLM mode" based on whether an API key is configured.
33
+
34
+ ### The Cli Object
35
+
36
+ `defineCli()` returns a `Cli` object — the public API with methods for running, testing, introspection, and metadata. The standard entry point is `cli.run(process.argv)`. For programmatic access (e.g., codegen scripts), use `cli.bootstrap()` which resolves workdir, config, and context without entering the dispatch loop.
37
+
38
+ ### Two Interaction Modes
39
+
40
+ 1. **Command mode** (headless): Execute one subcommand, then exit. Triggered by `mycli cmd --flag val`.
41
+ 2. **Interactive REPL mode**: Persistent session with `/command` syntax and bare text for the default subcommand (typically the agent). Triggered by `mycli -i` or when keep-alive features are active (routine loop, API server).
42
+
43
+ ### 6-Layer Config Resolution
44
+
45
+ Config values are resolved in this priority order (highest wins):
46
+ 1. `--config <file>` flag
47
+ 2. Environment variables: `{CLI_NAME}_{UPPER_SNAKE_FIELD}`
48
+ 3. Local config: `{workdir}/.ph/{cliName}.config.local.json`
49
+ 4. User config: `~/.ph/{cliName}.config.user.json`
50
+ 5. Implementation defaults: `configDefaults` in CliOptions
51
+ 6. Zod schema `.default()` values
52
+
53
+ ### Config vs Secrets
54
+
55
+ - `configSchema` — user-facing settings (model name, ports, feature flags). Shown in `config` command output.
56
+ - `secretsSchema` — sensitive values (API keys, tokens). Merged into configSchema internally but censored as `***` in output unless `--revealSecrets` is used.
57
+
58
+ Put API keys and tokens in `secretsSchema`, not `configSchema`.
59
+
60
+ ### configDefaults vs Schema Defaults
61
+
62
+ - `.default(value)` in the Zod schema → layer 6, the fallback when nothing else is configured
63
+ - `configDefaults` in CliOptions → layer 5, implementation-level overrides that sit above schema defaults but below user/local config
64
+
65
+ Use schema `.default()` for universal sensible defaults. Use `configDefaults` for implementation-specific overrides that differ from the general-purpose default.
66
+
67
+ ### Entry Point Convention
68
+
69
+ The CLI entry point is a TypeScript file with a Node.js shebang:
70
+
71
+ ```typescript
72
+ #!/usr/bin/env node
73
+ import { defineCli } from '@powerhousedao/ph-clint';
74
+ // ... imports ...
75
+ const cli = defineCli({ /* options */ });
76
+ cli.run(process.argv);
77
+ ```
78
+
79
+ The `package.json` needs a `"bin"` field pointing to the compiled output and `"type": "module"` for ESM.
80
+
81
+ ## Common Pitfalls
82
+
83
+ - **Forgetting `version`** — Commander needs it for the `--version` flag; omitting it breaks help output
84
+ - **Putting secrets in `configSchema`** — they show up in `config` command output and metadata, exposing sensitive values
85
+ - **Not setting `interactive.welcome`** — REPL starts with no context, confusing the user
86
+ - **Using `configDefaults` for universal defaults** — use `.default()` in the schema instead; `configDefaults` is for implementation-level overrides only
87
+ - **Calling `configureAgent()` inside `defineCli()`** — it's a method on the returned `Cli` object, called after definition
88
+ - **Forgetting `"type": "module"` in package.json** — ESM imports fail at runtime
89
+ - **Not exporting the `cli` object** — other files (e.g., `mastra/index.ts`) may need it for `cli.bootstrap()`
90
+
91
+ ## When to Use `createTypes()`
92
+
93
+ For projects with a config schema, use the typed factory to get automatic config typing in all commands:
94
+
95
+ ```typescript
96
+ import { createTypes } from '@powerhousedao/ph-clint';
97
+ const { defineCommand, defineTrigger } = createTypes({ configSchema });
98
+ // context.config is now fully typed in every command
99
+ ```
100
+
101
+ ## Codegen-Managed Projects
102
+
103
+ In ph-clint-cli projects, `clint-project-init` generates the initial scaffold including `cli.ts` with `@clint:begin`/`@clint:end` marker regions. The codegen system:
104
+
105
+ - **Generates `cli.ts`** with marker regions for imports, commands, services, triggers, prompts, events, interactive, reactor, and mastra
106
+ - **Generates `framework.gen.ts`** (codegen-owned) with the document registry — regenerated when the spec's `documentTypes` change
107
+ - **Emits `framework.ts`** once (user-owned) with `configSchema`, `secretsSchema`, and `createTypes()` — never overwritten after creation
108
+
109
+ **The agent never hand-edits marker regions in `cli.ts`.** To add or change CLI features:
110
+
111
+ 1. Update `project-spec.json` to declare the new structure
112
+ 2. Run `clint-project-regen` to regenerate the marker regions
113
+ 3. Run `clint-project-build` to verify
114
+
115
+ User-owned code outside markers (`configSchema`, `secretsSchema`, `CLI_NAME`) is preserved across regens. User-owned files (`framework.ts`, `src/commands/*.ts`, `src/services/*.ts`, `src/triggers/*.ts`) are never overwritten.
116
+
117
+ === END OF SKILL BRIEFING ===
118
+
119
+ ## Specific tasks
120
+
121
+ * **Assess Cli Needs** [references/00.assess-cli-needs.md](references/00.assess-cli-needs.md)
122
+ * **Define Config Schema** [references/01.define-config-schema.md](references/01.define-config-schema.md)
123
+ * **Wire Cli** [references/02.wire-cli.md](references/02.wire-cli.md)
124
+ * **Add Entrypoint** [references/03.add-entrypoint.md](references/03.add-entrypoint.md)
125
+ * **Expected Outcome** [references/expected-outcome.md](references/expected-outcome.md)
@@ -0,0 +1,53 @@
1
+ # Phase 0: Assess CLI Needs
2
+
3
+ Before writing any code, determine which features the CLI requires.
4
+
5
+ ## Steps
6
+
7
+ ### 1. Name the CLI
8
+
9
+ Choose a kebab-case name. This name is used for:
10
+ - Config file paths: `{workdir}/.ph/{name}.config.local.json`
11
+ - Environment variable prefix: `{NAME}_*` (UPPER_SNAKE_CASE)
12
+ - Package `"bin"` field and executable name
13
+
14
+ ### 2. Determine version sourcing
15
+
16
+ Choose one:
17
+ - **Hardcoded**: `version: '1.0.0'`
18
+ - **From package.json**: `const { version } = readPackageInfo(import.meta.url)`
19
+
20
+ ### 3. Feature checklist
21
+
22
+ For each feature, determine if the CLI needs it:
23
+
24
+ - [ ] **Custom config?** → needs `configSchema` (Zod object)
25
+ - [ ] **Sensitive config (API keys, tokens)?** → needs `secretsSchema` (Zod object)
26
+ - [ ] **Interactive REPL?** → needs `interactive` with `welcome` message
27
+ - [ ] **Background services?** → needs `services` array of `defineService()` definitions
28
+ - [ ] **Automated triggers?** → needs `triggers` array + `routine` config
29
+ - [ ] **AI agent?** → needs `cli.configureAgent(loader)` after `defineCli()`
30
+ - [ ] **Skill templates?** → needs `prompts` config with `artifacts`, `agents`, `skills`
31
+ - [ ] **Powerhouse documents?** → needs `cli.configureReactor(config)` after `defineCli()`
32
+ - [ ] **Service lifecycle events?** → needs `events` handlers
33
+ - [ ] **Implementation-level workdir override?** → needs `workdir` option (hides `--workdir` flag)
34
+
35
+ ### 4. List commands to register
36
+
37
+ Enumerate all commands that will be passed to the `commands` array. These should already be defined using `defineCommand()` (see the `command-definition` skill). Note which ones need agent-compatible `{ text, data }` returns.
38
+
39
+ ### 5. Detect codegen vs manual project
40
+
41
+ For existing projects, check if `cli.ts` already has `@clint:begin` marker regions:
42
+ - **Codegen-managed**: Markers present — update `project-spec.json` and run `clint-project-regen`. Never hand-edit marker regions.
43
+ - **Manual**: No markers — edit `defineCli()` directly as a regular TypeScript file.
44
+
45
+ For new projects, prefer using `clint-project-init` to generate the scaffold with markers.
46
+
47
+ ### 6. Determine config field names
48
+
49
+ For each config/secret field, verify the auto-generated env var name is sensible:
50
+ - Field `apiKey` on CLI `mycli` → env var `MYCLI_API_KEY`
51
+ - Field `connectPort` on CLI `vetra` → env var `VETRA_CONNECT_PORT`
52
+
53
+ If a name would be confusing, consider renaming the field.
@@ -0,0 +1,78 @@
1
+ # Phase 1: Define Config and Secrets Schemas
2
+
3
+ Design and wire the configuration layer. Skip this phase if the CLI needs no configuration.
4
+
5
+ ## Steps
6
+
7
+ ### 1. Define configSchema
8
+
9
+ Create a Zod object schema for user-facing settings:
10
+
11
+ ```typescript
12
+ import { z } from 'zod';
13
+
14
+ export const configSchema = z.object({
15
+ model: z.string().default('anthropic/claude-sonnet-4-5').describe('LLM model to use'),
16
+ port: z.number().default(4001).describe('Server port'),
17
+ verbose: z.boolean().default(false).describe('Enable verbose output'),
18
+ });
19
+ ```
20
+
21
+ Rules:
22
+ - Every field MUST have `.describe('...')` — it appears in `config` command output, `--help`, and env var listings
23
+ - Use `.default(value)` for fields with sensible defaults
24
+ - Use `.optional()` only for truly optional fields with no default
25
+ - Prefer specific types: `z.enum([...])` for constrained choices, `z.number()` for ports
26
+
27
+ ### 2. Define secretsSchema
28
+
29
+ Create a separate Zod object schema for sensitive values:
30
+
31
+ ```typescript
32
+ export const secretsSchema = z.object({
33
+ apiKey: z.string().optional().describe('LLM API key'),
34
+ dbToken: z.string().optional().describe('Database access token'),
35
+ });
36
+ ```
37
+
38
+ Rules:
39
+ - Secrets are almost always `.optional()` — the CLI should work without them (possibly in a degraded mode)
40
+ - These fields are merged into configSchema internally but censored in output
41
+ - They follow the same env var naming: `{CLI_NAME}_{FIELD}`
42
+
43
+ ### 3. Set configDefaults (if needed)
44
+
45
+ Use `configDefaults` in `defineCli()` for implementation-specific overrides that differ from the schema defaults:
46
+
47
+ ```typescript
48
+ defineCli({
49
+ configSchema,
50
+ configDefaults: {
51
+ port: 8080, // This implementation uses 8080, not the schema default of 4001
52
+ },
53
+ });
54
+ ```
55
+
56
+ This is layer 5 — above schema `.default()` but below user/local config files.
57
+
58
+ ### 4. Use createTypes for typed commands
59
+
60
+ If you have a configSchema, create a typed factory so all commands get typed `context.config`:
61
+
62
+ ```typescript
63
+ // framework.ts
64
+ import { createTypes } from '@powerhousedao/ph-clint';
65
+ import { configSchema, secretsSchema } from './config.js';
66
+
67
+ export const { defineCommand, defineTrigger } = createTypes({ configSchema, secretsSchema });
68
+ export { configSchema, secretsSchema };
69
+ ```
70
+
71
+ Then import `defineCommand` from `./framework.js` instead of `ph-clint` in all command files.
72
+
73
+ ### 5. Verify env var names
74
+
75
+ Run through each field and check the auto-generated env var name:
76
+ - `{CLI_NAME}` is the CLI name uppercased with hyphens replaced by underscores
77
+ - Field keys are converted to UPPER_SNAKE_CASE
78
+ - Example: CLI `my-app`, field `connectPort` → `MY_APP_CONNECT_PORT`
@@ -0,0 +1,141 @@
1
+ # Phase 2: Wire the defineCli Call
2
+
3
+ Compose the `defineCli()` call with all the options determined in Phase 0.
4
+
5
+ ## Steps
6
+
7
+ ### 1. Assemble the core options
8
+
9
+ ```typescript
10
+ import { defineCli } from '@powerhousedao/ph-clint';
11
+ import { configSchema, secretsSchema } from './config.js';
12
+ import { myCommand, otherCommand } from './commands/index.js';
13
+
14
+ export const cli = defineCli({
15
+ name: 'my-app',
16
+ version: '1.0.0',
17
+ description: 'My application CLI',
18
+ commands: [myCommand, otherCommand],
19
+ configSchema,
20
+ secretsSchema,
21
+ });
22
+ ```
23
+
24
+ Always export the `cli` object — other files may need it (e.g., `mastra/index.ts` for `cli.bootstrap()`).
25
+
26
+ ### 2. Configure interactive mode
27
+
28
+ Add an `interactive` block if the CLI supports REPL mode:
29
+
30
+ ```typescript
31
+ interactive: {
32
+ welcome: 'My App CLI — type /help for commands',
33
+ },
34
+ ```
35
+
36
+ For dynamic welcome messages that depend on config:
37
+
38
+ ```typescript
39
+ interactive: {
40
+ welcome: ({ config, workdir }) => {
41
+ const mode = config.apiKey ? config.model : 'demo mode';
42
+ return `My App (${mode})\nWorkdir: ${workdir}`;
43
+ },
44
+ },
45
+ ```
46
+
47
+ ### 3. Add services (if needed)
48
+
49
+ ```typescript
50
+ import { myService } from './services/my-service.js';
51
+
52
+ defineCli({
53
+ // ...
54
+ services: [myService],
55
+ });
56
+ ```
57
+
58
+ This auto-injects `my-service-start`, `my-service-stop`, `my-service-restart`, `my-service-ps`, `my-service-logs`, and `my-service-manage` commands.
59
+
60
+ ### 4. Add event handlers (if needed)
61
+
62
+ Wire lifecycle events for services or custom events:
63
+
64
+ ```typescript
65
+ events: {
66
+ 'service:ready': (event, log) => {
67
+ log.info(`${event.name} is ready`);
68
+ },
69
+ 'service:failed': (event, log) => {
70
+ log.error(`${event.name} failed: ${event.error}`);
71
+ },
72
+ 'service:stopped': (event, log) => {
73
+ log.info(`${event.name} stopped`);
74
+ },
75
+ },
76
+ ```
77
+
78
+ Available service events: `service:pattern-matched`, `service:ready`, `service:failed`, `service:restarting`, `service:stopped`. Each receives `(event, log)` where `log` is a structured Logger.
79
+
80
+ ### 5. Add prompts config (if skills are needed)
81
+
82
+ ```typescript
83
+ import path from 'node:path';
84
+
85
+ prompts: {
86
+ artifacts: [path.join(CLI_ROOT, 'gen', 'skills')],
87
+ agents: {
88
+ 'my-agent': {
89
+ name: 'MyAgent',
90
+ sections: ['AgentBase.md', 'MySpecialization.md'],
91
+ skills: ['skill-one', 'skill-two'],
92
+ },
93
+ },
94
+ skills: {
95
+ 'skill-one': {
96
+ description: 'Description of skill one',
97
+ inputSchema: z.object({
98
+ mode: z.enum(['expert', 'discovery']).default('expert').describe('Interaction mode'),
99
+ }),
100
+ instructionTemplate: 'Use your {{skillId}} skill in {{mode}} mode for: {{prompt}}',
101
+ },
102
+ },
103
+ },
104
+ ```
105
+
106
+ ### 6. Call configureAgent / configureReactor (if needed)
107
+
108
+ These are called AFTER `defineCli()` — they are methods on the returned `Cli` object:
109
+
110
+ ```typescript
111
+ export const cli = defineCli({ /* ... */ });
112
+
113
+ // Agent integration (Mastra)
114
+ cli.configureAgent(createAgent);
115
+
116
+ // Reactor integration (Powerhouse)
117
+ cli.configureReactor({
118
+ registry: [/* document models */],
119
+ // ...
120
+ });
121
+ ```
122
+
123
+ Both are lazy-loaded — the actual agent/reactor is only created when first accessed.
124
+
125
+ ### 7. Codegen projects: use spec + regen
126
+
127
+ In codegen-managed projects, do NOT manually edit `cli.ts` marker regions. Instead:
128
+
129
+ 1. Update `project-spec.json` with the new features (commands, services, triggers, integrations)
130
+ 2. Run `clint-project-regen` to regenerate marker regions
131
+ 3. Edit user-owned files directly: `framework.ts` for config/secrets schemas, `src/commands/*.ts` for commands, etc.
132
+
133
+ Core options outside markers (`name`, `version`, `description`, `configSchema`, `secretsSchema`) are in the user-editable zone — edit those directly in `cli.ts`.
134
+
135
+ ### 8. Verify built-in commands
136
+
137
+ After wiring, confirm these commands will be auto-injected:
138
+ - `cli-docs` — always present
139
+ - `config` — present if `configSchema` was provided
140
+ - Service commands — present for each entry in `services`
141
+ - Skill commands — present for each entry in `prompts.skills`