Skip to content

feat(pi): add Pi Coding Agent as a generation target#1553

Merged
dyoshikawa merged 3 commits intomainfrom
pi-agent
Apr 23, 2026
Merged

feat(pi): add Pi Coding Agent as a generation target#1553
dyoshikawa merged 3 commits intomainfrom
pi-agent

Conversation

@dyoshikawa
Copy link
Copy Markdown
Owner

Summary

Adds Pi Coding Agent (@mariozechner/pi-coding-agent) as a new generation target pi with native support for Rules, Commands, and Skills in both project and global scopes. MCP, Subagents, and Ignore features are intentionally not registered, matching Pi's upstream design that rejects those as framework features.

Closes #1552.

Feature × scope matrix

Feature Project Global
Rules AGENTS.md (root) + .agents/memories/*.md (TOON refs) ~/.pi/agent/AGENTS.md
Commands .pi/prompts/*.md ~/.pi/agent/prompts/*.md
Skills .pi/skills/<name>/SKILL.md ~/.pi/agent/skills/<name>/SKILL.md
MCP Not supported Not supported
Subagents Not supported Not supported
Ignore Not supported Not supported

Key changes

  • New PiRule (mirrors agentsmd-rule with ruleDiscoveryMode: "toon"), PiCommand, PiSkill (reuses the Agent Skills standard).
  • PiCommand round-trips argument-hint through a pi: namespace in rulesync frontmatter.
  • Processor wiring: registered in rules-processor.ts, commands-processor.ts, skills-processor.ts with supportsGlobal: true. Not registered in mcp-processor.ts, subagents-processor.ts, or ignore-processor.ts.
  • gitignore-entries.ts gains **/.agents/memories/, **/.pi/prompts/, **/.pi/skills/, and shares **/AGENTS.md with agentsmd.
  • Co-located unit tests for PiRule, PiCommand, PiSkill.
  • E2E happy-path rows added for pi × (rules, commands, skills) × (project generate, import, global, orphan-delete).
  • README.md, docs/reference/supported-tools.md, and the synced skills/rulesync/supported-tools.md list Pi.

Test plan

  • pnpm cicheck:code — formatter, oxlint, eslint, typecheck, 5204 unit tests pass
  • pnpm cicheck:content — skill-docs sync, cspell, secretlint pass
  • pnpm test:e2e — 346/346 pass (includes new pi rows)
  • Manual: rulesync generate --targets pi produces expected project layout
  • Manual: rulesync generate --targets pi --global produces expected ~/.pi/agent/ layout
  • Manual: rulesync import --targets pi round-trips back to .rulesync/

Copilot AI review requested due to automatic review settings April 23, 2026 10:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Pi Coding Agent as a new Rulesync generation/import target (pi), wiring it into the rules/commands/skills processors with global-mode support and updating docs/tests accordingly.

Changes:

  • Register new pi tool target across types and feature processors (rules/commands/skills), including global support and TOON rule discovery.
  • Implement Pi-specific generators/parsers: PiRule, PiCommand (round-trips argument-hint via pi: frontmatter namespace), and PiSkill (Agent Skills-style layout under .pi/).
  • Expand unit + E2E coverage and update documentation + gitignore registry for Pi outputs.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/types/tool-targets.ts Adds pi to the canonical tool target list.
src/types/tool-targets.test.ts Updates tool target snapshot/expectations to include pi.
src/features/skills/skills-processor.ts Registers PiSkill in the skills processor factory map.
src/features/skills/skills-processor.test.ts Updates skills processor target assertions to include pi.
src/features/skills/pi-skill.ts Introduces Pi skill directory implementation targeting .pi/skills (+ global).
src/features/skills/pi-skill.test.ts Adds unit tests for Pi skill pathing, parsing, and conversions.
src/features/rules/rules-processor.ts Registers PiRule with TOON discovery and Pi command/skill conventions.
src/features/rules/rules-processor.test.ts Updates rules processor target assertions and global target counts for pi.
src/features/rules/pi-rule.ts Introduces Pi rule implementation writing AGENTS.md + .agents/memories.
src/features/rules/pi-rule.test.ts Adds unit tests for Pi rule paths, loading, conversion, and global behavior.
src/features/commands/pi-command.ts Introduces Pi command implementation for .pi/prompts (+ global), with argument-hint round-trip.
src/features/commands/pi-command.test.ts Adds unit tests for Pi command parsing, conversion, and round-trip behavior.
src/features/commands/commands-processor.ts Registers PiCommand in the commands processor factory map.
src/features/commands/commands-processor.test.ts Updates commands processor target assertions to include pi.
src/e2e/e2e-skills.spec.ts Adds E2E rows for Pi skills generate/import/global/orphan-delete.
src/e2e/e2e-rules.spec.ts Adds E2E rows for Pi rules generate/import/global.
src/e2e/e2e-commands.spec.ts Adds E2E rows for Pi commands generate/import/global/orphan-delete.
src/cli/commands/gitignore-entries.ts Adds Pi-specific gitignore entries and shares AGENTS.md ignore with agentsmd.
skills/rulesync/supported-tools.md Documents Pi support in the synced supported-tools table.
docs/reference/supported-tools.md Documents Pi support in the reference supported-tools table.
README.md Documents Pi support in the main supported-tools table.

),
};
}

Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pi skills (Agent Skills standard) typically require the skill directory name to match the frontmatter name. PiSkill.validate() currently only checks schema shape, so it will treat mismatched dirName/frontmatter.name as valid and may generate a layout Pi rejects. Consider adding a validation step that compares parsed name to this.getDirName() (similar to ClineSkill.validate() / RooSkill.validate()).

