Skip to main content

Card Manifest

On disk: card.json at the root of an explicit user-owned Card source repository (for example <card-collection>/<name>/card.json) or a published/consumed Card tree. Editable sources do not live in the machine Store.

Purpose: the manifest a card carries. Declares the card's identity, versioned skill and MCP contributions, target defaults, extension intent, and authoring-quality metadata.

Type​

CardManifest (cli/core/card-manifest.ts:7-22).

Example​

{
"$schema": "https://drwn.dev/schemas/card-manifest-v1.json",
"name": "@your-handle/backend",
"version": "1.2.0",
"description": "Backend reviewer + release-notes harness for the api team.",
"license": "MIT",
"harness": { "minVersion": "0.1.0" },
"bundles": {
"@drwn/reviewer": "^2.0.0"
},
"skills": {
"include": ["reviewer", "release-notes"]
},
"servers": {
"context7": { "enabled": true }
},
"extensions": {
"parallel": { "enabled": true, "skills": true }
},
"targets": {
"claude": { "enabled": true },
"codex": { "enabled": true }
},
"stability": "stable",
"lastValidatedWith": "0.1.0",
"testStatusBadge": "https://github.com/me/backend/actions/workflows/test.yml/badge.svg"
}

Fields​

All validation lives in validateCardManifest (cli/core/card-manifest.ts:50-109); the asserting form is assertValidCardManifest (card-manifest.ts:111-116).

FieldTypeRequiredMeaningEnforced at
$schemastringnoOptional JSON-schema URL hint for editors. Not validated by drwn.cli/core/card-manifest.ts:8
namestringyes@scope/name or unscoped name. Matches @[a-z0-9-]+/[a-z0-9-]+ or [a-z0-9-]+.card-manifest.ts:56-60 (isCardScopeName, isCardUnscopedName)
versionstringyesStrict semver. Pre-release and build metadata follow isStrictSemver.card-manifest.ts:61-65
descriptionstringnoFree-form short description.card-manifest.ts:11
licensestringnoSPDX-style identifier. Free-form; not validated.card-manifest.ts:12
harness.minVersionstringnoStrict semver. Minimum drwn version this card needs at consume time.card-manifest.ts:66-68
bundlesRecord<string, string>noMap of bundle package name to semver range. Each range must pass validRange.card-manifest.ts:98-102
skills.includestring[]noSkill directories shipped in this card to include. Must be an array.card-manifest.ts:88-90
skills.exclude—forbiddenRejected: cards do not exclude — they include.card-manifest.ts:85-87
skills.sharedstring[]reservedMust be omitted or empty. Reserved for Wave 2 registry references.card-manifest.ts:91-97
serversRecord<string, ServerOverride>noSame ServerOverride shape as project config: toggle or full RegistryServer.Type: cli/core/types.ts:82-84
extensionsRecord<string, ProjectExtensionConfig>noPer-extension intent the card wants to project into consumers.Type: cli/core/types.ts:86-93
targetsPartial<Record<TargetName, { enabled: boolean }>>noPer-target enablement default the card prefers. Only claude, codex, cursor accepted.card-manifest.ts:103-107
hooks.includestring[]noHook policy names shipped in this card. Each name refers to a hooks/<name>/policy.ts relative to the card source root. Activated when the consumer runs drwn card trust <name> --hooks.card-manifest.ts:38
instructions{ text: string } or { path: string }noExplicit Worker guidance. Exactly one inline or Card-relative source; projection requires drwn card trust <name> --instructions.card-manifest.ts
persona{ include?: string[]; visibility?: "private" | "internal" | "public" }noPersona content declaration. Each entry in include refers to a persona/<entry>/PERSONA.md.card-manifest.ts:20,39
beliefs{ include?: string[]; visibility?: "private" | "internal" | "public" }noBelief content declaration. Each entry in include refers to a beliefs/<entry>/BELIEF.md.card-manifest.ts:21,40
memoryPartial<Record<"l4" | "l5" | "l6", { include?: string[]; visibility?: ...; format?: "md" | "jsonl" | "mixed" }>>noMemory layer declarations. Each key is a layer (l4, l5, l6); entries refer to directories under memory/<layer>/<entry>/.card-manifest.ts:23-27,41
stability"experimental" | "stable" | "production"noAuthoring quality signal.card-manifest.ts:69-74
lastValidatedWithstringnoStrict semver of the drwn version the author last validated this card with.card-manifest.ts:75-79
testStatusBadgestringnohttp(s) URL to a CI status badge image.card-manifest.ts:80-84

Mind content example​

{
"name": "@your-handle/mind",
"version": "1.0.0",
"hooks": { "include": ["audit-tool-calls"] },
"persona": { "include": ["voice"], "visibility": "internal" },
"beliefs": { "include": ["engineering"], "visibility": "public" },
"memory": {
"l4": { "include": ["context"], "visibility": "private", "format": "md" },
"l6": { "include": ["raw"], "visibility": "private", "format": "jsonl" }
}
}

Reserved and Forbidden​

  • skills.exclude is rejected outright. Cards contribute additively; consumers exclude via project config.
  • skills.shared is reserved. The validator accepts an empty array but rejects any non-empty value with a Wave 2 reservation message (card-manifest.ts:91-97). Today, cards only ship bundled skill directories under skills.include.

Quality Fields (Wave 2)​

stability, lastValidatedWith, and testStatusBadge are surfaced by drwn card show, drwn card source show, and search results. They are advisory: drwn does not gate publication on them. Authoring helpers like drwn card source set --stability ... --last-validated-with ... --test-status-badge ... write them in.