Skip to main content

A text-based DSL for defining software architecture alongside code

Project description

ArchML

ArchML is a text-based DSL for defining software architecture alongside your code. Architecture files live in the repository, are version-controlled like any other source file, and stay in sync with the system they describe.

The core idea: define your architecture once as a model, then derive multiple views from it — interactive web diagrams, consistency reports, and embedded Sphinx documentation — without maintaining separate diagrams per tool.

Why ArchML?

Architecture documentation drifts. Visual tools like Enterprise Architect or ArchiMate live outside the codebase, so diagrams rot while the code moves on. Lightweight alternatives like Mermaid embed diagrams in Markdown, but each diagram is standalone — there is no shared model, no cross-diagram consistency, and no drill-down navigation.

ArchML sits between these extremes:

  • Text-first.archml files are plain text, stored in git, reviewed in pull requests.
  • Model-based — one model, many views. Define a component once; reference it everywhere.
  • Consistency checking — the tooling catches dangling references, ports missing connect or expose, and type mismatches across channels.
  • Navigable views — drill down from system landscape to individual component internals.
  • Sphinx-native — embed live architecture views directly in your documentation.

Quick Example

A small e-commerce backend expressed in ArchML:

// types.archml

type OrderItem {
    field product_id: String
    field quantity:   Int
    field unit_price: Decimal
}

enum OrderStatus {
    Pending
    Confirmed
    Shipped
    Delivered
    Cancelled
}

interface OrderRequest {
    field order_id:   String
    field customer_id: String
    field items:      List<OrderItem>
}

interface OrderConfirmation {
    field order_id:     String
    field status:       OrderStatus
    field confirmed_at: Timestamp
}

interface PaymentRequest {
    field order_id: String
    field amount:   Decimal
    field currency: String
}

interface InventoryCheck {
    field product_id: String
    field quantity:   Int
}
// systems/ecommerce.archml
from types import OrderRequest, OrderConfirmation, PaymentRequest, InventoryCheck

system ECommerce {
    title = "E-Commerce Platform"
    description = "Customer-facing online store."

    user Customer {
        provides OrderRequest
        requires OrderConfirmation
    }

    component OrderService {
        title = "Order Service"
        description = "Accepts, validates, and processes customer orders."

        component Validator {
            requires OrderRequest
            provides ValidationResult
        }

        component Processor {
            requires ValidationResult
            requires PaymentRequest
            requires InventoryCheck
            provides OrderConfirmation
        }

        // Internal wiring: Validator feeds Processor via an implicit channel
        connect Validator.ValidationResult -> $validation -> Processor.ValidationResult

        // Remaining ports must be explicitly exposed at the OrderService boundary
        expose Validator.OrderRequest
        expose Processor.PaymentRequest
        expose Processor.InventoryCheck
        expose Processor.OrderConfirmation
    }

    component PaymentGateway {
        title = "Payment Gateway"
        tags = ["critical", "pci-scope"]

        provides PaymentRequest
    }

    component InventoryManager {
        title = "Inventory Manager"

        provides InventoryCheck
    }

    // Wire customer to order pipeline
    connect Customer.OrderRequest -> $order_in -> OrderService.OrderRequest
    connect OrderService.OrderConfirmation -> $order_out -> Customer.OrderConfirmation

    // Wire OrderService to backing services
    connect PaymentGateway.PaymentRequest -> $payment -> OrderService.PaymentRequest {
        protocol = "gRPC"
        async = true
    }
    connect InventoryManager.InventoryCheck -> $inventory -> OrderService.InventoryCheck {
        protocol = "HTTP"
    }
}

Large architectures split naturally across files. A from ... import statement brings named definitions into scope; use component X places an imported component inside a system without redefining it. Its exposed ports are available as Entity.port_name in connect and expose statements. Remote repositories can be referenced with @repo-name prefixes for multi-repo workspace setups.

Language at a Glance