Suggested change
const dirName = this.getDirName();
if (result.data.name !== dirName) {
return {
success: false,
error: new Error(
`Invalid frontmatter in ${this.getDirPath()}: frontmatter name "${result.data.name}" must match directory name "${dirName}"`,
),
};
}

Copilot uses AI. Check for mistakes.
Comment on lines +143 to +166
static fromRulesyncSkill({
baseDir = process.cwd(),
rulesyncSkill,
validate = true,
global = false,
}: ToolSkillFromRulesyncSkillParams): PiSkill {
const settablePaths = PiSkill.getSettablePaths({ global });
const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();

const piFrontmatter: PiSkillFrontmatter = {
name: rulesyncFrontmatter.name,
description: rulesyncFrontmatter.description,
};

return new PiSkill({
baseDir,
relativeDirPath: settablePaths.relativeDirPath,
dirName: rulesyncSkill.getDirName(),
frontmatter: piFrontmatter,
body: rulesyncSkill.getBody(),
otherFiles: rulesyncSkill.getOtherFiles(),
validate,
global,
});
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PiSkill.fromRulesyncSkill() uses dirName: rulesyncSkill.getDirName() while setting frontmatter.name from the rulesync frontmatter. If those differ, this will emit an on-disk skill directory whose name doesn’t match the skill name, which is invalid for several skill targets and (per Pi’s skill format) can break discovery. Consider using the (validated) frontmatter name as dirName (and/or failing fast when they differ).

Copilot uses AI. Check for mistakes.
…: command namespace

Address mid-severity review findings on PR #1553:
- Remove additionalConventions for pi in rules-processor (dead config; pi is not simulated so the block never renders, matching opencode).
- Document the pi: command frontmatter namespace (argument-hint) in docs/reference/file-formats.md and sync to skills/rulesync/.
Copilot AI review requested due to automatic review settings April 23, 2026 13:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment on lines +72 to +78
const paths = this.getSettablePaths({ global });
const isRoot = relativeFilePath === paths.root.relativeFilePath;

if (isRoot) {
const fileContent = await readFileContent(
join(baseDir, paths.root.relativeDirPath, paths.root.relativeFilePath),
);
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PiRule.fromFile determines isRoot solely by relativeFilePath === "AGENTS.md". When importing non-root rules, RulesProcessor passes relativeFilePath relative to the .agents/memories directory; a memory file named AGENTS.md would be misclassified as root and the wrong file would be read (project-root AGENTS.md instead of the memory file). Consider incorporating relativeDirPath into the root check (e.g., require it to match paths.root.relativeDirPath) or otherwise disambiguate root vs non-root based on both dir and filename.

Copilot uses AI. Check for mistakes.
Comment on lines +149 to +159
const paths = this.getSettablePaths({ global });
const isRoot = relativeFilePath === paths.root.relativeFilePath;

return new PiRule({
baseDir,
relativeDirPath,
relativeFilePath,
fileContent: "",
validate: false,
root: isRoot,
});
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PiRule.forDeletion sets root based only on relativeFilePath === "AGENTS.md". If a non-root memory file under .agents/memories/ happens to be named AGENTS.md, it will be treated as a root rule, which can lead to incorrect behavior when the rule is later converted/handled as a root. Align this with the AgentsMdRule pattern by considering both relativeDirPath and relativeFilePath when deciding isRoot (and account for global vs project roots).

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +118
const fileContent = stringifyFrontmatter(this.body, rulesyncFrontmatter);

return new RulesyncCommand({
baseDir: ".",
frontmatter: rulesyncFrontmatter,
body: this.body,
relativeDirPath: RulesyncCommand.getSettablePaths().relativeDirPath,
relativeFilePath: this.relativeFilePath,
fileContent,
validate: true,
});
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PiCommand.toRulesyncCommand hardcodes baseDir: ".". During import, the CommandsProcessor can be constructed with a baseDir that is not the current working directory (e.g., when importing for a configured baseDir), and FeatureProcessor.writeAiFiles uses the RulesyncCommand baseDir to compute output paths. Using "." here can write imported rulesync files to the wrong location. Prefer using this.baseDir (or process.cwd() consistently) so the produced RulesyncCommand writes under the same baseDir it was loaded from.

Copilot uses AI. Check for mistakes.
@dyoshikawa dyoshikawa merged commit bc869e1 into main Apr 23, 2026
13 checks passed
@dyoshikawa dyoshikawa deleted the pi-agent branch April 23, 2026 14:31
@github-actions github-actions Bot mentioned this pull request Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Pi Coding Agent as a generation target (rules, commands, skills)

2 participants