Reference

Every type, rule, tool and option

Tables to look things up in. The guide explains how to use them.

Element types

The C4 metamodel has the first eight. The Radical metamodel has all of them, lets a Software System sit inside a Domain, and adds the rest. Types of the Radical layers sit at the root, in a system, in a domain or in a group unless the table says otherwise. Every type has a name, a description and a parent.

C4

TypeWhat it isLives inFields
PersonSomeone who uses or runs the system: a customer, an operator, another team.Root, group. Never inside a system.External
Software SystemSomething that delivers value and is owned by one team: yours, or one you depend on.Root, group, system; in Radical also a domain, as the bounded context that realises it.External
ContainerSomething that runs or stores data and is deployed on its own: a service, a worker, a mobile app.System, or a group inside one.Technology, External
DatabaseA container that stores data and never starts an interaction.System, or a group inside one.Technology, External
Web AppA container that is a browser front end; it may hold components.System, or a group inside one.Technology, External
QueueA container that carries messages between containers.System, or a group inside one.Technology, External
ComponentA part of a container behind a clear interface: a controller, an adapter.Container, web app, or a group inside one. Never straight in a system.Technology, External
GroupA labelled boundary with no meaning of its own: a team, a layer, a zone. No relation starts or ends at a group.Root, group, system.—

Domain

TypeWhat it isLives inFields
DomainA part of the problem space in the language of the business: Payments. A domain in a domain is a subdomain.Root, group, domain.Kind (core, supporting, generic), Vision
EntityA thing with an identity over time: an order, a reservation. An aggregate root is a consistency boundary; an entity is part of exactly one root.Root, domain, group.Kind (aggregate root, entity)

Requirements

TypeWhat it isFields
NeedRaw stakeholder input kept verbatim: a brief, a user story, a regulation. No status; nothing satisfies or verifies it.Kind, Source; the text is the description
RequirementOne thing the system shall do, as an EARS sentence. Its subject is the first element that satisfies it.EARS type (ubiquitous, event-driven, state-driven, unwanted behaviour, optional, complex), Trigger, Precondition or While in state, Condition, Feature, Action, Rationale
ScenarioAn acceptance example in Gherkin.Given, When, Then, Extra steps, Tests (one file › title per line)

States

TypeWhat it isLives inFields
State MachineThe lifecycle of one entity, drawn as a frame that holds its states.Root, system, domain, group.—
StateA situation the entity can be in. A state with states is compound.Machine, state.Kind (normal, parallel, final), Entry, Exit, Do
PseudostateA point the machine passes through: initial, shallow or deep history, choice.Machine, state.Kind
EventSomething that happens and can trigger a transition.Root, machine, system, domain, group.Source (external, internal, timer), Payload

Process

TypeWhat it isLives inFields
ProcessA procedure made of steps.Root, system, domain, group.Children run (sequence, choice, concurrent)
StepOne part of a process.Process, step.Order, Repeat (1, 0..1, 1..n, 0..n), Condition, Children run

UX and governance

TypeWhat it isFields
MockupOne screen of the product, with an optional low-fi wireframe (sanitised SVG).Screen / route, Design link, Wireframe
ADRAn architecture decision record in the Nygard / MADR shape. A new one starts proposed with today's date.Status (proposed, accepted, deprecated, superseded), Date, Context, Decision, Consequences, Alternatives considered, Concern
Fitness FunctionAn automated check that the architecture keeps a property it was designed for.Category (structural, operational, process, holistic), Threshold / success criteria, Tests
BlueprintA curated reference architecture as the Hub once shipped them. Not in the palette; models that hold one keep it.Status, Domain / context, Rationale

Relation types

Each relation has a direction: read it as a sentence from source to target. Studio picks the type the pair of ends allows; where two fit (entity → entity, domain → domain) it asks which.

C4

RelationFrom → toFieldsMeaning
InteractsPerson → system, container, web app, component
System → person, system, container, database, web app, queue, component
Container, Web App → person, system, container, database, web app, queue
Component → component, container, web app, database, queue, system
Queue → container, web app, component
TechnologyThe source calls, uses, sends to or delivers to the target. Draw it from the initiator. A database never initiates; nothing touches a group.

Domain

RelationFrom → toFieldsMeaning
RealisesSystem, container → domain
System, container, component, web app → entity
—The bounded context that implements the domain; the element that owns the entity's data.
Part ofEntity → entity—A part of an aggregate points to its root.
ReferencesEntity → entityCardinality (one, many)One aggregate refers to another by id.
Depends onDomain → domain—The source needs the target to do its work.
PartnershipDomain → domainPattern (partnership, shared kernel, customer–supplier, conformist, anti-corruption layer, open host service, published language, separate ways)How the two teams' models meet.

