Skip to main content

Card Manifest

On disk: card.json at the root of a card source tree (~/.agents/drwn/sources/<scope>/<name>/card.json) or a published/consumed card tree.

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.excludeforbiddenRejected: 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
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.