Load a prompt template with fallback chain. Fallback order: 1. Project-specific: {project_dir}/prompts/{name}.md 2. Base template: .claude/templates/{name}.template.md Args: name: The prompt name (without extension), e.g., "initializer_prompt" project_dir: Opti
(name: str, project_dir: Path | None = None)
| 24 | |
| 25 | |
| 26 | def load_prompt(name: str, project_dir: Path | None = None) -> str: |
| 27 | """ |
| 28 | Load a prompt template with fallback chain. |
| 29 | |
| 30 | Fallback order: |
| 31 | 1. Project-specific: {project_dir}/prompts/{name}.md |
| 32 | 2. Base template: .claude/templates/{name}.template.md |
| 33 | |
| 34 | Args: |
| 35 | name: The prompt name (without extension), e.g., "initializer_prompt" |
| 36 | project_dir: Optional project directory for project-specific prompts |
| 37 | |
| 38 | Returns: |
| 39 | The prompt content as a string |
| 40 | |
| 41 | Raises: |
| 42 | FileNotFoundError: If prompt not found in any location |
| 43 | """ |
| 44 | # 1. Try project-specific first |
| 45 | if project_dir: |
| 46 | project_prompts = get_project_prompts_dir(project_dir) |
| 47 | project_path = project_prompts / f"{name}.md" |
| 48 | if project_path.exists(): |
| 49 | try: |
| 50 | return project_path.read_text(encoding="utf-8") |
| 51 | except (OSError, PermissionError) as e: |
| 52 | print(f"Warning: Could not read {project_path}: {e}") |
| 53 | |
| 54 | # 2. Try base template |
| 55 | template_path = TEMPLATES_DIR / f"{name}.template.md" |
| 56 | if template_path.exists(): |
| 57 | try: |
| 58 | return template_path.read_text(encoding="utf-8") |
| 59 | except (OSError, PermissionError) as e: |
| 60 | print(f"Warning: Could not read {template_path}: {e}") |
| 61 | |
| 62 | raise FileNotFoundError( |
| 63 | f"Prompt '{name}' not found in:\n" |
| 64 | f" - Project: {project_dir / 'prompts' if project_dir else 'N/A'}\n" |
| 65 | f" - Templates: {TEMPLATES_DIR}" |
| 66 | ) |
| 67 | |
| 68 | |
| 69 | def get_initializer_prompt(project_dir: Path | None = None) -> str: |
no test coverage detected