Traceability

RelationFrom → toFieldsMeaning
Derives fromRequirement → need
Requirement → requirement
Need → need
—The requirement turns that input into a shall-statement; decomposition; a need inside a broader one. Nothing else may point at a need.
SatisfiesC4 element, domain, entity, state machine, process → requirementNoteThis element is what makes the requirement true. The first one is the subject of the EARS sentence.
VerifiesScenario → requirement, state machine, process—The scenario is the acceptance test for it.
Traces toRequirement → ADR, fitness function—The decision the requirement led to, or the check that keeps it.

Behaviour

RelationFrom → toFieldsMeaning
Lifecycle ofState machine → entity—One machine per entity.
ImplementsSystem, container, component, web app → state machine
Fitness function → ADR
—This element runs the machine; this check verifies that the decision still holds.
TransitionState, pseudostate → state, pseudostate, within one machineEvent, Guard, Actions, Raises, Kind (external, internal)Labelled event [guard] / actions ^raised. No event means a completion transition.
EmitsPerson, system, container, component, web app, queue, state machine, state → eventOn (entry, exit, do) for a stateThis element raises the event.
Performed byStep → person, system, container, component, web app—Who does the step.

UX and governance

RelationFrom → toFieldsMeaning
IllustratesMockup → requirement, scenario, state—The screen shows this being met, or what the user sees in this state.
Presented byMockup → web app, container, component, system—The part of the architecture that renders the screen.
Navigates toMockup → mockupTriggerOne step of a screen flow.
ConstrainsADR, fitness function, requirement → person, system, domain, container, component, database, web app, queueNoteThe decision, check or requirement applies to that element. An agent reads this before it changes the element.
SupersedesADR → ADR—The newer decision replaces the older one.

Viewpoints

The Radical metamodel ships these twenty-five. The C4 metamodel ships the first six. Per element marks a viewpoint that makes a group with a view of each element of its type.

GroupViewpointView typeWhat it shows
C4System contextStructureThe people and systems, with every relation between them
ContainersStructureThe containers inside the systems
ComponentsStructureThe components inside the containers
Containers of a systemStructure, per elementOne system, its containers and what they are related to: C4's container diagram
Components of a containerStructure, per elementOne container, its components and what they are related to
Container dependenciesMatrixContainers, web apps, databases and queues
DomainDomain mapStructureDomains and how they depend on and partner with each other
Domain modelStructureEntities, what they are part of and reference
Entities of a domainStructure, per elementOne domain, its entities and the entities they reference
Domain realisationTableDomains, their entities and what realises each
RequirementsTraceabilityTableNeeds, the requirements refined from each, the scenarios that verify those
Requirement coverageTableRequirements, what satisfies and verifies each
Requirement gapsTableRequirements no scenario verifies or nothing satisfies
ResponsibilitiesTableSystems, containers and components with the requirements they satisfy
SpecificationWikiNeeds, their requirements and the scenarios and screens for each
DecisionsDecisionsTableADRs, the fitness functions that check each and what it constrains
Decision logWikiADRs, newest first, each with the ones it supersedes
Fitness functionsTableBy category, with what each checks and constrains
UXScreen flowStructureThe screens and how users move between them
ScreensTableThe screens with what they illustrate and what presents them
StatesEntity lifecyclesTableEntities with a state machine, what implements and verifies it
State machineStructure, per elementOne machine with its states, events and transitions
Event catalogueTableThe events and what emits each
ProcessProcess (Warnier)WarnierThe processes and their steps as Warnier–Orr diagrams
ProcessStructure, per elementOne process and its steps

Summary templates

Summary in tables on a node type is a template of tokens. A part in [ ] is left out when a token in it is empty; the template's own text may use Markdown. Left empty, the built-in template applies, else the description's first sentence.

TokenWhat it gives
{key}A property; also {label}, {description}, {technology}, {type}
{ears}A requirement's whole EARS sentence
{obligation} · {condition}Who shall do what; the when / while / if / where it holds under
{transitions}Where a state machine goes from a state or on an event
{out:type} · {in:type}The elements linked by relations of a type, out or in
{key.sentence} · {key.phrase}The first sentence; the first phrase
{key.cap} · {key.bold}Capitalised; bold
{a|b}The first of them that has a value

Built-in templates: [{obligation.bold}][ — {condition}] for a requirement, [{then.phrase.cap.bold}][ — when {when}] for a scenario, [{status.cap.bold}: ]{decision.sentence} for an ADR.

