Borrowing it
Nothing to install: this file belongs to Cratis/VerticalSlices. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/Cratis/VerticalSlices/main/.ai/skills/add-projection/SKILL.mdgit clone --depth 1 https://github.com/Cratis/VerticalSlicesWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/cratis/verticalslices/add-projection)<a href="https://agentmods.dev/skills/cratis/verticalslices/add-projection"><img src="https://agentmods.dev/badge/skills/cratis/verticalslices/add-projection/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/cratis/verticalslices/add-projection"><img src="https://agentmods.dev/badge/skills/cratis/verticalslices/add-projection.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00068 | $0.01551 |
| Opus 5.5 | $0.00027 | $0.00620 |
| Sonnet 5.5 | $0.00014 | $0.00310 |
| Haiku 4.5 | $0.00007 | $0.00155 |
Grade A, and why
add-projection scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 1mo ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
This is a copy
100% identical to add-projection — 0 lines differ, which has more behind it and is treated as the original. This page carries a canonical link to it rather than competing with it.
How it starts
The opening of the file, as written. The whole thing — 104 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Add a Chronicle projection that populates a read model from events.
For reactors (automation / translation), see the
add-reactorskill instead.
Projection — Model-Bound (preferred)
Put projection metadata directly on the read model using attributes. No separate class needed.
[ReadModel]
[FromEvent<SomeEventHappened>] // auto-maps all matching property names
public record <ReadModelName>(
[Key] <IdType> Id, // marks the primary key
<PropType> <PropName>) // auto-mapped from SomeEventHappened
{
public static ISubject<IEnumerable<<ReadModelName>>> All(IMongoCollection<<ReadModelName>> collection) =>
collection.Observe();
}
Attribute reference:
| Attribute | Purpose |
|---|---|
[FromEvent<T>] |
Maps event T onto the read model; matching property names map automatically (AutoMap is on by default — never call .AutoMap()) |
[FromEvent<T>(key: nameof(T.Prop))] |
Same, but uses Prop as the read model key instead of EventSourceId |
[Key] |
Marks the primary key property |
[SetFrom<T>(nameof(T.Prop))] |
Explicitly maps one property from event T |
[AddFrom<T>(nameof(T.Prop))] |
Adds event property value to the read model property |
[SubtractFrom<T>(nameof(T.Prop))] |
Subtracts event property value |
[ChildrenFrom<T>(key: nameof(T.Prop))] |
Projects into a nested child collection |
[Join<T>(on: nameof(Prop), eventPropertyName: nameof(T.EProp))] |
Joins data from a related event |
[RemovedWith<T>] |
Marks the instance as removed when event T is appended |
Critical rules:
- Joins must be on Chronicle events — NEVER join on a read model type
- If property names between event and read model match,
[FromEvent<T>]alone is sufficient - Child types also support all attributes recursively
Projection — Fluent / declarative (fallback for complex cases)
Use IProjectionFor<T> only when the projection logic is too complex for model-bound attributes or would become less clear if forced into attributes.
What ships with it
2 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 1mo ago First seen · 104 lines · 68 tokens per session scan A e6c53b655a68
add-projection is a skill published in the GitHub repository Cratis/VerticalSlices (2 stars, last pushed 1mo ago), licensed MIT. It adds 68 tokens to every session and 1,551 once invoked, about $0.0003 per session on Opus 5.5. A static security scan graded it A with 0 findings. It is 100% identical to add-projection, differing in 0 lines, and is treated as a copy.
Other skills, from other repositories
cratis-chronicle-event-type-migration
Evolve a Chronicle event schema without breaking replay - add a generation and an EventTypeMigration so stored events upcast into the new shape. Use when an event needs a new required property, a renamed or split property, a structural change, or a changed enum value after events of the prior shape already exist. Do…
cratis-chronicle-projection
Add Chronicle projection behavior to an existing read model - model-bound attributes first, the fluent IProjectionFor builder when they cannot express the shape. Covers AutoMap, keys, children and nested types, counters, event-sequence selection, variants (VariantOf and EntersOn, as attributes or fluent calls) for an…
cratis-chronicle-read-model
Create a Chronicle read model and its query surface - past-tense event types, the read-model record and its key, choosing a projection or a reducer to build it, snapshot versus observable queries (including why Arc does not discover a query declared to return Subject or BehaviorSubject), and reading an instance…
cratis-chronicle-reducer
Write a Chronicle IReducerFor reducer when model-bound projection attributes and the fluent IProjectionFor builder cannot express a read-model state transition. Covers the admission test, the exact accepted method signatures, the nullable-current requirement, deletion, passivity and event filtering. Use only after the…
cratis-screenplay-projections
Build a Cratis Screenplay read model with the Projection Declaration Language (PDL) — keys, from/every/all, property mapping and AutoMap, joins, children and nested objects, removal, arithmetic counters, and the reducer escape hatch. Use when declaring or changing how events become read-model state in a .play model…
cratis-arc-ef-core-migration
Change an Entity Framework Core schema in a Cratis Arc application — the DbContext base types Arc provides, the cross-database column helpers, JSON columns, how a migration is created and applied, and how an EF Core read model becomes injectable into a command. Use when adding or changing a table, column…