Mason
SkillDev toolsWorking with Mason bricks: installing the CLI, creating and consuming bricks, understanding brick structure, Mustache template syntax, hooks, and discovering bricks on BrickHub.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Mason skill
What this skill tells your AI
The instructions your AI receives, as published by verygoodopensource/very_good_templates in .agents/skills/mason/SKILL.md and read by ahel’s review.
Mason is a collection of tools that allow developers to create and consume reusable templates called bricks. BrickHub is the registry where bricks are published and discovered.
Core Standards
- All template logic belongs in hooks —
__brick__/files use only Mustache tags; no conditional logic lives in template files - Every brick variable must appear in both
brick.yamlandconfig.json— a missing key inconfig.jsonbreaks CI generation - Never edit
version.txt,brick.yamlversion, orCHANGELOG.mdmanually — these are owned by release-please - Hook packages require 100% test coverage — CI enforces this via
report_on: "pre_gen.dart"in each*_hooks.yamlworkflow - Use
{{{variable}}}(triple braces) when the value must not be HTML-escaped — double braces escape special characters by default
CLI Installation
# Activate from pub.dev (recommended)
dart pub global activate mason_cli
# Or via Homebrew
brew tap felangel/mason
brew install mason
Verify the installation:
mason --version
Workspace Setup
Initialize Mason in a directory to create a mason.yaml that tracks
installed bricks:
mason init
Install all bricks listed in mason.yaml:
mason get
Consuming Bricks
Add a brick
# From BrickHub
mason add very_good_core
# From a local path
mason add my_brick --path ./path/to/brick
# From a Git repository
mason add my_brick --git-url https://github.com/org/repo --git-path bricks/my_brick
Generate code from a brick
# Interactive prompts for each variable
mason make very_good_core
# Pass variables inline (used in CI via config.json)
mason make very_good_core -c very_good_core/config.json \
--on-conflict overwrite -o very_good_core_output
List installed bricks
mason list
Brick Structure
<brick>/
__brick__/ # Mustache template files — the generated output
hooks/ # pre_gen.dart / post_gen.dart + pubspec.yaml + test/
brick.yaml # Metadata and variable definitions
CHANGELOG.md # Auto-generated — never edit by hand
LICENSE
README.md
brick.yaml
Defines the brick name, version, and all input variables:
name: my_brick
description: A sample brick.
version: 0.1.0+1
environment:
mason: ">=0.1.0 <0.1.0"
vars:
project_name:
type: string
description: The name of the project.
default: my_project
prompt: What is the project name?
use_flutter:
type: boolean
description: Whether to include Flutter dependencies.
default: true
prompt: Include Flutter?
Variable Types
| Type | Description | Example |
|---|---|---|
string | A primitive string | "my_project" |
number | A primitive number | 42 |
boolean | A primitive boolean | true / false |
enum | Single choice from a fixed list | ["red", "green"] → "red" |
array | Multiple choices from a fixed list | ["ios", "android"] → ["ios"] |
list | Open-ended list of strings | ["dart", "python"] |
Mustache Template Syntax
Templates live in __brick__/ and use
Mustache syntax.
Variable interpolation
# Hello {{name}}!
Use triple braces to skip HTML escaping:
{{{raw_html_content}}}
Conditionals
{{#use_flutter}}
flutter:
sdk: flutter
{{/use_flutter}}
{{^use_flutter}}
# Pure Dart project
{{/use_flutter}}
Conditionals also work on file paths — wrap the filename in the brick
variable to generate the file only when the variable is true:
__brick__/
{{#create_changelog}}CHANGELOG.md{{/create_changelog}}
Loops
{{#platforms}}
- {{.}}
{{/platforms}}
Built-in Lambdas
Apply case transformations directly in templates or file names:
| Lambda | Example output | Shorthand syntax |
|---|---|---|
camelCase | helloWorld | {{name.camelCase()}} |
pascalCase | HelloWorld | {{name.pascalCase()}} |
snakeCase | hello_world | {{name.snakeCase()}} |
paramCase | hello-world | {{name.paramCase()}} |
constantCase | HELLO_WORLD | {{name.constantCase()}} |
dotCase | hello.world | {{name.dotCase()}} |
pathCase | hello/world | {{name.pathCase()}} |
sentenceCase | Hello world | {{name.sentenceCase()}} |
titleCase | Hello World | {{name.titleCase()}} |
lowerCase | hello world | {{name.lowerCase()}} |
upperCase | HELLO WORLD | {{name.upperCase()}} |
Lambdas apply to file names too:
__brick__/
{{name.snakeCase()}}.dart
Partials
Reuse template fragments across files using partials. Partial files are
prefixed with {{~ }} and included with {{> }}:
__brick__/
HELLO.md
{{~ header.md }}
{{~ footer.md }}
In HELLO.md:
{{> header.md }}
Hello {{name}}!
{{> footer.md }}
Hooks
Hooks run Dart code before (pre_gen) or after (post_gen) generation.
All conditional logic and derived variable computation belongs here — never
in __brick__/ files.
hooks/
pre_gen.dart
post_gen.dart
pubspec.yaml
lib/
test/
pre_gen.dart
import 'package:mason/mason.dart';
void run(HookContext context) {
// Read a variable
final name = context.vars['project_name'] as String;
// Compute and inject a derived variable
context.vars['project_name_pascal'] = name.pascalCase;
// Log to the user
context.logger.info('Generating $name...');
}
post_gen.dart
import 'dart:io';
import 'package:mason/mason.dart';
Future<void> run(HookContext context) async {
final progress = context.logger.progress('Installing packages');
await Process.run('flutter', ['pub', 'get']);
progress.complete();
}
Disable hooks during generation with --no-hooks:
mason make my_brick --no-hooks
Creating a New Brick
# Scaffold a new brick in the current directory
mason new my_brick
# With a custom description
mason new my_brick --desc "Generates a feature module"
# With hooks scaffolded
mason new my_brick --hooks
# In a specific output directory
mason new my_brick -o ./bricks
Discovering Bricks on BrickHub
Search for community bricks at brickhub.dev/search or via the CLI:
mason search <query>
Publishing a Brick
# Log in to BrickHub
mason login
# Publish the brick in the current directory
mason publish
Anti-Patterns
| Anti-Pattern | Problem | Correct Approach |
|---|---|---|
Putting conditional logic in __brick__/ files | Mustache is logic-less; complex conditions become unreadable | Move all logic to pre_gen.dart and inject derived variables |
Adding a variable to brick.yaml but not config.json | CI generation fails with a missing key error | Always keep both files in sync |
Editing version.txt or CHANGELOG.md by hand | Breaks the automated release-please workflow | Let release-please manage versioning |
Using {{variable}} for raw HTML or code with <, >, & | Output gets HTML-escaped | Use {{{variable}}} for unescaped output |
| Skipping hook tests | CI enforces 100% coverage on hook code | Write tests for every hook code path |
References
Signals
- GitHub stars
- 174
- Forks
- 31
- Last commit
- Sep 2026
ahel review
K1binfo
installs-packages
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
mason-verygoodopensource- Source
- github.com/verygoodopensource/very_good_templates