Shape is a typed architecture conformance language for making architectural claims explicit and checkable.
Application code can be messy, implicit, and spread across many files. Shape gives the system a small human-readable model in .shape files:
- resources, traits, and invariants
- components, ownership, capabilities, and structural relations
- function effect summaries with source evidence
- model updates for architecture changes
- coverage rules for governed source paths
- bindings that require paired review-surface changes, such as docs updates
- typed design memory for refactor-sensitive functions
- constrained project rules such as hypercycle bans over the structural hypergraph
The checker does not prove the application implementation is correct. It checks that the declared architecture model is coherent. That is the product boundary: humans and LLMs write reviewable claims, then a deterministic checker accepts or rejects those claims.
Install the released shp typechecker binary. Pin the version in scripts and CI so checks are reproducible.
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/timbrinded/shapelang/releases/download/v0.4.0/install.sh | shOn Windows:
irm https://github.com/timbrinded/shapelang/releases/download/v0.4.0/install.ps1 | iexRun the checker from a repo that contains Shape files:
shp check
shp fmt --check
shp coverage --changed-files changed.txt
shp memory
shp obligationsFor local developer installs, update the released binary explicitly:
shp update
shp update --dry-runshp update --path PATH can replace a custom install path, but an existing target
must already identify itself as the Shape CLI and report a valid version.
shp check scans these paths when no files are provided:
shape/**/*.shape
In GitHub Actions, install the same pinned release with the setup action:
steps:
- uses: actions/checkout@v4
- uses: timbrinded/shapelang@v0.4.0
- run: shp checkManual archive downloads are available on the GitHub release if you do not want to run the installer script.
The first core use case is append-only resource protection.
If a resource is declared AppendOnly, then a function that emits HardDelete<Resource> is rejected even if the component grants that effect. Final forbids win over grants.
Shape also covers:
- unknown effects in protected components
- missing grants for declared function effects
- governed source files changed without a Shape update or current attestation
- Shape-affecting files changed without a bound docs update or
docs_not_neededattestation - refactor-sensitive functions changed without a recorded reevaluation
- required design context or descriptions missing from non-obvious function shapes
- semantic hypercycles in the structural hypergraph with witness paths
- project-specific rules like "only Gateway may provide JsonRpcEndpoint", expressed over
providesrelation hyperedges - optional analyzer hints for obvious
DELETE,TRUNCATE, andDROPoperations
See Refactor Constraints for the design-memory workflow around rationale, memory, and reevaluation.
Shape files use the .shape extension. This example declares an append-only audit resource and two allowed functions:
module audit
trait AppendOnly<T: Resource> {
allow Append<T>
allow Read<T>
forbid final DropStorage<T>
forbid final HardDelete<T>
forbid final Truncate<T>
}
resource AuditEvent : AppendOnly
component AuditStore {
owns AuditEvent
grants Append<AuditEvent>
grants Read<AuditEvent>
fn appendEvent
source ts("src/audit/store.ts#appendEvent")
effects complete {
Append<AuditEvent>
evidence ts("src/audit/store.ts:8-14")
}
fn listEvents
source ts("src/audit/store.ts#listEvents")
effects complete {
Read<AuditEvent>
evidence ts("src/audit/store.ts:18-25")
}
}
A source-backed model update can add a new function directly to the global Shape model:
module audit
component AuditStore {
grants HardDelete<AuditEvent>
fn purgeOldEvents
source ts("src/audit/purge.ts#purgeOldEvents")
effects complete {
HardDelete<AuditEvent>
evidence ts("src/audit/purge.ts:12-16")
}
}
That model update fails because AuditEvent : AppendOnly derives a final forbid for HardDelete<AuditEvent>.
The checker pipeline is:
- Parse
.shapefiles with Langium. - Lower declarations into facts such as resources, traits, effects, grants, relation hyperedges, and governed paths.
- Evaluate deterministic rules.
- Emit diagnostics with provenance, including the declarations that caused a violation.
The optional analyzer is advisory only: it can flag suspicious omissions, but .shape remains the source of truth.
shp check
shp check --changed-files changed.txt
shp coverage --changed-files changed.txt
shp fmt --check
shp explain AuditEvent
shp graph show Gateway --kind calls
shp graph stats --kind calls
shp memory
shp obligations
shp analyze --shape-files fixtures/pass/append_only_append/audit.shape src/audit/purge.ts
shp ast source --language rust --module generated.audit src/audit/store.rs
shp ast json --module generated.audit --raw-out ast.raw.shape ast.json
shp update --dry-runshp check scans shape/**/*.shape when no files are provided. Any .shape file under shape/ is part of the checked model.
Useful commands:
shp check: run conformance checks.shp coverage --changed-files changed.txt: enforce Shape updates or current attestations for governed paths.shp check --changed-files changed.txt: run semantic checks, coverage, and bindings together.shp fmt --check: verify canonical formatting.shp explain AuditEvent: show derived facts and incident relations for a symbol.shp graph all [--kind KIND]: print the whole hypergraph grouped by kind.shp graph show SYMBOL [--kind KIND]: print the hyperedges incident to a component or resource.shp graph stats [--kind KIND]: print aggregate vertex, hyperedge, and incidence counts.shp memory: list rationale and memory entries that protect design context.shp obligations: list open design-memory obligations such as missing rationale or reevaluation.shp analyze --shape-files fixtures/pass/append_only_append/audit.shape src/file.ts: compare obvious source hints against declared effects.shp ast source [--language LANG] [--module NAME] src/file.rs: parse source with Tree-sitter and print a conservative Shape draft with compact AST anchors and semantic fingerprints.shp ast json [--module NAME] [--include-ast-layer] ast.json: read normalized AST JSON from another parser, with raw AST resources opt-in.shp update: update a local released binary from GitHub Releases.
shape/
checker.shape
delivery.shape
language.shape
tooling.shape
fixtures/
pass/
fail/
packages/
shp-checker/
shp-cli/
docs-site/
src/content/docs/
The implementation currently lives in two packages:
@shape/shp-checker: parser, formatter, fact lowering, rule checks, authoring helpers, editor primitives, and analyzer hints.@shape/shp-cli: command-line wrapper around the checker package.
The Starlight documentation site lives in docs-site/ and is configured for static publishing under /shapelang/.
Use the Bun workspace only when contributing to Shape itself:
bun install --frozen-lockfile
bun run langium:generate
bun shp check
bun run changed-files
bun run shape:ci
bun test
bun run typecheck
bun run docs:checkRun the docs site locally:
bun run docs:devBuild release archives locally:
bun run build:releaseRelease archives are written under dist/release/, which is ignored by git.
Each archive includes the shp executable, LICENSE, and bundled Tree-sitter parser assets used by shp ast source for TypeScript, TSX, JavaScript/JSX, Rust, Go, and Python.
Before opening changes, run the local development checks. Documentation changes should keep complete shape code fences parseable; use shape no-verify only for intentional fragments. CLI behavior changes should update the README, docs quickstart, and CLI reference together.
The docs site is configured for GitHub Pages at https://timbrinded.github.io/shapelang/.
GitHub Pages should use the GitHub Actions publishing source. The deployment workflow builds docs-site, uploads docs-site/dist, and publishes the artifact with the Pages deployment actions.
CI is wired in .github/workflows/shape.yml for generated AST freshness, formatting, tests, typechecking, shp check --changed-files changed.txt, Shape coverage/bindings, and docs checks. Governed source changes require a faithful shape update or a narrow current attestation; bound docs surfaces must change unless a current docs_not_needed attestation explains why not.
Releases are built from version tags:
git tag v0.4.0
git push origin v0.4.0The release workflow validates the repo, cross-compiles shp for the native parser target matrix, publishes tarballs as GitHub release assets, and includes SHA-256 checksums. The current matrix is Linux x64, Linux ARM64, macOS ARM64, and Windows x64.
Other GitHub Actions workflows can install shp with the setup action shown in Quick Start. Use with.version to install a different release than the action ref:
- uses: timbrinded/shapelang@master
with:
version: v0.4.0BSD 3-Clause