Keyword Purpose
system Group of components or sub-systems with a shared goal
component Module with a clear responsibility; may nest sub-components
user Human actor (role or persona) that interacts with the system
interface Named contract of typed data fields; supports @v1, @v2 versioning
type Reusable data structure (used within interfaces)
artifact Abstract data artifact (file, directory, blob, etc.) used as a field type
enum Constrained set of named values
field Named, typed data element with optional description and schema
requires / provides Declare a port that consumes or exposes an interface
requires X as port Assign an explicit name to a port
connect A.p -> $ch -> B.p Wire two ports via a named implicit channel
connect A.p -> B.p Wire two ports directly (no named channel)
expose Entity.port [as name] Explicitly surface a sub-entity's port at the enclosing boundary
external Marks a system, component, or user as outside the development boundary
from … import Bring specific definitions from another file into scope
use component X Place an imported entity inside a system
tags Arbitrary labels for filtering and view generation

Primitive types: String, Int, Float, Decimal, Bool, Bytes, Timestamp, Datetime Container types: List<T>, Map<K, V>, Optional<T>

Multi-line descriptions use triple-quoted strings:

description = """
Accepts and validates customer orders.
Delegates payment to PaymentGateway.
"""

Enum values each occupy their own line — no commas needed.

Full syntax reference: docs/LANGUAGE_SYNTAX.md

Installation

pip install archml

Or with uv:

uv add archml

Commands

archml init <name> <directory>

Initialize a new ArchML workspace. Creates .archml-workspace.yaml in the given directory with <name> as the workspace identity.

archml init my-service .

archml check [directory]

Parse and validate all .archml files in the workspace. Reports dangling references, unused interfaces, and other consistency errors. Exits with a non-zero status if any errors are found.

archml check
archml check /path/to/workspace

archml visualize <entity> <output> [directory]

Render a box diagram for a system or component and write it to a file. The entity path uses :: as a separator for nested elements.

archml visualize ECommerce diagram.svg
archml visualize ECommerce::OrderService order_service.png

[!NOTE]
This command exists, but is not yet working properly.


archml serve [directory]

Launch an interactive web-based architecture viewer. Opens a browser UI for exploring the full architecture with drill-down navigation.

archml serve
archml serve --port 9000
archml serve --host 0.0.0.0 --port 8080

[!NOTE]
This command exists, but is not yet working properly.


archml update-remote [directory]

Resolve branch or tag references in the workspace configuration to their latest commit SHAs and write them to the lockfile (.archml-lock.yaml). Run this to update pinned revisions.

archml update-remote

archml sync-remote [directory]

Download remote git repositories to the local sync directory at the commits pinned in the lockfile. Run update-remote first if the lockfile does not exist yet.

archml sync-remote

Project Status

ArchML is in early development. The functional architecture domain (systems, components, interfaces, ports, and channels) is implemented. Behavioral and deployment domains are planned.

See docs/PROJECT_SCOPE.md for the full vision and roadmap.

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

archml-0.1.0.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

archml-0.1.0-py3-none-any.whl (1.3 MB view details)

Uploaded Python 3

File details

Details for the file archml-0.1.0.tar.gz.

File metadata

  • Download URL: archml-0.1.0.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for archml-0.1.0.tar.gz
Algorithm Hash digest
SHA256 32269c23b6c17fdcbc3fec68593a7886894fc8dfad7f86d64dd5e399afb63914
MD5 1c704652e5dfd5636b85088e1bd01f73
BLAKE2b-256 f17f5e7ee22158d4cfaa49ff95c5914844ba4883b5043eec9809c477d48ea7a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for archml-0.1.0.tar.gz:

Publisher: publish.yml on amhellmund/archml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file archml-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: archml-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for archml-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 71ebc83d0b67a4fc66311c0df6f35f879fddd09b10d619590bcdc9ee4517a18d
MD5 d78241642cd44a486c975024c741d62b
BLAKE2b-256 faf1fcb6a2a73465d813b1e9ff14e15f0ef4dd8b547689367231335f8f721360

See more details on using hashes here.

Provenance

The following attestation bundles were made for archml-0.1.0-py3-none-any.whl:

Publisher: publish.yml on amhellmund/archml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page