Ai-setup writers-pattern
Adds a new platform writer in src/writers/ following existing patterns (claude, cursor, codex). Returns string[] of generated file paths. Integrates with writeSetup() orchestration. Use when implementing 'add platform', 'new writer', 'support new agent'. Do NOT use for refactoring existing writers or modifying writers/index.ts exports.
install
source · Clone the upstream repo
git clone https://github.com/caliber-ai-org/ai-setup
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/caliber-ai-org/ai-setup "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.agents/skills/writers-pattern" ~/.claude/skills/caliber-ai-org-ai-setup-writers-pattern && rm -rf "$T"
manifest:
.agents/skills/writers-pattern/SKILL.mdsource content
Writers Pattern
Critical
- Each writer MUST export a default function matching the signature:
(config: WriterConfig, skillLines: SkillLine[]) => Promise<string[]> - Writer MUST return full file paths written, not relative paths
- All writers MUST be exported in
as named exportssrc/writers/index.ts - Writer files live in
with siblingsrc/writers/{platform}/index.ts__tests__/index.test.ts - Configuration object (
) is shared across all writers — inspectWriterConfig
for the exact shapesrc/writers/claude/index.ts - Never hardcode file paths or extension detection — use the
object andconfig
array passed inskillLines
Instructions
-
Create directory structure
- Create
(main writer)src/writers/{platform}/index.ts - Create
(test file)src/writers/{platform}/__tests__/index.test.ts - Verify directory does not already exist:
should return errorls -la src/writers/{platform}/
- Create
-
Implement writer function signature
- Import
andWriterConfig
fromSkillLinesrc/writers/index.ts - Export default async function:
export default async function write{Platform}(config: WriterConfig, skillLines: SkillLine[]): Promise<string[]> - Function receives
with properties:config
,cwd
,platform
,agent
(optional),token
(boolean)quiet - Function receives
array of objects withskillLines
,name
,description
,path
propertiesmarkdown - Return array of absolute file paths written (e.g.,
)['/path/to/file1', '/path/to/file2']
- Import
-
Implement core write logic
- Determine target directory from
(entry point for all writes)config.cwd - For each skill in
, generate platform-specific file(s)skillLines - Match file structure of existing writer: inspect
lines 1–50 for pattern (typically generates SKILL.md or equivalent)src/writers/claude/index.ts - Use
or Caliber'sawait fs.promises.writeFile()
helper if availablewriteFile() - Catch and handle write errors — log to stderr if
is falseconfig.quiet - Use
andpath.resolve()
for all path operationspath.join()
- Determine target directory from
-
Add test file
- Create
with vitest importssrc/writers/{platform}/__tests__/index.test.ts - Test the writer function with mock
andWriterConfig
inputsSkillLine[] - Assert that returned
contains expected file pathsstring[] - Mock file I/O if needed using memfs or spy on
fs.promises.writeFile - Verify at least one skill is written per test case
- Create
-
Export writer in src/writers/index.ts
- Open
src/writers/index.ts - Add import:
import write{Platform} from './{platform}/index.js' - Export as named export in the module exports object (inspect existing claude, cursor, codex exports)
- Verify import uses
extension (ESM convention in this project).js
- Open
-
Verify integration
- Run
— must compile without errorsnpm run build - Run
— all tests passnpm run test -- src/writers/{platform}/__tests__/ - Run
— no linting errors in new writer codenpm run lint - Inspect
to confirm new writer is exported and callablesrc/writers/index.ts
- Run
Examples
User says: "Add support for a new agent platform called Jetbrains"
Actions:
- Create
src/writers/jetbrains/index.ts - Implement
— readsexport default async function writeJetbrains(config: WriterConfig, skillLines: SkillLine[]): Promise<string[]>
, iteratesconfig.cwd
, writes files toskillLines
(or platform-specific dir).jetbrains/rules/ - Create
with testssrc/writers/jetbrains/__tests__/index.test.ts - Add to
:src/writers/index.ts
and exportimport writeJetbrains from './jetbrains/index.js' - Run build + tests + lint — all pass
Result: New writer available via
writeSetup() orchestration; each skill generates a file in the platform-specific directory and returns full paths written.
Common Issues
- Type error: 'WriterConfig' not found — Ensure import is
(useimport type { WriterConfig, SkillLine } from '../index.js'
keyword for type imports)type - Function returns relative paths instead of absolute — Use
to construct full paths; all returned paths must be absolutepath.resolve(config.cwd, relativePath) - Writer not callable in index.ts exports — Verify default export function in
is async and returns{platform}/index.ts
, then checkPromise<string[]>
import usesindex.ts
extension.js - Tests fail with 'Cannot find module' — Confirm
imports writer as__tests__/index.test.ts
(relative path, ESM)import write{Platform} from '../index.js' - Build fails: 'platform' already exists — Check if
dir exists from prior attempt; remove or use different platform namesrc/writers/{platform}/