# TREE.md

├── bin/
│   ├── ps.ts
│   │   # CLI for `ps`
│   │   └── uses PromptScript to process .ps.md files
│   │
│   │   # Data Flow:
│   │   # 1. Parse CLI arguments for input/output
│   │   # 2. Create PromptScript instance
│   │   # 3. PromptScript.process() → extracts, executes, replaces
│   │   # 4. Writes processed output to file or stdout
│   │
│   └── oneshot.ts
│       # CLI for `oneshot`
│       └── uses Oneshot to send prompts to AI providers
│       │
│       # Data Flow:
│       # 1. Parse CLI arguments (model, prompt, system prompt, variations, iterations)
│       # 2. Select provider (Anthropic or OpenAI)
│       # 3. Oneshot.process() → single or multiple calls to chosen AI provider
│       # 4. Print or save responses
│       │
│       └── oneshotcat.ts
│           # CLI for `oneshotcat`
│           └── 1-step “ps + oneshot” combo
│           │
│           # Data Flow:
│           # 1. Parse CLI arguments (model, .ps.md file, etc.)
│           # 2. PromptScript.process() to expand commands
│           # 3. Oneshot.process() on expanded text
│           # 4. Print or save combined response
│
├── src/
│   ├── config.ts
│   │   # Loads and merges config from env, .rc file, CLI
│   │   # exports loadConfig(options?: ToolConfig): ToolConfig
│   │
│   ├── errors.ts
│   │   # Centralized error definitions
│   │   └── class ToolError
│   │       # Extend base Error; includes error codes & details
│   │
│   ├── prompt-script.ts
│   │   # Core logic for the `ps` tool
│   │   └── class PromptScript
│   │       # 1) parse .ps.md file
│   │       # 2) extract all @cmd[...] occurrences
│   │       # 3) execute each command
│   │       # 4) replace placeholders with command output in the final text
│   │       │
│   │       # Data Flow:
│   │       # 1. readFile → extractCommands(content)
│   │       # 2. for each command → executeCommand(command)
│   │       # 3. replaceCommands(content, results)
│   │       # 4. return final content string
│   │       │
│   │       ├── constructor(options: PSOptions)
│   │       ├── async process(): Promise<string>
│   │       ├── async extractCommands(content: string): Promise<Command[]>
│   │       ├── async executeCommand(cmd: Command): Promise<CommandResult>
│   │       └── async replaceCommands(content: string, results: CommandResult[]): Promise<string>
│   │
│   ├── oneshot.ts
│   │   # Core logic for the `oneshot` tool
│   │   └── class Oneshot
│   │       # 1) Reads prompt from file
│   │       # 2) Possibly merges with system prompt
│   │       # 3) Possibly iterates over variations
│   │       # 4) Calls chosen AI provider
│   │       # 5) Returns aggregated result
│   │       │
│   │       # Data Flow:
│   │       # 1. readFile(promptFile) → userPrompt
│   │       # 2. for each variation:
│   │       #      → provider.sendPrompt({ model, systemPrompt, userPrompt })
│   │       # 3. collects responses in an array
│   │       # 4. returns results
│   │       │
│   │       ├── constructor(options: OneshotOptions, provider: AIProvider)
│   │       └── async process(): Promise<ResponseEnvelope[]>
│   │
│   ├── oneshotcat.ts
│   │   # Combines PromptScript + Oneshot in a single class
│   │   └── class Oneshotcat
│   │       # 1) Uses PromptScript to expand .ps.md file
│   │       # 2) Then uses Oneshot to call AI
│   │       │
│   │       # Data Flow:
│   │       # 1. promptScript.process() → expandedMarkdown
│   │       # 2. oneshot.process() with expandedMarkdown
│   │       # 3. return aggregated results
│   │       │
│   │       ├── constructor(options: OneshotOptions & PSOptions)
│   │       └── async process(): Promise<ResponseEnvelope[]>
│   │
│   └── providers/
│       ├── anthropic.ts
│       │   # Anthropic-specific AI calls
│       │   └── class AnthropicProvider implements AIProvider
│       │       # uses anthropicApiKey from config
│       │       # calls Anthropic's API endpoint
│       │       # returns string
│       │
│       └── openai.ts
│           # OpenAI-specific AI calls
│           └── class OpenAIProvider implements AIProvider
│               # uses openaiApiKey from config
│               # calls OpenAI's API endpoint
│               # returns string
│
├── tests/
│   ├── prompt-script.test.ts
│   ├── oneshot.test.ts
│   └── oneshotcat.test.ts
│
└── package.json
