Compare commits

..

1 Commits

Author SHA1 Message Date
Markus Ende d70f7b0d97
Merge 147144a1ec into eeb773c33d 2026-02-20 20:36:36 -06:00
25 changed files with 325 additions and 313 deletions

View File

@ -1,6 +0,0 @@
---
name: bmad-os-audit-file-refs
description: Audit BMAD source files for file-reference convention violations using parallel Haiku subagents. Use when users requests an "audit file references" for a skill, workflow or task.
---
Read `prompts/instructions.md` and execute.

View File

@ -1,59 +0,0 @@
# audit-file-refs
Audit new-format BMAD source files for file-reference convention violations using parallel Haiku subagents.
## Convention
In new-format BMAD workflow and task files (`src/bmm/`, `src/core/`, `src/utility/`), every file path reference must use one of these **valid** forms:
- `{project-root}/_bmad/path/to/file.ext` — canonical form, always correct
- `{installed_path}/relative/path` — valid in new-format step files (always defined by workflow.md before any step is reached)
- Template/runtime variables: `{nextStepFile}`, `{workflowFile}`, `{{mustache}}`, `{output_folder}`, `{communication_language}`, etc. — skip these, they are substituted at runtime
**Flag any reference that uses:**
- `./step-NN.md` or `../something.md` — relative paths
- `step-NN.md` — bare filename with no path prefix
- `steps/step-NN.md` — bare steps-relative path (missing `{project-root}/_bmad/...` prefix)
- `` `_bmad/core/tasks/help.md` `` — bare `_bmad/` path (missing `{project-root}/`)
- `/Users/...`, `/home/...`, `C:\...` — absolute system paths
References inside fenced code blocks (``` ``` ```) are examples — skip them.
Old-format files in `src/bmm/workflows/4-implementation/` use `{installed_path}` by design within the XML calling chain — exclude that directory entirely.
## Steps
1. Run this command to get the file list:
```
find src/bmm src/core src/utility -type f \( -name "*.md" -o -name "*.yaml" \) | grep -v "4-implementation" | sort
```
2. Divide the resulting file paths into batches of roughly 20 files each.
3. For each batch, spawn a subagent (`subagent_type: "Explore"`, `model: "haiku"`) with this prompt (fill in the actual file paths):
> Read each of these files (use the Read tool on each):
> [list the file paths from this batch]
>
> For each file, identify every line that contains a file path reference that violates the convention described below. Skip references inside fenced code blocks. Skip template variables (anything containing `{` that isn't `{project-root}` or `{installed_path}`).
>
> **Valid references:** `{project-root}/_bmad/...`, `{installed_path}/...`, template variables.
> **Flag:** bare filenames (`step-NN.md`), `./` or `../` relative paths, bare `steps/` paths, bare `_bmad/` paths (without `{project-root}/`), absolute system paths.
>
> Return findings as a list:
> `path/to/file.md:LINE_NUMBER | VIOLATION_TYPE | offending text`
>
> If a file has no violations, include it as: `path/to/file.md | clean`
>
> End your response with a single line: `FILES CHECKED: N` where N is the exact number of files you read.
4. Collect all findings from all subagents.
5. **Self-check before reporting:** Count the total number of files returned by the `find` command. Sum the `FILES CHECKED: N` values across all subagent responses. If the totals do not match, identify which files are missing and re-run subagents for those files before proceeding. Do not produce the final report until all files are accounted for.
6. Output a final report:
- Group findings by violation type
- List each finding as `file:line — offending text`
- Show total count of violations and number of affected files
- If nothing found, say "All files conform to the convention."

View File

@ -1,6 +1,7 @@
---
name: bmad-os-changelog-social
description: Generate social media announcements for Discord, Twitter, and LinkedIn from the latest changelog entry. Use when user asks to 'create release announcement' or 'create social posts' or share changelog updates.
description: Generate social media announcements for Discord, Twitter, and LinkedIn from the latest changelog entry. Use when user asks to create release announcements, social posts, or share changelog updates. Reads CHANGELOG.md in current working directory. Reference examples/ for tone and format.
disable-model-invocation: true
---
# Changelog Social

View File

@ -1,6 +1,7 @@
---
name: bmad-os-diataxis-style-fix
description: Fixes documentation to comply with Diataxis framework and BMad Method style guide rules. Use when user asks to check or fix style of files under the docs folder.
description: Fixes documentation to comply with Diataxis framework and BMad Method style guide rules
disable-model-invocation: true
---
Read `prompts/instructions.md` and execute.

View File

@ -1,6 +1,7 @@
---
name: bmad-os-draft-changelog
description: "Analyzes changes since last release and updates CHANGELOG.md ONLY. Use when users requests 'update the changelog' or 'prepare changelog release notes'"
description: Analyzes changes since last release and updates CHANGELOG.md ONLY. Does NOT trigger releases.
disable-model-invocation: true
---
Read `prompts/instructions.md` and execute.

View File

@ -0,0 +1,14 @@
# gh-triage
Fetches all GitHub issues via gh CLI and uses AI agents to deeply analyze, cluster, and prioritize issues.
## Usage
Run from within any BMad Method repository to triage issues.
## What It Does
1. Fetches all open issues via `gh issue list`
2. Splits issues into batches
3. Launches parallel agents to analyze each batch
4. Generates comprehensive triage report to `_bmad-output/triage-reports/`

View File

@ -1,6 +1,12 @@
---
name: bmad-os-gh-triage
description: Analyze all github issues. Use when the user says 'triage the github issues' or 'analyze open github issues'.
description: Fetch all GitHub issues via gh CLI and use AI agents to deeply analyze, cluster, and prioritize issues
license: MIT
disable-model-invocation: true
metadata:
author: bmad-code-org
version: "3.0.0"
compatibility: Requires gh CLI, git repository, and BMad Method with Task tool support
---
Read `prompts/instructions.md` and execute.

View File

@ -0,0 +1,24 @@
# release-module
Automates the complete release process for npm modules.
## Usage
Run from project root or pass project path:
```
bmad-utility-skills:release-module
```
## Prerequisite
First run `draft-changelog` to analyze changes and create a draft changelog.
## What It Does
1. Gets and confirms changelog entry
2. Confirms version bump type (patch/minor/major)
3. Updates CHANGELOG.md
4. Bumps version with `npm version`
5. Pushes git tag
6. Publishes to npm
7. Creates GitHub release

View File

@ -1,6 +1,7 @@
---
name: bmad-os-release-module
description: Perform requested version bump, git tag, npm publish, GitHub release. Use when user requests 'perform a release' only.
description: Automates the complete release process for npm modules - version bump, changelog, git tag, npm publish, GitHub release
disable-model-invocation: true
---
Read `prompts/instructions.md` and execute.

View File

@ -1,6 +0,0 @@
---
name: bmad-os-review-pr
description: Adversarial PR review tool (Raven's Verdict). Cynical deep review transformed into professional engineering findings. Use when user asks to 'review a PR' and provides a PR url or id.
---
Read `prompts/instructions.md` and execute.

2
.gitignore vendored
View File

@ -37,7 +37,6 @@ CLAUDE.local.md
.serena/
.claude/settings.local.json
.junie/
.agents/
z*/
@ -47,7 +46,6 @@ _bmad-output
# .augment/ is gitignored except tracked config files — add exceptions explicitly
.augment/*
!.augment/code_review_guidelines.yaml
.codebuddy
.crush
.cursor
.iflow

View File

@ -44,7 +44,7 @@ First, check if the output document already exists:
If the document exists and has frontmatter with `stepsCompleted`:
- **STOP here** and load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md` immediately
- **STOP here** and load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-01b-continue.md` immediately
- Do not proceed with any initialization tasks
- Let step-01b handle the continuation logic
@ -148,6 +148,6 @@ Ready to begin architectural decision making. Do you have any other documents yo
## NEXT STEP:
After user selects [C] to continue, only after ensuring all the template output has been created, then load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md` to analyze the project context and begin architectural decision making.
After user selects [C] to continue, only after ensuring all the template output has been created, then load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-02-context.md` to analyze the project context and begin architectural decision making.
Remember: Do NOT proceed to step-02 until user explicitly selects [C] from the menu and setup is confirmed!

View File

@ -85,7 +85,7 @@ Show the user their current progress:
- Identify the next step based on `stepsCompleted`
- Load the appropriate step file to continue
- Example: If `stepsCompleted: [1, 2, 3]`, load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md`
- Example: If `stepsCompleted: [1, 2, 3]`, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-04-decisions.md`
#### If 'C' (Continue to next logical step):
@ -103,7 +103,7 @@ Show the user their current progress:
#### If 'X' (Start over):
- Confirm: "This will delete all existing architectural decisions. Are you sure? (y/n)"
- If confirmed: Delete existing document and read fully and follow: `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md`
- If confirmed: Delete existing document and read fully and follow: `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-01-init.md`
- If not confirmed: Return to continuation menu
### 4. Navigate to Selected Step
@ -162,12 +162,12 @@ After user makes choice:
After user selects their continuation option, load the appropriate step file based on their choice. The step file will handle the detailed work from that point forward.
Valid step files to load:
- `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-02-context.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-03-starter.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-04-decisions.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-05-patterns.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-06-structure.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-07-validation.md`
- `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-08-complete.md`
Remember: The goal is smooth, transparent resumption that respects the work already done while giving the user control over how to proceed.

View File

@ -188,7 +188,7 @@ Show the generated content and present choices:
- Append the final content to `{planning_artifacts}/architecture.md`
- Update frontmatter: `stepsCompleted: [1, 2]`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-03-starter.md`
## APPEND TO DOCUMENT:
@ -219,6 +219,6 @@ When user selects 'C', append the content directly to the document using the str
## NEXT STEP:
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md` to evaluate starter template options.
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-03-starter.md` to evaluate starter template options.
Remember: Do NOT proceed to step-03 until user explicitly selects 'C' from the A/P/C menu and content is saved!

View File

@ -294,7 +294,7 @@ Show the generated content and present choices:
- Append the final content to `{planning_artifacts}/architecture.md`
- Update frontmatter: `stepsCompleted: [1, 2, 3]`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-04-decisions.md`
## APPEND TO DOCUMENT:
@ -324,6 +324,6 @@ When user selects 'C', append the content directly to the document using the str
## NEXT STEP:
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md` to begin making specific architectural decisions.
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-04-decisions.md` to begin making specific architectural decisions.
Remember: Do NOT proceed to step-04 until user explicitly selects 'C' from the A/P/C menu and content is saved!

View File

@ -282,7 +282,7 @@ Show the generated decisions content and present choices:
- Append the final content to `{planning_artifacts}/architecture.md`
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4]`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-05-patterns.md`
## APPEND TO DOCUMENT:
@ -313,6 +313,6 @@ When user selects 'C', append the content directly to the document using the str
## NEXT STEP:
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md` to define implementation patterns that ensure consistency across AI agents.
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-05-patterns.md` to define implementation patterns that ensure consistency across AI agents.
Remember: Do NOT proceed to step-05 until user explicitly selects 'C' from the A/P/C menu and content is saved!

View File

@ -323,7 +323,7 @@ Show the generated patterns content and present choices:
- Append the final content to `{planning_artifacts}/architecture.md`
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5]`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-06-structure.md`
## APPEND TO DOCUMENT:
@ -354,6 +354,6 @@ When user selects 'C', append the content directly to the document using the str
## NEXT STEP:
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md` to define the complete project structure.
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-06-structure.md` to define the complete project structure.
Remember: Do NOT proceed to step-06 until user explicitly selects 'C' from the A/P/C menu and content is saved!

View File

@ -343,7 +343,7 @@ Show the generated project structure content and present choices:
- Append the final content to `{planning_artifacts}/architecture.md`
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5, 6]`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-07-validation.md`
## APPEND TO DOCUMENT:
@ -374,6 +374,6 @@ When user selects 'C', append the content directly to the document using the str
## NEXT STEP:
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md` to validate architectural coherence and completeness.
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-07-validation.md` to validate architectural coherence and completeness.
Remember: Do NOT proceed to step-07 until user explicitly selects 'C' from the A/P/C menu and content is saved!

View File

@ -323,7 +323,7 @@ Show the validation results and present choices:
- Append the final content to `{planning_artifacts}/architecture.md`
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5, 6, 7]`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md`
- Load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-08-complete.md`
## APPEND TO DOCUMENT:
@ -354,6 +354,6 @@ When user selects 'C', append the content directly to the document using the str
## NEXT STEP:
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md` to complete the workflow and provide implementation guidance.
After user selects 'C' and content is saved to document, load `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-08-complete.md` to complete the workflow and provide implementation guidance.
Remember: Do NOT proceed to step-08 until user explicitly selects 'C' from the A/P/C menu and content is saved!

View File

@ -44,6 +44,6 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
## EXECUTION
Read fully and follow: `{project-root}/_bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md` to begin the workflow.
Read fully and follow: `{project-root}/_bmad/bmm/workflows/3-solutioning/architecture/steps/step-01-init.md` to begin the workflow.
**Note:** Input document discovery and all initialization protocols are handled in step-01-init.md.

View File

@ -1,7 +1,6 @@
const path = require('node:path');
const os = require('node:os');
const fs = require('fs-extra');
const yaml = require('yaml');
const os = require('node:os');
const { BaseIdeSetup } = require('./_base-ide');
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
@ -18,6 +17,57 @@ class CodexSetup extends BaseIdeSetup {
super('codex', 'Codex', false);
}
/**
* Collect configuration choices before installation
* @param {Object} options - Configuration options
* @returns {Object} Collected configuration
*/
async collectConfiguration(options = {}) {
// Non-interactive mode: use default (project) - recommended for real work
if (options.skipPrompts) {
return { installLocation: options.codexLocation || 'project' };
}
let confirmed = false;
let installLocation = 'global';
while (!confirmed) {
installLocation = await prompts.select({
message: 'Where would you like to install Codex CLI prompts?',
choices: [
{
name: 'Global - Simple for single project ' + '(~/.codex/prompts, but references THIS project only)',
value: 'global',
},
{
name: `Project-specific - Recommended for real work (requires CODEX_HOME=<project-dir>${path.sep}.codex)`,
value: 'project',
},
],
default: 'global',
});
// Show brief confirmation hint (detailed instructions available via verbose)
if (installLocation === 'project') {
await prompts.log.info('Prompts installed to: <project>/.codex/prompts (requires CODEX_HOME)');
} else {
await prompts.log.info('Prompts installed to: ~/.codex/prompts');
}
// Confirm the choice
confirmed = await prompts.confirm({
message: 'Proceed with this installation option?',
default: true,
});
if (!confirmed) {
await prompts.log.warn("Let's choose a different installation option.");
}
}
return { installLocation };
}
/**
* Setup Codex configuration
* @param {string} projectDir - Project directory
@ -30,25 +80,20 @@ class CodexSetup extends BaseIdeSetup {
// Always use CLI mode
const mode = 'cli';
// Get installation location from pre-collected config or default to global
const installLocation = options.preCollectedConfig?.installLocation || 'global';
const { artifacts, counts } = await this.collectClaudeArtifacts(projectDir, bmadDir, options);
// Clean up old .codex/prompts locations (both global and project)
const oldGlobalDir = this.getOldCodexPromptDir(null, 'global');
await this.clearOldBmadFiles(oldGlobalDir, options);
const oldProjectDir = this.getOldCodexPromptDir(projectDir, 'project');
await this.clearOldBmadFiles(oldProjectDir, options);
// Install to .agents/skills
const destDir = this.getCodexSkillsDir(projectDir);
const destDir = this.getCodexPromptDir(projectDir, installLocation);
await fs.ensureDir(destDir);
await this.clearOldBmadSkills(destDir, options);
await this.clearOldBmadFiles(destDir, options);
// Collect and write agent skills
// Collect artifacts and write using underscore format
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
const agentCount = await this.writeSkillArtifacts(destDir, agentArtifacts, 'agent-launcher');
const agentCount = await agentGen.writeDashArtifacts(destDir, agentArtifacts);
// Collect and write task skills
const tasks = await getTasksFromBmad(bmadDir, options.selectedModules || []);
const taskArtifacts = [];
for (const task of tasks) {
@ -72,23 +117,19 @@ class CodexSetup extends BaseIdeSetup {
});
}
const ttGen = new TaskToolCommandGenerator(this.bmadFolderName);
const taskSkillArtifacts = taskArtifacts.map((artifact) => ({
...artifact,
content: ttGen.generateCommandContent(artifact, artifact.type),
}));
const tasksWritten = await this.writeSkillArtifacts(destDir, taskSkillArtifacts, 'task');
// Collect and write workflow skills
const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
const workflowCount = await this.writeSkillArtifacts(destDir, workflowArtifacts, 'workflow-command');
const workflowCount = await workflowGenerator.writeDashArtifacts(destDir, workflowArtifacts);
// Also write tasks using underscore format
const ttGen = new TaskToolCommandGenerator(this.bmadFolderName);
const tasksWritten = await ttGen.writeDashArtifacts(destDir, taskArtifacts);
const written = agentCount + workflowCount + tasksWritten;
if (!options.silent) {
await prompts.log.success(
`${this.name} configured: ${counts.agents} agents, ${counts.workflows} workflows, ${counts.tasks} tasks, ${written} skills → ${destDir}`,
`${this.name} configured: ${counts.agents} agents, ${counts.workflows} workflows, ${counts.tasks} tasks, ${written} files → ${destDir}`,
);
}
@ -99,18 +140,35 @@ class CodexSetup extends BaseIdeSetup {
counts,
destination: destDir,
written,
installLocation,
};
}
/**
* Detect Codex installation by checking for BMAD skills
* Detect Codex installation by checking for BMAD prompt exports
*/
async detect(projectDir) {
const dir = this.getCodexSkillsDir(projectDir || process.cwd());
// Check both global and project-specific locations
const globalDir = this.getCodexPromptDir(null, 'global');
const projectDir_local = projectDir || process.cwd();
const projectSpecificDir = this.getCodexPromptDir(projectDir_local, 'project');
if (await fs.pathExists(dir)) {
// Check global location
if (await fs.pathExists(globalDir)) {
try {
const entries = await fs.readdir(dir);
const entries = await fs.readdir(globalDir);
if (entries && entries.some((entry) => entry && typeof entry === 'string' && entry.startsWith('bmad'))) {
return true;
}
} catch {
// Ignore errors
}
}
// Check project-specific location
if (await fs.pathExists(projectSpecificDir)) {
try {
const entries = await fs.readdir(projectSpecificDir);
if (entries && entries.some((entry) => entry && typeof entry === 'string' && entry.startsWith('bmad'))) {
return true;
}
@ -182,138 +240,26 @@ class CodexSetup extends BaseIdeSetup {
};
}
getCodexSkillsDir(projectDir) {
if (!projectDir) {
throw new Error('projectDir is required for project-scoped skill installation');
}
return path.join(projectDir, '.agents', 'skills');
}
/**
* Get the old .codex/prompts directory for cleanup purposes
*/
getOldCodexPromptDir(projectDir = null, location = 'global') {
getCodexPromptDir(projectDir = null, location = 'global') {
if (location === 'project' && projectDir) {
return path.join(projectDir, '.codex', 'prompts');
}
return path.join(os.homedir(), '.codex', 'prompts');
}
/**
* Write artifacts as Agent Skills (agentskills.io format).
* Each artifact becomes a directory containing SKILL.md.
* @param {string} destDir - Base skills directory
* @param {Array} artifacts - Artifacts to write
* @param {string} artifactType - Type filter (e.g., 'agent-launcher', 'workflow-command', 'task')
* @returns {number} Number of skills written
*/
async writeSkillArtifacts(destDir, artifacts, artifactType) {
let writtenCount = 0;
async flattenAndWriteArtifacts(artifacts, destDir) {
let written = 0;
for (const artifact of artifacts) {
// Filter by type if the artifact has a type field
if (artifact.type && artifact.type !== artifactType) {
continue;
const flattenedName = this.flattenFilename(artifact.relativePath);
const targetPath = path.join(destDir, flattenedName);
await fs.writeFile(targetPath, artifact.content);
written++;
}
// Get the dash-format name (e.g., bmad-bmm-create-prd.md) and remove .md
const flatName = toDashPath(artifact.relativePath);
const skillName = flatName.replace(/\.md$/, '');
// Create skill directory
const skillDir = path.join(destDir, skillName);
await fs.ensureDir(skillDir);
// Transform content: rewrite frontmatter for skills format
const skillContent = this.transformToSkillFormat(artifact.content, skillName);
// Write SKILL.md with platform-native line endings
const platformContent = skillContent.replaceAll('\n', os.EOL);
await fs.writeFile(path.join(skillDir, 'SKILL.md'), platformContent, 'utf8');
writtenCount++;
return written;
}
return writtenCount;
}
/**
* Transform artifact content from Codex prompt format to Agent Skills format.
* Removes disable-model-invocation, ensures name matches directory.
* @param {string} content - Original content with YAML frontmatter
* @param {string} skillName - Skill name (must match directory name)
* @returns {string} Transformed content
*/
transformToSkillFormat(content, skillName) {
// Normalize line endings so body matches rebuilt frontmatter (both LF)
content = content.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
// Parse frontmatter
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
if (!fmMatch) {
// No frontmatter -- wrap with minimal frontmatter
const fm = yaml.stringify({ name: skillName, description: skillName }).trimEnd();
return `---\n${fm}\n---\n\n${content}`;
}
const frontmatter = fmMatch[1];
const body = fmMatch[2];
// Parse frontmatter with yaml library to handle all quoting variants
let description;
try {
const parsed = yaml.parse(frontmatter);
description = parsed?.description || `${skillName} skill`;
} catch {
description = `${skillName} skill`;
}
// Build new frontmatter with only skills-spec fields, let yaml handle quoting
const newFrontmatter = yaml.stringify({ name: skillName, description }, { lineWidth: 0 }).trimEnd();
return `---\n${newFrontmatter}\n---\n${body}`;
}
/**
* Remove existing BMAD skill directories from the skills directory.
*/
async clearOldBmadSkills(destDir, options = {}) {
if (!(await fs.pathExists(destDir))) {
return;
}
let entries;
try {
entries = await fs.readdir(destDir);
} catch (error) {
if (!options.silent) await prompts.log.warn(`Warning: Could not read directory ${destDir}: ${error.message}`);
return;
}
if (!entries || !Array.isArray(entries)) {
return;
}
for (const entry of entries) {
if (!entry || typeof entry !== 'string') {
continue;
}
if (!entry.startsWith('bmad')) {
continue;
}
const entryPath = path.join(destDir, entry);
try {
await fs.remove(entryPath);
} catch (error) {
if (!options.silent) {
await prompts.log.message(` Skipping ${entry}: ${error.message}`);
}
}
}
}
/**
* Clean old BMAD files from legacy .codex/prompts directories.
*/
async clearOldBmadFiles(destDir, options = {}) {
if (!(await fs.pathExists(destDir))) {
return;
@ -353,11 +299,30 @@ class CodexSetup extends BaseIdeSetup {
}
async readAndProcessWithProject(filePath, metadata, projectDir) {
const rawContent = await fs.readFile(filePath, 'utf8');
const content = rawContent.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
const content = await fs.readFile(filePath, 'utf8');
return super.processContent(content, metadata, projectDir);
}
/**
* Get instructions for global installation
* @returns {string} Instructions text
*/
getGlobalInstructions(destDir) {
const lines = [
'IMPORTANT: Codex Configuration',
'',
'/prompts installed globally to your HOME DIRECTORY.',
'',
'These prompts reference a specific _bmad path.',
"To use with other projects, you'd need to copy the _bmad dir.",
'',
'You can now use /commands in Codex CLI',
' Example: /bmad_bmm_pm',
' Type / to see all available commands',
];
return lines.join('\n');
}
/**
* Get instructions for project-specific installation
* @param {string} projectDir - Optional project directory
@ -365,74 +330,95 @@ class CodexSetup extends BaseIdeSetup {
* @returns {string} Instructions text
*/
getProjectSpecificInstructions(projectDir = null, destDir = null) {
const lines = [
const isWindows = os.platform() === 'win32';
const commonLines = [
'Project-Specific Codex Configuration',
'',
`Skills installed to: ${destDir || '<project>/.agents/skills'}`,
`Prompts will be installed to: ${destDir || '<project>/.codex/prompts'}`,
'',
'REQUIRED: You must set CODEX_HOME to use these prompts',
'',
'Codex automatically discovers skills in .agents/skills/ at and above the current directory and in your home directory.',
'No additional configuration is needed.',
];
const windowsLines = [
'Create a codex.cmd file in your project root:',
'',
' @echo off',
' set CODEX_HOME=%~dp0.codex',
' codex %*',
'',
String.raw`Then run: .\codex instead of codex`,
'(The %~dp0 gets the directory of the .cmd file)',
];
const unixLines = [
'Add this alias to your ~/.bashrc or ~/.zshrc:',
'',
' alias codex=\'CODEX_HOME="$PWD/.codex" codex\'',
'',
'After adding, run: source ~/.bashrc (or source ~/.zshrc)',
'(The $PWD uses your current working directory)',
];
const closingLines = ['', 'This tells Codex CLI to use prompts from this project instead of ~/.codex'];
const lines = [...commonLines, ...(isWindows ? windowsLines : unixLines), ...closingLines];
return lines.join('\n');
}
/**
* Cleanup Codex configuration - cleans both new .agents/skills and old .codex/prompts
* Cleanup Codex configuration
*/
async cleanup(projectDir = null) {
// Clean old .codex/prompts locations
const oldGlobalDir = this.getOldCodexPromptDir(null, 'global');
await this.clearOldBmadFiles(oldGlobalDir);
// Clean both global and project-specific locations
const globalDir = this.getCodexPromptDir(null, 'global');
await this.clearOldBmadFiles(globalDir);
if (projectDir) {
const oldProjectDir = this.getOldCodexPromptDir(projectDir, 'project');
await this.clearOldBmadFiles(oldProjectDir);
// Clean new .agents/skills location
const destDir = this.getCodexSkillsDir(projectDir);
await this.clearOldBmadSkills(destDir);
const projectSpecificDir = this.getCodexPromptDir(projectDir, 'project');
await this.clearOldBmadFiles(projectSpecificDir);
}
}
/**
* Install a custom agent launcher for Codex as an Agent Skill
* @param {string} projectDir - Project directory
* Install a custom agent launcher for Codex
* @param {string} projectDir - Project directory (not used, Codex installs to home)
* @param {string} agentName - Agent name (e.g., "fred-commit-poet")
* @param {string} agentPath - Path to compiled agent (relative to project root)
* @param {Object} metadata - Agent metadata
* @returns {Object|null} Info about created skill
* @returns {Object|null} Info about created command
*/
async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
const destDir = this.getCodexSkillsDir(projectDir);
const destDir = this.getCodexPromptDir(projectDir, 'project');
await fs.ensureDir(destDir);
// Skill name from the dash name (without .md)
const skillName = customAgentDashName(agentName).replace(/\.md$/, '');
const skillDir = path.join(destDir, skillName);
await fs.ensureDir(skillDir);
const launcherContent = `---
name: '${agentName}'
description: '${agentName} agent'
disable-model-invocation: true
---
const description = metadata?.description || `${agentName} agent`;
const fm = yaml.stringify({ name: skillName, description }).trimEnd();
const skillContent =
`---\n${fm}\n---\n` +
"\nYou must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.\n" +
'\n<agent-activation CRITICAL="TRUE">\n' +
`1. LOAD the FULL agent file from @${agentPath}\n` +
'2. READ its entire contents - this contains the complete agent persona, menu, and instructions\n' +
'3. FOLLOW every step in the <activation> section precisely\n' +
'4. DISPLAY the welcome/greeting as instructed\n' +
'5. PRESENT the numbered menu\n' +
'6. WAIT for user input before proceeding\n' +
'</agent-activation>\n';
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
// Write with platform-native line endings
const platformContent = skillContent.replaceAll('\n', os.EOL);
const skillPath = path.join(skillDir, 'SKILL.md');
await fs.writeFile(skillPath, platformContent, 'utf8');
<agent-activation CRITICAL="TRUE">
1. LOAD the FULL agent file from @${agentPath}
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
3. FOLLOW every step in the <activation> section precisely
4. DISPLAY the welcome/greeting as instructed
5. PRESENT the numbered menu
6. WAIT for user input before proceeding
</agent-activation>
`;
// Use underscore format: bmad_custom_fred-commit-poet.md
const fileName = customAgentDashName(agentName);
const launcherPath = path.join(destDir, fileName);
await fs.writeFile(launcherPath, launcherContent, 'utf8');
return {
path: path.relative(projectDir, skillPath),
command: `$${skillName}`,
path: path.relative(projectDir, launcherPath),
command: `/${fileName.replace('.md', '')}`,
};
}
}

View File

@ -57,15 +57,6 @@ platforms:
description: "OpenAI Codex integration"
# No installer config - uses custom codex.js
codebuddy:
name: "CodeBuddy"
preferred: false
category: ide
description: "Tencent Cloud Code Assistant - AI-powered coding companion"
installer:
target_dir: .codebuddy/commands
template_type: default
crush:
name: "Crush"
preferred: false

View File

@ -0,0 +1,55 @@
# Raven's Verdict - Deep PR Review Tool
Adversarial code review for GitHub PRs. Works with any LLM agent.
> **Status: Experimental.** We're still figuring out how to use this effectively. Expect the workflow to evolve.
## How It Works
Point your agent at `review-pr.md` and ask it to review a specific PR:
> "Read tools/maintainer/review-pr.md and apply it to PR #123"
The tool will:
1. Check out the PR branch locally
2. Run an adversarial review (find at least 5 issues)
3. Transform findings into professional tone
4. Preview the review and ask before posting
See `review-pr.md` for full prompt structure, severity ratings, and sandboxing rules.
## When to Use
**Good candidates:**
- PRs with meaningful logic changes
- Refactors touching multiple files
- New features or architectural changes
**Skip it for:**
- Trivial PRs (typo fixes, version bumps, single-line changes)
- PRs you've already reviewed manually
- PRs where you haven't agreed on the approach yet — fix the direction before the implementation
## Workflow Tips
**Always review before posting.** The preview step exists for a reason:
- **[y] Yes** — Post as-is (only if you're confident)
- **[e] Edit** — Modify findings before posting
- **[s] Save only** — Write to file, don't post
The save option is useful when you want to:
- Hand-edit the review before posting
- Use the findings as input for a second opinion ("Hey Claude, here's what Raven found — what do you think?")
- Cherry-pick specific findings
**Trust but verify.** LLM reviews can miss context or flag non-issues. Skim the findings before they hit the PR.
## Prerequisites
- `gh` CLI installed and authenticated (`gh auth status`)
- Any LLM agent capable of running bash commands

View File

@ -2,7 +2,8 @@
A cynical adversarial review, transformed into cold engineering professionalism.
## CRITICAL: Sandboxed Execution Rules
<orientation>
CRITICAL: Sandboxed Execution Rules
Before proceeding, you MUST verify:
@ -13,6 +14,9 @@ Before proceeding, you MUST verify:
**If no explicit PR number/URL was provided, STOP immediately and ask:**
"What PR number or URL should I review?"
</orientation>
<preflight-checks>
## Preflight Checks
@ -93,7 +97,9 @@ gh pr diff {PR_NUMBER} [--repo {REPO}] --name-only | grep -E '\.(png|jpg|jpeg|gi
Store list of binary files to skip. Note them in final output.
## Adversarial Review
</preflight-checks>
<adversarial-review>
### 1.1 Run Cynical Review
@ -124,7 +130,9 @@ Likely tag:
- Add `[likely]` to findings with high confidence, e.g. with direct evidence
- Sort findings by severity (Critical → Moderate → Minor), not by confidence
## Tone Transformation
</adversarial-review>
<tone-transformation>
**Transform the cynical output into cold engineering professionalism.**
@ -169,8 +177,9 @@ Output format after transformation:
_Review generated by Raven's Verdict. LLM-produced analysis - findings may be incorrect or lack context. Verify before acting._
```
## Post Review
</tone-transformation>
<post-review>
### 3.1 Preview
Display the complete transformed review to the user.
@ -222,10 +231,12 @@ Do NOT use heredocs or `echo` - Markdown code blocks will break shell parsing. U
Keep the temp file and inform user of location.
## Notes
</post-review>
<notes>
- The "cynical asshole" phase is internal only - never posted
- Tone transform MUST happen before any external output
- When in doubt, ask the user - never assume
- If you're unsure about severity, err toward higher severity
- If you're unsure about confidence, be honest and use Medium or Low
</notes>

View File

@ -37,12 +37,6 @@ platforms:
category: ide
description: "OpenCode terminal coding assistant"
codebuddy:
name: "CodeBuddy"
preferred: false
category: ide
description: "Tencent Cloud Code Assistant - AI-powered coding companion"
auggie:
name: "Auggie"
preferred: false