Rules & checks

The metamodel is enforced in three rings: what Studio refuses at once, what the Validation list and get_issues list as issues, and what only radical check and the Inspector report.

Refused at once

  • Placing or moving an element where its type may not sit, or at the root when it needs a parent.
  • One more element of a type that has reached its maximum.
  • A relation type that does not join its two ends, or a pair no relation type allows.
  • Changing an element's type when one of its relations would then not be allowed.
  • Moving a group where something it holds would have no place; moving an element into itself.
  • A transition out of a final state, or into an initial pseudostate.

The same refusals reach the AI assistant, Radical Forge and the MCP server as messages they can act on.

Listed as issues

AreaIssues
Any metamodelAn unknown type, a misplaced element, a relation to an element that is gone or between types no relation joins, a reference that points at nothing or the wrong type, an empty required field, too few or too many elements of a type; in custom metamodels, two properties of a type with one key.
Domain modelAn aggregate root that is part of something; a part of something that is not a root; an entity that belongs to no aggregate or to two.
State machinesA machine with no entity, or an entity with two machines; no initial pseudostate, or more than one; an initial pseudostate without exactly one outgoing transition; a parallel state with fewer than two regions; a final state with children or outgoing transitions; a transition that leaves its machine; two unguarded transitions from one state on one event; a state the initial state cannot reach.

Checked by radical check

Warnings unless check.json says otherwise; radical check --list-rules lists them with their ids.

AreaRules
RequirementsA requirement without the clauses its EARS type needs; one no scenario verifies; one nothing satisfies; one that derives from nothing; a need no requirement derives from; a scenario that verifies nothing.
Concernsconcern-unaddressed: a concern a pack finds in the model that no accepted ADR marked with it covers. concern-unbound: an accepted ADR marked with a concern that constrains no element.
DecisionsAn accepted ADR no fitness function implements; one without date, context, decision or consequences; a superseded status and Supersedes links that disagree; a fitness function that implements no ADR and constrains nothing, or has no threshold.
TestsA scenario or fitness function that names no test. With reports: a named test that failed or is missing (errors), was skipped, or whose file did not run; with an include, tests the model does not name (test-unbound).
The folderA missing radical.md, a JSON file that does not parse, git conflict markers, a node file without id or type, two files with one id (errors); views, sequences or slides that point at something gone.
Goalsgoal-unmet: a metric below the share check.json asks for (requirements with a scenario, accepted ADRs with a fitness function, requirements verified, scenarios passing, …).

radical check

Checks a Markdown folder: the folder's files, the metamodel rules and the completeness rules above. It never changes the model. Run the published package, or build it from a clone (see Install & build).

npx -y @radicaltools/cli check path/to/my-model --report reports
OptionWhat it does
[folder]The model folder. Default: the working directory.
--config <file>Rule settings. Default: check.json in the model folder.
--format text|json|githubPlain text (default), JSON, or GitHub Actions annotations.
--report <path>A test report (Vitest or Jest JSON, Playwright JSON, JUnit XML) or a directory of them; repeat for more. The test cases read are kept in .radical/test-results.json for the Inspector. A report with no test case stops the check with status 2.
--evidence <file>With --report: writes what the reports say about each scenario, fitness function, requirement and ADR as JSON.
--ratchetLowers each max in the config to the count found now and writes the config back. Never raises one.
--verboseLists every warning, not the first five of each rule.
--list-rulesLists the rules, their default severity, and the metrics goals can set.
radical --versionPrints the version, with the commit when the build is not a release (0.3.0+1a2b3c4).

Exit status: 0 no errors (warnings allowed), 1 errors, 2 the check could not run.

check.json

rules sets a rule by its id, or one kind of metamodel issue by metamodel/<code>, to error, warning or off. With max, up to that many findings pass as warnings and one more fails the check, so an existing model can adopt a rule before every gap is closed. goals sets the least share of a metric, in percent; a metric below its goal is goal-unmet, an error unless set otherwise.

{
  "rules": {
    "adr-incomplete": "off",
    "requirement-without-scenario": { "severity": "error", "max": 104 }
  },
  "goals": {
    "requirements-with-scenario": { "min": 85 },
    "requirements-verified": { "min": 80 }
  }
}

The Inspector's Settings tab edits the same file.

Changes on branch

radical diff <folder> prints the elements and relations added, removed and changed since the branch left main, with old and new values. Views and layout are left out. --since <ref> compares with another commit, tag or branch.

The base is the model at git merge-base HEAD origin/main, saved to .radical/base.json. Studio reads the file every few seconds and compares the model with it as you edit. Only the command line and the MCP server save it:

