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:
.radish/MANIFEST.json- Top-level manifest tracking all generations.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
| Field | Description |
|---|---|
manifestVersion | Manifest schema version (currently 1.0) |
radishVersion | CLI version used for generation |
projectName | Project name (from directory name or --app-name) |
generatedAt | ISO 8601 timestamp of generation |
blueprints.types.path | Relative path to types blueprint file |
blueprints.types.hash | SHA-256 hash (first 16 chars) of blueprint content |
blueprints.types.lastModified | Blueprint file modification timestamp |
layers.datalayer.enabled | Whether datalayer was generated |
layers.datalayer.manifestPath | Path to layer-specific manifest |
cli.command | Full command used for generation |
cli.cwd | Working directory during generation |
cli.nodeVersion | Node.js version used |
cli.platform | Operating 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
| Field | Description |
|---|---|
blueprint.hash | SHA-256 hash of blueprint (matches top-level manifest) |
blueprint.entities | Total entity count |
blueprint.builtinEntities | Number of builtin entities (User, Role, etc.) |
blueprint.customEntities | Number of custom entities from blueprint |
entities[] | Array of entity metadata |
entities[].name | Entity name |
entities[].type | Entity type: "system" or "custom" |
entities[].builtin | Whether entity is builtin |
entities[].extended | Whether entity extends a builtin entity |
entities[].fields | Field count |
entities[].relationships | Array of referenced entity names |
entities[].features.versioning | Versioning mode: "full", "simple", or false |
entities[].features.filtering | Whether filtering is enabled |
entities[].features.population | Whether entity has relationships |
entities[].features.permissions | Array of permission names |
generated.* | File counts by category |
database.type | Database type ("mongodb") |
database.adapter | ORM adapter ("mongoose") |
permissions.roles | Available roles |
permissions.wildcards | Whether 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 blueprint1- 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
Related Documentation
- Generated Code Overview - Complete generated structure
- CLI Reference - Command-line options
- Blueprint Reference - Blueprint syntax