<pectus.ai/>
./pectus.ai — builder framework · self-hosted · MIT

For skill authors

Skill specification

How to author a Pectus skill. This is the contract — the runner and the CMS depend on it.

Folder layout

skills/<skill-name>/
├── SKILL.md          required — manifest + prompt
├── schema.ts         required — Zod schema for structured output
└── reference/        optional — knowledge files the skill loads
    ├── *.md
    └── *.json

The folder name is the skill name. Use kebab-case.

SKILL.md frontmatter

---
name: my-skill                      # required, must match folder name
description: One line shown in UI   # required
version: 1.0.0                      # required, semver
inputs:                             # required, named inputs gathered by the runner
  - project_id
  - some_other_input
outputs:                            # required, named outputs returned to the caller
  - some_named_output
schema: ./schema.ts                 # required, path to Zod schema
model: claude-opus-4-7              # optional, default claude-opus-4-7
cache_inputs:                       # optional, inputs to mark with cache_control
  - brand
  - icp_profile
---

Body

The body of SKILL.md is the system prompt Claude receives. Plain markdown. Reference files in the reference/ subfolder are inlined by the runner when the body contains {{ reference/<file> }} directives.

Keep the body under 4000 tokens. Long reference material goes in reference/ so prompt caching can absorb it.

Inputs

Named inputs the runner knows how to gather:

InputSource
project_idAlways required. The project (market) the skill runs against.
brand_idResolved from the project. Skills that need brand-level data declare this.
week_startISO date. Defaults to current week’s Monday.
top_keywordsTop 200 keywords by search volume from keywords for the project.
recent_articlesLast 500 articles from articles for the project.
icp_profileThe icp_profiles row for the project.
brandThe brands row for the project’s brand (voice, tonality, colors, fonts).
knowledge_insightsContents of brands/<slug>/knowledge/insights.md if present.
answer_public_entriesUp to 2000 rows from answer_public_entries.
last_runMost recent skill_runs row for this skill + project.
sitemapAll content_source_pages rows for the project’s primary content source.
article_bodiesBlock content from articles.

Skills declare which they need. The runner fetches only those.

Outputs

The Zod schema in schema.ts defines exactly what the skill returns. Outputs land in:

  • skill_runs.output (always — every run logs the full output here)
  • Skill-specific destinations: weekly_analyses for weekly-analysis, file writes for internal-linking and knowledge-digest

Skills don’t write to arbitrary tables. If a skill needs to land data somewhere structural, that’s a CMS concern — the runner exposes hooks the CMS uses.

Caching

Mark large, slow-changing inputs with cache_inputs: in frontmatter. The runner adds cache_control: { type: "ephemeral" } to those input blocks. Cache TTL is 5 minutes — back-to-back skill runs in a session reuse the cache.

Don’t cache inputs that change every run (keywords, articles). The cache miss costs more than no cache at all in those cases.

Versioning

Bump version in frontmatter when you change the schema or the prompt in a way that produces materially different output. The runner records the version on every skill_runs row so changes are auditable.

Breaking changes (schema field removed, semantics changed) require a major bump. Additions are minor. Prompt tweaks that don’t change schema are patch.

Authoring locally vs upstream

Skills you write yourself live in skills/ alongside the upstream-shipped ones. pectus update is a git rebase, so your locally-added skill files are preserved untouched. If you edit an upstream skill, the rebase surfaces a conflict; resolve by keeping your changes if they’re brand-specific, or by sending a PR upstream if they’re general.

The fastest path to a new skill is the make-it skill:

npx pectus make-it skill

The CLI prompts you for the brief (what does it do, what core blocks does it consume, what inputs does it need, what does it produce), calls make-it, and writes a complete scaffold. Then:

  1. Test in your fork via npm install and npx pectus analyze --project <code> --skill <your-skill> against your dev Supabase.
  2. Open a PR to pectusai/pectus for an official skill, or push to your own GitHub repo for community distribution.

Community contributions are tracked at pectus.dev.

Authoring an app instead

If what you want to add is a publisher, a data source, or anything that talks to an external service, you want an app, not a skill. See apps-spec. The decision rule: if the unit of work is a verb the model performs (“write”, “analyze”, “cluster”), it’s a skill. If it’s a surface (“WordPress”, “GA4”, “content-insights”), it’s an app.