UNPKG

chorenzo

Version:

Open-source CLI engine that automates your engineering workflow with AI-powered workspace analysis and recipe application

333 lines (238 loc) 13.6 kB
# Chorenzo Recipes Chorenzo uses atomic, composable automation recipes to handle workspace setup and configuration. ## Recipe Levels Recipes operate at different levels with hierarchical application logic: ### Workspace-Only Recipes (`workspace-only`) Apply exclusively to the workspace root and execute once per workspace: - **Use case**: Global configuration, workspace-wide tools, root-level dependencies - **Examples**: Git hooks, workspace package manager setup, global linting rules - **State storage**: Values stored under `workspace` field in state.json - **Ecosystem matching**: Must support the workspace's primary ecosystem - **Behavior**: Never applies to individual projects, even in mixed-ecosystem scenarios ### Project-Only Recipes (`project-only`) Apply exclusively to individual projects and execute once per applicable project: - **Use case**: Project-specific configuration, per-project dependencies, build setup - **Examples**: Framework setup, project-specific linting, test configuration - **State storage**: Values stored under `projects.{project_path}` in state.json - **Ecosystem matching**: Must support each project's individual ecosystem - **Behavior**: Never applies at workspace level, always targets individual projects ### Workspace-Preferred Recipes (`workspace-preferred`) Intelligently apply at workspace or project level based on ecosystem and state compatibility: - **Primary behavior**: Apply at workspace level when the recipe supports the workspace ecosystem - **Fallback behavior**: Apply to individual projects when: - Project ecosystem differs from workspace ecosystem - Recipe doesn't support workspace ecosystem but supports project ecosystems - Project-specific state requirements differ from workspace state - **Use case**: Tools that work best globally but need project-specific handling in mixed environments - **Examples**: Code formatting in JavaScript monorepos with Python projects, linting rules that vary by project - **State storage**: Uses both workspace and project state as appropriate - **Ecosystem matching**: Supports both workspace and project ecosystems dynamically ## Recipe Structure All recipes use a unified structure with a mandatory base `fix.md` file and optional variant-specific additions: ``` recipe_id/ ├── metadata.yaml # Recipe configuration and dependencies ├── prompt.md # Consolidated LLM instructions ├── fix.md # REQUIRED: Base instructions for all ecosystems └── variants/ # OPTIONAL: Variant-specific additions ├── eslint.md # Simple variant name ├── github-actions.md # Simple variant name ├── javascript_eslint.md # Ecosystem-prefixed variant └── python_ruff.md # Ecosystem-prefixed variant ``` **All recipes** must have a `fix.md` file containing base instructions. **Ecosystem-agnostic recipes** use `ecosystems: []` and typically only need the base `fix.md` file. **Ecosystem-specific recipes** can add variant files in the `variants/` directory for specialized implementations. ## File Contents ### metadata.yaml Minimal manifest declaring the recipe's identity, supported ecosystems, and dependencies: ```yaml id: recipe_id # Must match folder name (kebab-case) category: category_id # Grouping for UI display summary: One-sentence description of what this recipe does. level: workspace-preferred # Required: 'workspace-only', 'project-only', or 'workspace-preferred' ecosystems: # Languages/runtimes this recipe supports - id: javascript default_variant: prettier variants: - id: prettier fix_prompt: variants/javascript_prettier.md provides: # Facts this recipe outputs - recipe_id.exists - recipe_id.configured - recipe_id.variant requires: [] # Dependencies (array of {key: fact, equals: value}) or project characteristics ``` > **Note**: For ecosystem-agnostic recipes, use `ecosystems: []` (empty array) instead of listing specific ecosystems. These recipes work across all programming languages and use a single `fix.md` file. ### prompt.md Single unified prompt file with three required sections that focuses on WHAT to investigate and WHY: ```markdown ## Goal One-sentence goal describing what this recipe accomplishes (the end state). ## Investigation 1. **Step one** - Specific, actionable discovery instruction - Tool-agnostic detection commands 2. **Step two** - Focus on detection, not implementation - No vague instructions like "examine files" ## Expected Output - <recipe_id>.key1: Clear description of what this boolean/string represents - <recipe_id>.key2: Another fact this recipe will emit **CRITICAL**: Every field listed in metadata.yaml's "provides" section MUST have: 1. A clear description here explaining what it represents 2. An explanation of how it will be determined (either discovered through investigation OR set as a result of recipe application) ``` **Content Rules for prompt.md**: - ✅ MUST contain: Goal statement, investigation steps to discover current state, expected output facts - ✅ MUST contain: Clear descriptions in Expected Output section for EVERY field listed in the "provides" section of metadata.yaml - ✅ MUST explain: How each provides field will be determined (through investigation or as result of recipe application) - ❌ MUST NOT contain: Implementation instructions, HOW to fix/install/configure, actual code samples or commands **Important**: Investigation prompts are consumed by machines, not humans. Use definitive, declarative language (e.g., "Check if package exists" not "You should check if package exists"). ### fix.md Base implementation instructions that focus on HOW to achieve the desired state: ```markdown # Setting up [Recipe Name] ## Installation Common installation steps that work across ecosystems. ## Configuration Base configuration that applies universally. ## Verification How to verify the setup is working correctly. ``` **Content Rules for fix.md**: - ✅ MUST contain: HOW to install, configure, and verify the setup - ✅ MUST contain: Base implementation that applies to all variants - ✅ MUST contain: Only single-line code samples when truly universal - ❌ MUST NOT contain: Investigation/discovery logic (belongs in prompt.md) - ❌ MUST NOT contain: Variant-specific details (belongs in variant files) - ❌ MUST NOT contain: Multi-line code blocks (explain verbally instead) ### variants/[variant].md Optional variant-specific ADDITIONS that extend the base fix.md: ```markdown # [Variant Name] specific additions ## Additional Installation Additional steps specific to this variant. ## Variant Configuration Configuration specific to this tool or ecosystem. ## Variant Verification Additional verification steps for this variant. ``` **Content Rules for variant files**: - ✅ MUST contain: ONLY variant-specific additions that extend fix.md - ✅ MUST be: Additive content that complements the base implementation - ✅ MUST contain: Only single-line code samples specific to this variant - ❌ MUST NOT contain: Content duplicated from fix.md - ❌ MUST NOT contain: Investigation logic (belongs in prompt.md) - ❌ MUST NOT contain: Base instructions that apply to all variants (belongs in fix.md) - ❌ MUST NOT contain: Multi-line code blocks (explain verbally instead) **Content Concatenation**: When applying a recipe with a variant, the system automatically concatenates `fix.md` content with the variant content: `baseContent + '\n\n' + variantContent`. This ensures variant files only need to contain additional, variant-specific instructions. ## Recipe Design Principles 1. **Single Responsibility**: Each recipe does one thing well 2. **Language Agnostic**: Investigation prompts detect ANY relevant tools, not specific ones 3. **Actionable Instructions**: Every step must be concrete and executable 4. **No Overlapping Concerns**: Integration, CI/CD, and editor config are separate recipes 5. **Clear Facts**: Expected outputs are well-defined contracts for downstream recipes 6. **Machine-First Language**: Use declarative, definitive instructions without human-oriented phrasing 7. **Minimal Configuration**: Only specify non-default settings when necessary 8. **Respect Existing Ignore Files**: Most tools respect .gitignore; only add ignore patterns for files not already gitignored 9. **Level Awareness**: Choose the appropriate level based on the recipe's scope: - `workspace-only` for tools that must be global (git hooks, workspace config) - `project-only` for tools that must be per-project (framework setup, project build) - `workspace-preferred` for tools that work best globally but handle mixed ecosystems ## State Management Recipe state is stored in `.chorenzo/state.json` with a hierarchical structure: ```json { "workspace": { "git-hooks.configured": true, "workspace-eslint.enabled": true }, "projects": { "frontend": { "react-setup.configured": true, "typescript.enabled": true }, "backend": { "node-api.configured": true, "express.setup": "complete" } } } ``` ### State Structure - **Workspace state**: Shared across the entire workspace under the `workspace` key - **Project state**: Per-project values under `projects.{relative_path}` - **Key naming**: Use recipe ID as prefix (e.g., `recipe-id.property`) - **Value types**: Primitives (boolean, string, number) for reliable dependency checking ## Example Recipe See `code_quality/code_formatting/` for a complete example implementing code formatter detection and setup. ## Contributing 1. Create a folder matching your recipe ID (kebab-case) 2. Add `metadata.yaml` with at least: id, summary, level, ecosystems, provides 3. Write `prompt.md` with Goal, Investigation, and Expected Output sections 4. Add fix implementation: - **Most recipes**: Add variant-specific fix prompts under `variants/` directory - **Universal tools only**: Use `ecosystems: []` and create a single `fix.md` file 5. Ensure all paths in metadata.yaml match actual file locations 6. Choose the appropriate level: - `workspace-only` for global tools that must never apply per-project - `project-only` for per-project setup that must never apply globally - `workspace-preferred` for tools that work best globally but handle mixed ecosystems > **Ecosystem-agnostic recipes** should only be used for truly universal tools like Git hooks, editor configs, or documentation templates that work identically across all programming languages. ## Project Characteristics Recipes can use project and workspace characteristics from analysis.json in their `requires` field to conditionally apply based on project properties: ### Workspace Characteristics Access workspace-level properties with the `workspace.` prefix: - `workspace.is_monorepo`: Whether the workspace contains multiple projects (boolean) - `workspace.has_workspace_package_manager`: Whether a workspace-level package manager is detected (boolean) - `workspace.ecosystem`: Primary ecosystem of the workspace (string) - `workspace.cicd`: CI/CD platform detected in the workspace (string) ### Project Characteristics Access project-level properties with the `project.` prefix: - `project.language`: Primary programming language (string) - `project.type`: Project type (e.g., "library", "application") (string) - `project.framework`: Framework used by the project (string) - `project.ecosystem`: Project's ecosystem (string) - `project.has_package_manager`: Whether the project has a package manager (boolean) - `project.dockerized`: Whether the project is containerized (boolean) ### Usage Examples ```yaml # Recipe that only applies to Python projects requires: - key: project.ecosystem equals: python # Recipe that requires a monorepo workspace requires: - key: workspace.is_monorepo equals: true # Recipe that applies to React projects in JavaScript ecosystem requires: - key: project.ecosystem equals: javascript - key: project.framework equals: react ``` ### Important Notes - Project characteristics are **read-only** and cannot be provided by recipes - Reserved keywords (`workspace.*`, `project.*`) cannot be used in the `provides` field - Workspace characteristics are available at both workspace and project levels - Project characteristics are only available when applying to specific projects ## Recipe Validation Use the `chorenzo recipes validate` command to validate recipes. The command automatically detects the input type and validates accordingly: ```bash # Validate by recipe name (searches ~/.chorenzo/recipes) chorenzo recipes validate code-formatting # Validate a local recipe folder chorenzo recipes validate ./my-recipe chorenzo recipes validate ~/my-recipes/custom-recipe # Validate an entire recipe library chorenzo recipes validate ~/.chorenzo/recipes/core chorenzo recipes validate ./my-recipes-library # Validate recipes from a git repository chorenzo recipes validate https://github.com/chorenzo-dev/recipes-core.git ``` ### Validation Features - **Smart Detection**: Automatically detects recipe names, local paths, libraries, and git URLs - **Recipe Discovery**: Finds recipes by name across all libraries in ~/.chorenzo/recipes - **Conflict Resolution**: Shows clear errors when multiple recipes have the same name - **Comprehensive Validation**: Validates metadata structure, required files, and recipe integrity - **Detailed Reporting**: Shows validation results with errors, warnings, and summary statistics