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.json",
"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.json",
"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.json",
"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": "core/models/"
},
"repositories": {
"files": 28,
"path": "core/repos/"
},
"services": {
"files": 32,
"path": "services/"
},
"routes": {
"files": 156,
"path": "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.json | sha256sum | head -c 16

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

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.json (sha256:89f21a4b)
#
# Layers:
# ✅ Datalayer v1.0.0
# - 12 entities (3 builtin, 9 custom)
# - 318 generated files
# - Blueprint: blueprints/app.types.json (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:

{
"name": "Verify generated code is current",
"run": "MANIFEST_HASH=$(cat .radish/MANIFEST.json | jq -r '.blueprints.types.hash') && BLUEPRINT_HASH=$(cat blueprints/app.types.json | 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.json' && 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.json

# 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.json",
- "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.json
# 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.json

# 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.json (sha256:89f21a4b)
#
# Layers:
# ✅ Datalayer v1.0.0
# - 12 entities (3 builtin, 9 custom)
# - 318 generated files
# - Blueprint: blueprints/app.types.json (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.json

Hash mismatch after blueprint edit​

Cause: Blueprint modified but code not regenerated

Solution: Regenerate:

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

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.json