Saves the baseThrough
A checkout or switch of branchthe post-checkout hook
A commit, amended toothe post-commit hook
A pull that merges or fast-forwards, a mergethe post-merge hook
A rebase, git pull --rebase, an amendthe post-rewrite hook
An agent's get_changes without sincethe MCP server
By handradical diff <folder> --save-base
  • radical hooks install <folder> adds the four hooks. A fetch, a reset or a stash runs no hook.
  • Committing keeps the base, so the list holds the whole branch's work. After the pull request is merged, switch to main and pull: the list empties.
  • To see only what is not committed yet: radical diff <folder> --save-base --since HEAD.
  • A folder outside git has no base from git. A Radical Forge run on such a folder saves the model before it as the base; the next run replaces it.
  • A base older than a day is marked in the Inspector with the commands that save it again.

MCP server

Runs locally over stdio, bound to one Markdown folder. Node.js 20.11 or newer.

npx -y @radicaltools/mcp --folder /absolute/path/to/my-model   # waits for MCP messages on stdin
radical-mcp --version

Claude Desktop: add it under mcpServers in ~/Library/Application Support/Claude/claude_desktop_config.json (Windows: %APPDATA%\Claude\claude_desktop_config.json) and restart the app. Give the full path to node, because the app does not see your shell's PATH.

{
  "mcpServers": {
    "radical-folder": {
      "command": "/usr/local/bin/node",
      "args": ["/path/to/radical.tools/apps/mcp/dist/index.js", "--folder", "/path/to/my-model"]
    }
  }
}
  • --metamodel radical|c4 picks the metamodel of a new folder (default radical). A folder with other files and no radical.md is refused.
  • Studio warns once when the server's version differs from its own; update the older one.
  • Not supported: single .radical files, driving Studio's canvas, loading a milestone over the model, clearing the model, remote HTTP connections.

Tools

GroupTools
Readget_model_summary (counts, views, sequences, milestones, the modelling rules and the metamodel rules) · get_issues · search_model (LIST NODES WHERE …, GET NEIGHBORS, LIST SEQUENCES) · get_selection · get_changes
Elements & relationsadd_node, update_node, delete_node, move_node · add_relation, update_relation, delete_relation
Viewscreate_view, update_view, set_view_nodes, order_views, delete_view · smart_layout · align_nodes, grid_nodes, remove_alignment
Sequences & slidescreate_sequence, update_sequence, delete_sequence · create_presentation, update_presentation, delete_presentation (a slide shows a view or zooms onto elements with focus, from the model or a milestone)
Milestoneslist_milestones, create_milestone, update_milestone, delete_milestone, compare_milestones
Metamodelupsert_node_type, delete_node_type, upsert_relation_type, delete_relation_type, upsert_viewpoint, delete_viewpoint
Radical Forgeforge_start · forge_clarify → forge_generate (with forge_propose_refinement → forge_answer_refinement when a stage finds what an earlier one lacks) → forge_complete_stage → forge_arrange, per stage · forge_wireframe · forge_import_hub_concept · forge_finish
  • Writes go through the same schemas and metamodel rules as Studio. An invalid parent, type or pair is refused with a message; warnings come back with the result. A tool reports success only after the files are written.
  • A reference such as a transition's event takes an element's id, or a tempId from the same session.
  • Changing a built-in metamodel saves a -custom copy and re-announces the tools with the new types.
  • The server keeps a Forge run in .radical/forge-run.json, and refuses direct writes to earlier stages while a proposal waits. In Claude Code, /mcp__radical-folder__forge starts a run.

Editing beside an agent

Studio and an agent can work on one folder at the same time; neither overwrites the other.

  • Turns. After each write the server marks the folder as being written (.radical/agent-activity.json) for 15 seconds. Studio holds its saves meanwhile, keeps your edits on top of the agent's, and saves them when the agent pauses. A reload keeps them in the browser until the folder has them.
  • Merges. Changes are merged element by element and field by field. Where both sides changed one value, what is in the folder is kept and a notice names it. What one side deleted stays deleted, with what the other side built on it, and the notice names that too. Two agents on one folder take turns through .radical/write.lock.
  • What stays. An agent's change leaves your view, selection, camera and milestone as they were. While you drag, the change waits for the drop; while a presentation plays, until it stops.
  • Undo. Your Undo and Redo take back your own steps only. Where a step meets a value or an element the agent changed since, the agent's version stays and a notice names it.
  • Files. A file that does not read as a model (conflict markers, a trailing comma) is never merged over: Studio says which file and saves nothing until it reads again.

File formats

.radical (JSON)

