Manifest Schema v1
A project-kit manifest is a YAML file under manifests/<id>.yml that describes how a project type is generated. Logic lives in Ruby; manifests describe structure only — there is no embedded Ruby and no inline patch logic in YAML.
Top-level keys
| Key | Required | Type | Description |
|---|---|---|---|
version | yes | Integer | Schema version. Must be 1. |
id | yes | String | Unique manifest id (e.g. ruby-gem). Used as the CLI <type> argument. |
language | yes | String | Primary language (e.g. ruby, typescript). |
type | yes | String | Broad classification (library, application, script, cli). |
templates | yes | Array | Base template sets, applied in order (e.g. [shared, ruby, ruby-gem]). |
name | no | String | Human-readable name. Defaults to id. |
subtype | no | String | Finer classification (e.g. gem, rails). |
capabilities | no | Hash | See Capabilities. |
variables | no | Hash<String, Hash> | Variables and defaults available in templates. |
initializer | no | Hash | Upstream command to bootstrap the project. See Initializer. |
capability_templates | no | Hash<String, Array | Per-capability template overlays. |
mise | no | Hash | Source data for the generated mise.toml. |
patchers | no | Array | Symbolic patcher references (e.g. ruby/gemspec). |
Capabilities
capabilities:
supported:
- cli
- typed
- coverage
- github-actions
- mise
default:
- mise
- github-actions
- coverage
supported— capabilities this manifest is willing to apply. Anything not listed here is rejected by the CLI.default— capabilities enabled by default. Must be a subset ofsupported.
Built-in capabilities: cli, typed, docs, release, coverage, github-actions, mise. The CLI exposes a --<capability> / --no-<capability> flag for each.
Variables
variables:
ruby_version:
default: "3.4"
author:
default: "TODO Author"
Variables are available in templates as <%= var('ruby_version') %>, in path tokens as __ruby_version__, and in mise/initializer string fields as ``. The name variable is automatically seeded from the CLI argument.
Initializer
initializer:
command: "bundle gem --test=rspec --mit --linter=standard --git"
append_if:
cli:
- "--exe"
typed:
- "--rbs"
The command is run in the parent directory of the destination, so generators that create their own subdirectory (most do) write into the expected path. append_if[<cap>] arguments are appended for each enabled capability.
Templates
templates:
- shared
- ruby
- ruby-gem
Walked in order. Files are looked up under templates/<set>/. See template-overlay.md for details.
Capability templates
capability_templates:
cli:
- cli
github-actions:
- github-actions
coverage:
- coverage-ruby
Mapping of capability id -> array of template set names under templates/capabilities/. Applied after base templates, in capability-resolution order.
Mise
mise:
tools:
ruby: ""
tasks:
test:
description: "Run the test suite"
run: "bundle exec rspec"
check:
description: "Run lint and tests"
depends:
- lint
- test
String values support `` interpolation. The MiseWriter renders this section into a project-local mise.toml.
Patchers
patchers:
- ruby/gemspec
- ruby/spec_helper
Each entry resolves to a Ruby class:
| Manifest reference | Class |
|---|---|
ruby/gemspec | ProjectKit::Patchers::Ruby::Gemspec |
ruby/spec_helper | ProjectKit::Patchers::Ruby::SpecHelper |
rails/rspec | ProjectKit::Patchers::Rails::Rspec |
github_actions/non_blocking_lint | ProjectKit::Patchers::GithubActions::NonBlockingLint |
Patchers run after templates and have read/write access to the generated tree.
Validation
Manifest.load(path) calls validate! which checks:
- All required keys are present.
- No unknown top-level keys.
versionmatchesManifest::SCHEMA_VERSION(currently1).templates,capabilities.supported,capabilities.defaultare arrays.capabilities.defaultis a subset ofcapabilities.supported.initializer.commandis a string.