.cursor/skills/adding-ai-agent-rendering-system/SKILL.md
Implement a new Packmind AI agent rendering/deployer pipeline (single-file or multi-file) with type and registry wiring, frontend UI/docs updates, and thorough unit/integration tests to reliably support additional coding assistants and distribution formats when introducing a new agent integration or render mode.
npx skillsauth add PackmindHub/packmind adding-ai-agent-rendering-systemInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Add a new AI agent rendering system to Packmind, supporting both single-file (like AGENTS.md) and multi-file (like Cursor/Continue) patterns, including type definitions, deployer implementation, registry registration, frontend UI integration, documentation updates, and comprehensive tests following Packmind test standards.
When adding support for a new AI coding assistant (e.g., Continue, Cursor, Claude Code, GitHub Copilot, OpenCode)
When implementing a new rendering format for standards and recipes distribution
When extending Packmind to support additional AI agent integrations
When creating a new deployer that follows the ICodingAgentDeployer interface
Before proceeding, the following information must be known. If any of these are unclear or not provided, prompt the user to clarify before starting implementation.
What is the agent's identifier key and display name?
CodingAgent type, CodingAgents record, AGENT_FILE_PATHS, etc.). Examples: opencode, gitlab_duo, continue, agents_md.OpenCode, GitLab Duo, Continue, AGENTS.md.In which directories will Standards be rendered?
.agent/rules/ (one file per standard)AGENTS.md, .agent/guidelines.md (all standards aggregated into one file)In which directories will Commands be rendered?
.agent/commands/).packmind/commands/ as a fallback (same pattern used by GitLab Duo, Junie, and AGENTS.md agents). Users invoke them via @.packmind/commands/command-name.md.In which directories will Skills be rendered?
.agent/skills/CodingAgentArtefactPaths.If standards are rendered into a shared file like AGENTS.md: What should be the precedence rules?
AGENTS.md).RENDER_MODE_ORDER determines priority — agents later in the array supersede agents earlier when both are active.What frontmatter format does the agent require? (YAML, Markdown, plain text, none)
What file extensions should be used? (.md, .mdc, .txt, etc.)
What naming convention should be used for files? (e.g., packmind-standard-{slug}.md, standard-{slug}.mdc)
Does the agent require specific frontmatter properties? (name, globs, alwaysApply, description, etc.)
What is the relative path from agent files to .packmind/standards/ directory?
Convention: Throughout all recipe steps below,
NEW_AGENT/new_agent/NewAgentare placeholders for the identifier key (from prerequisite 1), and'New Agent'is a placeholder for the display name. Substitute both consistently in every step.
Add the new AI agent to the RenderMode enum in packages/types/src/deployments/RenderMode.ts. Add the enum value and include it in the RENDER_MODE_ORDER array to ensure proper ordering. Position matters for supersedence: agents earlier in the array are overridden by agents later in the array when they share a file.
export enum RenderMode {
// ... existing values
NEW_AGENT = 'NEW_AGENT',
}
export const RENDER_MODE_ORDER: RenderMode[] = [
// ... existing values
RenderMode.NEW_AGENT,
];
Add the new agent identifier to the CodingAgent union type in both packages/types/src/coding-agent/CodingAgent.ts and packages/coding-agent/src/domain/CodingAgents.ts. Also add it to the CodingAgents record object.
export type CodingAgent =
| 'packmind'
| 'junie'
| 'claude'
| 'cursor'
| 'copilot'
| 'agents_md'
| 'gitlab_duo'
| 'continue'
| 'new_agent';
export const CodingAgents: Record<CodingAgent, CodingAgent> = {
// ... existing values
new_agent: 'new_agent',
};
If the agent supports commands, standards, or skills as multi-file artifacts, add it to packages/types/src/coding-agent/CodingAgentArtefactPaths.ts:
MultiFileCodingAgent type unionCODING_AGENT_ARTEFACT_PATHS record for each supported artifact type (command, standard, skill). Use empty string for unsupported artifact types.export type MultiFileCodingAgent = Extract<CodingAgent, 'claude' | 'cursor' | ... | 'new_agent'>;
export const CODING_AGENT_ARTEFACT_PATHS: Record<MultiFileCodingAgent, { command: string; standard: string; skill: string }> = {
// ... existing values
new_agent: {
command: '.new-agent/commands/',
standard: '', // empty if standards are single-file (embedded in a shared file)
skill: '.new-agent/skills/',
},
};
Add the agent identifier to the VALID_CODING_AGENTS array in packages/types/src/coding-agent/validation.ts. This enables validation of the agent string in configuration files.
export const VALID_CODING_AGENTS: CodingAgent[] = [
// ... existing values
'new_agent',
];
Update the corresponding test in validation.spec.ts to include the new agent in test fixtures.
Add the mapping from RenderMode to CodingAgent in packages/types/src/deployments/RenderModeCodingAgentMapping.ts in the RENDER_MODE_TO_CODING_AGENT record.
export const RENDER_MODE_TO_CODING_AGENT: Record<RenderMode, CodingAgent> = {
// ... existing mappings
[RenderMode.NEW_AGENT]: CodingAgents.new_agent,
};
Create a new deployer class in packages/coding-agent/src/infra/repositories/{agentName}/{AgentName}Deployer.ts. Choose a base class based on the agent's rendering pattern:
For hybrid agents (single-file standards + multi-file commands/skills), extend SingleFileDeployer and override the artifact methods:
import { SingleFileDeployer } from '../singleFile/SingleFileDeployer';
export class NewAgentDeployer extends SingleFileDeployer {
// Implement required methods:
// - deployRecipes() - deploy standards/recipes content
// - deploySkills() - deploy skill files to agent directories
// - deployArtifacts() - deploy command files to agent directories
// - generateRemovalFileUpdates() - handle artifact removal
// - generateAgentCleanupFileUpdates() - handle full agent cleanup
}
In the deployer, implement frontmatter generation based on the agent's requirements. For Continue-style agents, include name, globs (if scope exists), alwaysApply (false if scope, true otherwise), and description (from summary or standard name). For Cursor-style agents, use simpler frontmatter with just globs and alwaysApply. For single-file agents, frontmatter may not be needed.
// For Continue-style (with name and description)
const frontmatter = standardVersion.scope && standardVersion.scope.trim() !== ''
? `---
name: ${standardVersion.name}
globs: ${standardVersion.scope}
alwaysApply: false
description: ${summary}
---`
: `---
name: ${standardVersion.name}
alwaysApply: true
description: ${summary}
---`;
// For Cursor-style (simpler)
const frontmatter = standardVersion.scope && standardVersion.scope.trim() !== ''
? `---
globs: ${standardVersion.scope}
alwaysApply: false
---`
: `---
alwaysApply: true
---`;
Register the new deployer in packages/coding-agent/src/infra/repositories/CodingAgentDeployerRegistry.ts by importing it and adding a case in the createDeployer switch statement. Also add the agent to the canCreateDeployer method.
If the agent supports multi-file artifacts (commands/skills), also add it to the isMultiFileAgent() check if that method exists.
import { NewAgentDeployer } from './newAgent/NewAgentDeployer';
private createDeployer(agent: CodingAgent): ICodingAgentDeployer {
switch (agent) {
// ... existing cases
case 'new_agent':
return new NewAgentDeployer(this.standardsPort, this.gitPort);
default:
throw new Error(`Unknown coding agent: ${agent}`);
}
}
private canCreateDeployer(agent: CodingAgent): boolean {
return (
// ... existing agents
agent === 'new_agent'
);
}
Add the new agent to the AGENT_FILE_PATHS record in packages/coding-agent/src/domain/AgentConfiguration.ts. This maps the agent to its main config/standards file path.
export const AGENT_FILE_PATHS: Record<CodingAgent, string> = {
// ... existing mappings
new_agent: 'AGENTS.md', // or '.new-agent/rules/index.md', etc.
};
Note: If the agent shares a file path with another agent (e.g., both opencode and agents_md map to AGENTS.md), this is valid but requires supersedence handling in Step 11.
Add the deployer export to packages/coding-agent/src/index.ts so it can be imported by other packages.
export * from './infra/repositories/newAgent/NewAgentDeployer';
Skip this step if the agent does not share a config file with another agent.
If two agents write to the same file (e.g., both OpenCode and agents_md write to AGENTS.md), add suppression logic in packages/coding-agent/src/application/DeployerService.ts to ensure only the higher-priority agent writes to the shared file when both are active.
This typically involves:
aggregateStandardsDeployments() and aggregateArtifactRendering()DeployerService.spec.tsAdd the new agent to the agentToFile record in packages/deployments/src/application/utils/GitFileUtils.ts. This maps the agent to its main file for git operations. If the file path is shared with another agent, the deduplication in fetchExistingFilesFromGit() handles avoiding duplicate fetches.
const agentToFile: Record<CodingAgent, string> = {
// ... existing mappings
new_agent: 'AGENTS.md', // or the agent's main file
};
Ensure the relative path from agent files to .packmind/standards/{slug}.md is correct. For files in .continue/rules/ or .cursor/rules/packmind/, use ../../.packmind/standards/. For files at root level like CLAUDE.md, use .packmind/standards/. Adjust based on the actual directory structure.
// For .continue/rules/ or .cursor/rules/packmind/
link: `../../.packmind/standards/${standardVersion.slug}.md`
// For root-level files
link: `.packmind/standards/${standardVersion.slug}.md`
Add the agent's directory or file to the detection list in apps/cli/src/application/services/AgentArtifactDetectionService.ts. This allows the CLI to detect whether the agent is already set up in a repository.
const AGENT_ARTIFACT_CHECKS = [
// ... existing entries
{ agent: 'new_agent', paths: ['.new-agent'] },
];
Add a corresponding test in AgentArtifactDetectionService.spec.ts.
Add the agent to the CLI's agent configuration in apps/cli/src/infra/commands/config/configAgentsHandler.ts:
SELECTABLE_AGENTS array (alphabetically sorted, Packmind always first/excluded)AGENT_DISPLAY_NAMES record with a human-readable nameexport const SELECTABLE_AGENTS: CodingAgent[] = [
'agents_md', 'claude', 'continue', 'copilot', 'cursor', 'gitlab_duo', 'junie', 'new_agent',
];
export const AGENT_DISPLAY_NAMES: Record<CodingAgent, string> = {
// ... existing entries
new_agent: 'New Agent',
};
Add tests in configAgentsHandler.spec.ts confirming the agent is in SELECTABLE_AGENTS and has the correct display name.
Add a parser entry for the agent in apps/cli/src/application/utils/parseStandardMd.ts:
AGENT_PARSERS record. For single-file agents that embed standards in a shared file (e.g., AGENTS.md), use () => null since individual standards can't be parsed from the file.DEPLOYER_PARSERS.// In AGENT_PARSERS
export const AGENT_PARSERS: Partial<Record<CodingAgent, (content: string) => ParsedStandard | null>> = {
// ... existing entries
new_agent: () => null, // single-file agent, cannot parse individually
};
// In DEPLOYER_PARSERS (only for multi-file standard agents)
export const DEPLOYER_PARSERS = [
// ... existing entries
{ pattern: '.new-agent/rules/packmind-', parse: parseNewAgentStandard },
];
Add the new agent to apps/frontend/src/domain/deployments/components/RenderingSettings/RenderingSettings.tsx by adding entries to RENDER_MODE_TO_VALUE, VALUE_TO_RENDER_MODE, and DEFAULT_FORMATS arrays.
const RENDER_MODE_TO_VALUE: Record<RenderMode, string> = {
// ... existing values
[RenderMode.NEW_AGENT]: 'new-agent',
};
const VALUE_TO_RENDER_MODE: Record<string, RenderMode> = {
// ... existing values
'new-agent': RenderMode.NEW_AGENT,
};
const DEFAULT_FORMATS: RenderingItem[] = [
// ... existing formats
{ value: 'new-agent', name: 'New Agent', checked: false },
];
Add the new agent label to apps/frontend/src/domain/deployments/components/RunDistribution/RunDistributionBody.tsx in the renderModeLabels record.
const labels: Record<RenderMode, string> = {
// ... existing labels
[RenderMode.NEW_AGENT]: 'New Agent',
};
Add the new agent label to apps/frontend/src/domain/deployments/components/DeploymentsHistory/DeploymentsHistory.tsx in the formatNames record.
const formatNames: Record<RenderMode, string> = {
// ... existing labels
[RenderMode.NEW_AGENT]: 'New Agent',
};
Add the new agent to the documentation:
apps/doc/docs/manage-ai-agents.mdx - Add a row to the agent support table showing file locations and supported featuresapps/doc/docs/artifact-rendering.mdx - Add the agent to the standards, commands, and/or skills tables as applicable| **New Agent** | AGENTS.md + `.new-agent/` directories | Yes |
Create comprehensive unit tests in packages/coding-agent/src/infra/repositories/{agentName}/{AgentName}Deployer.spec.ts. Follow Packmind test standards: single expectation per test, assertive titles (no "should"), and nested describe blocks for workflows. Test:
describe('NewAgentDeployer', () => {
describe('deployRecipes', () => {
describe('when deploying recipes', () => {
it('creates one file update', async () => {
// Single expectation test
});
});
});
});
Create integration tests in packages/integration-tests/src/coding-agents-deployments/{agent-name}-deployment.spec.ts following the pattern of existing integration tests (e.g., cursor-deployment.spec.ts). Test the full deployment workflow through DeployerService, including file creation, frontmatter validation, and content verification. If the agent shares a file with another agent, test the dual-active supersedence scenario. Follow test standards with single expectations and nested describe blocks.
describe('New Agent Deployment Integration', () => {
describe('when deploying standards', () => {
it('creates the expected file', async () => {
// Test through deployerService
});
});
});
tools
Record polished UI demo videos and screenshots of a running web app using Playwright MCP — for client deliverables, release notes, feature walkthroughs, or bug repros. Produces an HD WebM video with chapter markers, a mandatory animated cursor overlay, and a mandatory subtitle bar that narrates each step (positioned deliberately so it never masks the UI being demonstrated), plus full-page screenshots at each step. Use this whenever the user asks to "record a demo", "create a screencast", "make a UI walkthrough video", "document this feature with video", "show the client how X works", "capture screenshots of the app", or anything similar — even when the user only says "make a video" or "take screenshots" in the context of a running frontend. Also use it when the user wants to demonstrate a workflow, generate marketing-quality footage of an app, or produce repeatable visual documentation.
tools
The canonical recipe for starting, checking, and stopping the Packmind local dev stack with Docker Compose — the single source of truth other skills and the Michel agent defer to. Covers bringing the full stack (PostgreSQL, Redis, NestJS API, React/Vite frontend on :4200, MCP server, nginx) up in the background, the init services (dependency install + TypeORM migrations) you must wait on, the critical host-port trap that the API on container port 3000 is NOT exposed to the host and must be reached via the frontend Vite proxy at localhost:4200/api/v0, confirming the API and frontend are actually serving before you depend on them, the persistent-volume gotcha that leaves stale Postgres schema and node_modules behind between runs, building the CLI, and tearing everything down so no container is left blocking the run. Use this whenever you need Packmind running locally — to verify a change, record a UI or CLI demo, hit the API, seed data, or reproduce a bug — and whenever you are about to start or stop `docker compose`. If you are an autonomous agent (e.g. Michel) that started the stack, you MUST use the teardown half before finishing. Prefer this over running `nx serve` on the host for anything that needs the real, containerized stack.
tools
Best practices for creating GitHub pull requests that include inline images — CLI terminal screenshots (from cli-demo-recorder), UI screenshots/videos (from ui-demo-recorder), or any other visual artifact. Use this skill whenever opening or updating a PR that has visual artifacts to embed, or when images aren't rendering in a PR description. Also use it when asked "how do I add screenshots to a PR", "why isn't my image showing", or "embed a demo in the PR".
tools
--- name: michel-create-packmind-dataset description: Seed a local Packmind instance with a realistic dataset — one organization populated with standards, commands, and skills — so an autonomous agent can exercise its own changes against lifelike data instead of an empty app. Use this whenever you need populated Packmind data to verify a change end-to-end: reproducing a bug that only shows with existing artifacts, recording a UI/CLI demo that needs content on screen, smoke-testing a new endpoint