Skip to main content

Manifest Files

Radish CLI generates manifest files to track generation metadata, blueprint hashes, and enable verification.

Overview

Every time you generate code, Radish creates two manifest files:

  1. .radish/MANIFEST.json - Top-level manifest tracking all generations
  2. .radish/lib/datalayer/MANIFEST.json - Datalayer-specific manifest with detailed metadata

These manifests enable:

  • Blueprint verification - Check if generated code matches current blueprint
  • Debugging - Know exact CLI version and generation timestamp
  • CI/CD validation - Fail builds if generated code is stale
  • Environment sync - Compare staging vs production manifests

Top-Level Manifest

Location: .radish/MANIFEST.json

Tracks overall project generation state.

Structure

{
"$schema": "https://radish-cli.dev/schemas/manifest.v1.json",
"manifestVersion": "1.0",
"radishVersion": "0.6.0",
"projectName": "my-app",
"generatedAt": "2026-03-11T10:30:00.000Z",

"blueprints": {
"types": {
"path": "blueprints/app.types.yml",
"hash": "sha256:89f21a4b2c3d4e5f",
"lastModified": "2026-03-11T09:15:00.000Z"
}
},

"layers": {
"datalayer": {
"enabled": true,
"manifestPath": "lib/datalayer/MANIFEST.json",
"version": "1.0.0",
"generatedAt": "2026-03-11T10:30:00.000Z"
},
"uilayer": {
"enabled": false,
"manifestPath": null,
"version": null,
"generatedAt": null
},
"infrastructure": {
"enabled": false,
"manifestPath": null,
"version": null,
"generatedAt": null
}
},

"cli": {
"version": "0.6.0",
"command": "radish-cli create datalayer . --schema blueprints/app.types.yml",
"cwd": "/path/to/project",
"nodeVersion": "v20.10.0",
"platform": "darwin"
}
}

Fields

FieldDescription
manifestVersionManifest schema version (currently 1.0)
radishVersionCLI version used for generation
projectNameProject name (from directory name or --app-name)
generatedAtISO 8601 timestamp of generation
blueprints.types.pathRelative path to types blueprint file
blueprints.types.hashSHA-256 hash (first 16 chars) of blueprint content
blueprints.types.lastModifiedBlueprint file modification timestamp
layers.datalayer.enabledWhether datalayer was generated
layers.datalayer.manifestPathPath to layer-specific manifest
cli.commandFull command used for generation
cli.cwdWorking directory during generation
cli.nodeVersionNode.js version used
cli.platformOperating system platform

Datalayer Manifest

Location: .radish/lib/datalayer/MANIFEST.json

Detailed metadata about generated datalayer.

Structure

{
"$schema": "https://radish-cli.dev/schemas/datalayer-manifest.v1.json",
"manifestVersion": "1.0",
"layer": "datalayer",
"layerVersion": "1.0.0",
"radishVersion": "0.6.0",
"generatedAt": "2026-03-11T10:30:00.000Z",

"blueprint": {
"path": "blueprints/app.types.yml",
"hash": "sha256:89f21a4b2c3d4e5f",
"entities": 12,
"builtinEntities": 3,
"customEntities": 9
},

"entities": [
{
"name": "Product",
"type": "custom",
"builtin": false,
"extended": false,
"fields": 8,
"relationships": ["Category", "Vendor"],
"features": {
"versioning": "full",
"filtering": true,
"population": true,
"permissions": ["admin", "user"]
}
},
{
"name": "User",
"type": "system",
"builtin": true,
"extended": true,
"fields": 12,
"relationships": [],
"features": {
"versioning": "simple",
"filtering": true,
"population": false,
"permissions": ["admin", "self"]
}
}
],

"generated": {
"contracts": {
"files": 45,
"path": "contracts/"
},
"models": {
"files": 28,
"path": "server/models/"
},
"repositories": {
"files": 28,
"path": "server/repos/"
},
"services": {
"files": 32,
"path": "server/services/"
},
"routes": {
"files": 156,
"path": "server/routes/"
},
"metadata": {
"files": 29,
"path": "contracts/metadata/"
},
"docs": {
"files": 8,
"path": "docs/"
}
},

"database": {
"type": "mongodb",
"adapter": "mongoose"
},

"permissions": {
"roles": ["admin", "user", "anonymous"],
"wildcards": true
}
}

Fields