One file: nodes, relations, sequences, views (positions, camera and layout constraints per view), defaultEdgeStyle, snapshots (milestones), presentations, the metamodel and Hub template records. Older .c4.json files open unchanged.

Markdown folder

my-model/
├─ radical.md                 # manifest
├─ nodes/
│  ├─ retail-customer.md       # one element = one file
│  └─ core-banking-platform/   # an element with children becomes a directory
│     ├─ _index.md             # the element itself
│     └─ payments-service/
│        ├─ _index.md
│        └─ fx-engine.md
├─ relations.json
├─ views.json · sequences.json · snapshots.json · presentations.json
├─ metamodel.json · hubTemplates.json
├─ _layout.json               # positions, camera, line style — the only noisy file
├─ check.json                 # optional: rule settings for radical check and the Inspector
└─ .radical/                  # editor state, kept out of git by its own .gitignore
   ├─ selection.json          # what is selected in Studio, for the MCP server
   ├─ base.json               # the model where the branch left main
   ├─ forge-run.json          # where an agent's Forge run stands
   ├─ agent-activity.json     # an agent is writing
   └─ test-results.json       # test cases from the last radical check --report
  • Each .md has YAML front-matter (id, type, label, then the properties, sorted) and the description as body. Hierarchy is the directory tree.
  • Output is deterministic: sorted keys, stable file names. A file is named after its element and keeps its name until the element is renamed or moved; two of one name are orders-db.md and orders-db-2.md.
  • Edit the files by hand or through the MCP server; Studio picks them up and merges what you have not saved yet. A file with a byte-order mark reads as any other.

Keyboard shortcuts

KeysAction
⌘/Ctrl+PQuick Search (and AI prompt)
Tab / ⌘/Ctrl+EnterIn Quick Search: switch to AI mode / send to AI
⌘/Ctrl+Z · ⌘/Ctrl+⇧+ZUndo · Redo (Designer)
The special key: Alt/⌥ (Settings → Special key)Held with an element selected: mark where a relation from it, or nesting, can go
Special key + drag from an elementConnect it (or the selected elements) to another, or nest them there, on a pill; to the empty canvas: take them out of their container (those the metamodel keeps there are named). One step for Undo; in Viewer and Presenter it only selects
Special key + drag a relation's endMove the end, keeping the relation's type
Special key + clickAdd an element to the selection, or take it out
Special key + drag on the backgroundSelect with a box
Special key + drop from the paletteAdd the element without its wizard
⌘/Ctrl + dragDrag with the live physics making room
Double-click an element, relation or rowOpen its properties card (a click only selects; an open card follows the selection)
F2Rename the selected row in place (a table, Warnier)
DeleteDelete the selection (Designer; fn+⌫ on a Mac)
Double-click the empty canvasNew Software System at the pointer
EscCancel a connection, close dialogs, leave edit mode, stop the presentation; go up a level in a Hierarchy view
F5Start / stop the presentation
→ ↓ Space · ← ↑Next · previous slide
Alt+← / Alt+→Back / forward (⌘+[ / ⌘+] on a Mac)
⌘/Ctrl++ / − · ⌘/Ctrl+0Zoom in / out · fit (Flow views)
⌘/Ctrl+EnterIn a wizard: create the element (Esc discards it)
EnterConfirm inline edits (names, notes, table cells)

The Warnier view's outline keys are in the guide.

Install & build

VS Code extension

The Radical.Tools extension opens .radical files in a Radical.Tools editor inside VS Code, keeps the file and the editor in sync both ways, and follows the editor's theme. Commands: Radical.Tools: Open current file, Open app, Stop and Show output log. Markdown folders open in Studio, not in VS Code.

Desktop app and a clone

# Node.js 20.11 or newer
git clone https://github.com/radicaltools/radical.tools.git
cd radical.tools
npm install
npm run dev                          # Electron, hot reload
npm run build && npm start           # desktop app
npm run dist                         # packaged desktop app
npm run dev:web                      # browser build of Studio
npm run dev:hub                      # Concern Hub
npm run build -w @radicaltools/mcp   # MCP server:  node apps/mcp/dist/index.js --folder …
npm run build -w @radicaltools/cli   # radical:     node apps/cli/dist/index.js check …
npm test                             # unit tests of every workspace
npm run e2e                          # browser tests
npm run check:architecture           # radical check on this repository's own model

The desktop app adds native file dialogs, Markdown folders without browser permissions and --file watching (or the RADICAL_FILE variable). Everything else is identical to the browser build. Studio, the desktop app, the VS Code extension, the MCP server and the command line share one version; a build that is not a release shows the commit after it.