FieldDescription
blueprint.hashSHA-256 hash of blueprint (matches top-level manifest)
blueprint.entitiesTotal entity count
blueprint.builtinEntitiesNumber of builtin entities (User, Role, etc.)
blueprint.customEntitiesNumber of custom entities from blueprint
entities[]Array of entity metadata
entities[].nameEntity name
entities[].typeEntity type: "system" or "custom"
entities[].builtinWhether entity is builtin
entities[].extendedWhether entity extends a builtin entity
entities[].fieldsField count
entities[].relationshipsArray of referenced entity names
entities[].features.versioningVersioning mode: "full", "simple", or false
entities[].features.filteringWhether filtering is enabled
entities[].features.populationWhether entity has relationships
entities[].features.permissionsArray of permission names
generated.*File counts by category
database.typeDatabase type ("mongodb")
database.adapterORM adapter ("mongoose")
permissions.rolesAvailable roles
permissions.wildcardsWhether wildcard permissions are supported

Use Cases

1. Verify Generated Code Matches Blueprint

Automated verification (available in v0.6.0+):

# Quick verification
radish-cli verify

# Output:
# ✅ types: Up to date (sha256:89f21a4b)

# Verbose mode with detailed info
radish-cli verify --verbose

# Use in CI/CD (exits 0 if match, 1 if mismatch)
radish-cli verify || exit 1

Manual verification:

# View blueprint hash
cat .radish/MANIFEST.json | jq '.blueprints.types.hash'

# Compute hash of current blueprint
cat blueprints/app.types.yml | sha256sum | head -c 16

# Compare - if they don't match, regenerate
radish-cli create datalayer . --schema blueprints/app.types.yml

2. Debug Regeneration Issues

Using the info command (available in v0.6.0+):

# Human-readable manifest info
radish-cli info

# Output:
# 📦 Radish CLI v0.6.0
# Project: my-app
#
# Blueprints:
# types: blueprints/app.types.yml (sha256:89f21a4b)
#
# Layers:
# ✅ Datalayer v1.0.0
# - 12 entities (3 builtin, 9 custom)
# - 318 generated files
# - Blueprint: blueprints/app.types.yml (sha256:89f21a4b)
#
# Last generated: 2 hours ago

# JSON output for scripting
radish-cli info --json | jq '.radishVersion'

Manual queries:

# What CLI version generated this code?
cat .radish/MANIFEST.json | jq -r '.radishVersion'

# When was it generated?
cat .radish/MANIFEST.json | jq -r '.generatedAt'

# What was the exact command?
cat .radish/MANIFEST.json | jq -r '.cli.command'

3. CI/CD Validation

Ensure generated code is up-to-date before deployment:

# .github/workflows/ci.yml
- name: Verify generated code is current
run: |
MANIFEST_HASH=$(cat .radish/MANIFEST.json | jq -r '.blueprints.types.hash')
BLUEPRINT_HASH=$(cat blueprints/app.types.yml | sha256sum | head -c 16)

if [ "sha256:$BLUEPRINT_HASH" != "$MANIFEST_HASH" ]; then
echo "❌ Generated code out of date!"
echo "Run: radish-cli create datalayer . --schema blueprints/app.types.yml"
exit 1
fi

echo "✅ Generated code matches blueprint"

4. Compare Environments

Check if staging and production have matching generated code:

# On local machine
LOCAL_HASH=$(cat .radish/MANIFEST.json | jq -r '.blueprints.types.hash')

# On staging server
STAGING_HASH=$(ssh staging 'cat /app/.radish/MANIFEST.json | jq -r ".blueprints.types.hash"')

# Compare
if [ "$LOCAL_HASH" == "$STAGING_HASH" ]; then
echo "✅ Local matches staging"
else
echo "⚠️ Different blueprint versions:"
echo " Local: $LOCAL_HASH"
echo " Staging: $STAGING_HASH"
fi

Future: radish-cli compare staging command will automate this (v0.7+).

5. Entity Overview

Get a quick overview of generated entities:

# How many entities?
cat .radish/lib/datalayer/MANIFEST.json | jq '.blueprint.entities'

# List all entity names
cat .radish/lib/datalayer/MANIFEST.json | jq -r '.entities[].name'

# Which entities have versioning?
cat .radish/lib/datalayer/MANIFEST.json | jq -r '.entities[] | select(.features.versioning != false) | .name'

# Entity with most fields
cat .radish/lib/datalayer/MANIFEST.json | jq '.entities | max_by(.fields) | .name'

6. File Count Tracking

See how much code was generated:

# Total files generated
cat .radish/lib/datalayer/MANIFEST.json | jq '[.generated[].files] | add'

# Files by category
cat .radish/lib/datalayer/MANIFEST.json | jq '.generated | to_entries | map({key: .key, value: .value.files})'

Blueprint Hash Algorithm

Radish uses SHA-256 hashing with the first 16 characters for compact representation:

import crypto from 'crypto';

function generateBlueprintHash(blueprintContent) {
return crypto
.createHash('sha256')
.update(blueprintContent)
.digest('hex')
.substring(0, 16); // First 16 chars (64 bits)
}

Why first 16 characters?

  • 64-bit hash space (16^16 = 2^64)
  • Astronomically low collision probability
  • Compact representation in manifests
  • Sufficient for change detection

Git Integration

Commit Manifests with Generated Code

# Regenerate after blueprint changes
radish-cli create datalayer . --schema blueprints/app.types.yml

# Review changes (manifests show blueprint hash update)
git diff .radish/MANIFEST.json .radish/lib/datalayer/MANIFEST.json

# Commit blueprint + manifests + generated code together
git add blueprints/ .radish/
git commit -m "feat: add Product entity"

Benefits in Code Review

  • Minimal diff - Only 2 manifest files change on blueprint edits (vs 300+ file headers)
  • Clear intent - Blueprint hash change shows blueprint was modified
  • Metadata visible - Entity counts, file counts show scope of changes
  • Verification - Reviewers can verify hash matches blueprint

Example Git Diff

When you modify a blueprint, git diff shows:

diff --git a/.radish/MANIFEST.json b/.radish/MANIFEST.json
--- a/.radish/MANIFEST.json
+++ b/.radish/MANIFEST.json
@@ -7,7 +7,7 @@
"blueprints": {
"types": {
"path": "blueprints/app.types.yml",
- "hash": "sha256:89f21a4b2c3d4e5f",
+ "hash": "sha256:7a8b9c0d1e2f3a4b",
"lastModified": "2026-03-11T12:45:00.000Z"

Clean, minimal change showing blueprint was modified.

Available CLI Commands

The following manifest-related commands are available in v0.6.0+:

radish-cli verify ✅ Available

Automated blueprint verification:

# Basic verification
radish-cli verify

# Output if up to date:
# ✅ types: Up to date (sha256:89f21a4b)
#
# Blueprint: blueprints/app.types.yml
# Generated: 2 hours ago

# Output if blueprint changed:
# ⚠️ types: Blueprint has changed
# Current: sha256:7a8b9c0d
# Manifest: sha256:89f21a4b
#
# Regenerate: radish-cli create datalayer . --schema blueprints/app.types.yml

# Verbose mode
radish-cli verify --verbose

Exit codes:

  • 0 - Generated code matches blueprint
  • 1 - Generated code out of sync with blueprint

radish-cli info ✅ Available

Display manifest information:

# Human-readable output
radish-cli info

# Output:
# 📦 Radish CLI v0.6.0
# Project: my-app
#
# Blueprints:
# types: blueprints/app.types.yml (sha256:89f21a4b)
#
# Layers:
# ✅ Datalayer v1.0.0
# - 12 entities (3 builtin, 9 custom)
# - 318 generated files
# - Blueprint: blueprints/app.types.yml (sha256:89f21a4b)
#
# Last generated: 2 hours ago

# JSON output for scripting
radish-cli info --json

# Extract specific fields
radish-cli info --json | jq '.radishVersion'
radish-cli info --json | jq '.blueprints.types.hash'

Future Enhancements

The following commands are planned for v0.7+:

radish-cli compare <env>

Compare manifests across environments:

radish-cli compare staging

# Output:
# Comparing local vs staging.example.com/.radish/MANIFEST.json
#
# ⚠️ Blueprint hash mismatch:
# Local: sha256:89f21a4b
# Staging: sha256:1a2b3c4d
#
# Entities changed:
# + Product (new)
# ~ User (modified - 2 new fields)
# - Category (deleted)

Best Practices

DO:

  • ✅ Commit manifests with generated code
  • ✅ Check manifest hash after regeneration
  • ✅ Use manifests for debugging generation issues
  • ✅ Review manifest diffs in pull requests
  • ✅ Validate manifests in CI/CD pipelines

DON'T:

  • ❌ Manually edit manifest files
  • ❌ Ignore manifest hash mismatches
  • ❌ Delete manifests (regenerate will recreate them)
  • ❌ Rely on file headers for blueprint hashes (headers are for humans, manifests are for tools)

Troubleshooting

Manifest file missing

Cause: Generated with older CLI version (< 0.6.0)

Solution: Regenerate with latest CLI:

npm update -g radish-cli
radish-cli create datalayer . --schema blueprints/app.types.yml

Hash mismatch after blueprint edit

Cause: Blueprint modified but code not regenerated

Solution: Regenerate:

radish-cli create datalayer . --schema blueprints/app.types.yml

Wrong entity counts in manifest

Cause: Regeneration error or partial generation

Solution: Clean and regenerate:

rm -rf .radish/
radish-cli create datalayer . --schema blueprints/app.types.yml