Skip to main content

Desktop-first Enterprise Capability Model studio with Git-managed JSONL storage.

Project description

ECM Studio

PyPI Python Publish License: MIT

ECM Studio is a Windows-first desktop application for managing an Enterprise Capability Model as local, Git-managed JSONL files. It gives architects and capability owners a focused workspace for editing capability trees, reviewing change history, publishing model snapshots, and exporting portable artifacts without putting the authoritative model in a database.

ECM Studio screenshot

Highlights

  • Desktop UI built with React, Dockview, Fluent UI, and pywebview.
  • Durable model storage in readable JSONL files under ecm/.
  • Git-native workflow for checkpoints, scenarios, merges, restore, pull, and push.
  • SQLite projection rebuilt locally for navigation and search speed.
  • Capability map view with SVG and HTML export.
  • Direct structural operations for retire, merge, and controlled Draft leaf delete.
  • Model import/export for JSONL, CSV, and bundled JSON.
  • Release workflow for tagged ECM model exports and GitHub release publication.
  • Light/dark theme support with native Windows chrome integration.

Install

ECM Studio requires Python 3.13 or newer. Install it from PyPI:

pip install ecm-studio

On Windows, if pip points at a different Python installation, use the Python launcher instead:

py -m pip install ecm-studio

With uv, install ECM Studio as a command-line tool:

uv tool install ecm-studio

Or install it into the current uv-managed environment:

uv pip install ecm-studio

Start the desktop app:

ecms

Open a workspace directly:

ecms C:\path\to\capability-model-repo

Check the installed package version:

ecms --version

Workspace Model

An ECM Studio workspace is a normal Git repository. The application stores the authoritative model in ecm/*.jsonl files and keeps local runtime state in .ecm-studio/, which should stay ignored by Git.

The SQLite database is only a local projection. It can be rebuilt from JSONL at any time and is not the source of truth.

Common Workflows

Open Or Create A Workspace

Use the workspace panel to open an existing Git-backed ECM repository or create a new one. ECM Studio writes the model to ecm/*.jsonl, rebuilds the local SQLite projection for search and navigation, and keeps runtime files under .ecm-studio/.

Bootstrap An Existing Model

Many teams already have a capability model in a spreadsheet, architecture tool, or another repository. To bootstrap ECM Studio, first create or open the target workspace, then convert the existing model to CSV, JSONL, or bundled JSON and use the Import / Export panel.

Recommended first import flow:

  1. Prepare stable capability IDs. Use short durable IDs from the source system when possible, because parent_id and replacement_capability_id depend on those IDs.
  2. Put top-level capabilities first when producing CSV or JSONL. The importer validates by ID rather than row order, but parent-first files are easier to inspect and review.
  3. Choose Validate only and preview the file. Fix duplicate IDs, duplicate names, missing parents, and hierarchy cycles before applying.
  4. Choose the apply mode. Use Replace current model for the first load of a new ECM Studio repo, Append new capabilities when adding new branches to an existing model, or Merge by ID when refreshing records from an external source while keeping the same stable IDs.
  5. Preview again in the selected apply mode, then apply the import. ECM Studio writes ecm/capabilities.jsonl, records a model import event, rebuilds the SQLite projection, and refreshes the workspace views.

If the workspace is already a Git repository, replace and merge-by-ID imports create a pre-import checkpoint before writing the imported model.

Bootstrap Schema

JSONL imports use one capability object per line. Bundled JSON imports use the same capability objects inside a wrapper:

{
  "_t": "ecm_model_bundle",
  "schema_version": "1.0",
  "capabilities": []
}

CSV imports support the common bootstrap columns listed below. For JSONL and bundled JSON, the same fields are accepted as JSON object properties, with aliases, tags, and source_references represented as arrays. JSON imports reject unknown fields so schema mistakes fail during preview.

Field Required CSV Notes
_t No Filled by importer Use capability when present in JSONL or bundled JSON.
schema_version No Filled by importer Use 1.0 when present in JSONL or bundled JSON.
id No Yes Stable unique ID. Generated when omitted.
name Yes Yes Capability names must be unique after trimming and case normalization.
parent_id No Yes Parent capability ID. Blank means top-level capability.
order No Yes Non-negative sibling order. Defaults to 0 when omitted.
domain No Yes Free-text business or architecture domain.
type No Yes leaf or abstract; imported value is recomputed from hierarchy.
lifecycle_status No Yes Draft, Active, Deprecated, or Retired. Defaults to Draft.
description No Yes Free-text description.
aliases No Yes CSV accepts semicolon- or comma-separated aliases. JSON uses an array.
tags No Yes CSV accepts semicolon- or comma-separated tags. JSON uses an array.
steward_id No Yes Owner or steward identifier.
steward_department No Yes Steward organization or department.
replacement_capability_id No Yes Successor capability ID for retired or merged capabilities.
effective_from No JSON only ISO-style date or timestamp for when the capability became effective.
effective_to No JSON only ISO-style date or timestamp for retirement or end of validity.
rationale No JSON only Reason for the current lifecycle or structural state.
source_references No JSON only Array of source-system links, IDs, or references.
created_at No JSON only Timestamp generated when omitted.
updated_at No JSON only Timestamp generated when omitted.

Minimal CSV example:

id,name,parent_id,order,domain,type,lifecycle_status,description,aliases,tags,steward_id,steward_department,replacement_capability_id
cap-payments,Payments,,0,Banking,abstract,Active,Payment capabilities,Payments Hub;Pay,finance,owner-123,Banking,
cap-domestic-payments,Domestic Payments,cap-payments,0,Banking,leaf,Active,Domestic clearing and settlement,Local transfers,finance,owner-123,Banking,

Minimal JSONL example:

{"_t":"capability","schema_version":"1.0","id":"cap-payments","name":"Payments","parent_id":null,"order":0,"domain":"Banking","lifecycle_status":"Active","description":"Payment capabilities","aliases":["Payments Hub","Pay"],"tags":["finance"],"steward_id":"owner-123","steward_department":"Banking"}
{"_t":"capability","schema_version":"1.0","id":"cap-domestic-payments","name":"Domestic Payments","parent_id":"cap-payments","order":0,"domain":"Banking","lifecycle_status":"Active","description":"Domestic clearing and settlement","aliases":["Local transfers"],"tags":["finance"],"steward_id":"owner-123","steward_department":"Banking"}

Add Or Edit Capabilities

Create capabilities from the tree, then use the inspector to edit descriptive fields, lifecycle status, parent placement, aliases, and external references. Capability type is derived from hierarchy: capabilities with children are abstract, and capabilities without children are leaves. When edits change that derived type, ECM Studio records promote or demote audit events.

Retire A Capability

Select a capability and choose Retire from the inspector's structural actions. Provide a rationale, optionally choose a replacement capability, and capture any downstream handling notes. Retiring sets the capability lifecycle to Retired, sets an effective end date, stores the rationale in audit history, and preserves replacement_capability_id when a replacement is selected.

Use an optional replacement when the capability should no longer be used but there is a clear successor that consumers should move to. The replacement link is useful because it gives architects, reviewers, search users, and downstream consumers an explicit redirect from the retired capability to the active one. That keeps historical references understandable, makes migration decisions auditable, and avoids leaving teams to infer the intended successor from names or notes. Leave it blank when the capability is ending without a direct successor.

Merge Duplicate Capabilities

Select the duplicate source capability and choose Merge. Pick the survivor, enter a rationale, and capture downstream handling notes. ECM Studio moves the source children under the survivor, folds the source name and aliases into the survivor aliases, and prevents merge targets that would create a hierarchy cycle.

Draft sources are removed after the merge. Non-Draft sources remain in the model as Retired records with replacement_capability_id pointing at the survivor, so historical references still have a visible redirect.

Delete An Erroneous Draft Leaf

Use Delete Draft only for capabilities that are both Draft and leaf nodes. ECM Studio rejects delete attempts for non-Draft capabilities or capabilities with descendants. Deleting requires a rationale, records audit evidence, removes the capability from JSONL, rebuilds SQLite, and refreshes the UI.

Review, Checkpoint, And Publish

Review the audit panel after structural changes. It shows direct actions such as retire, delete, and merge, plus derived promote and demote events when hierarchy changes alter capability type. Run diagnostics, create a Git checkpoint, and use the release workflow or JSONL, CSV, bundled JSON, SVG, and HTML exports when the model is ready to share.

Development

Install Python and frontend dependencies:

py -m pip install -e .[dev]
npm install --prefix ui

Run the Vite dev server and launch the desktop shell against it:

npm run dev --prefix ui
py -m ecm_studio --dev-ui http://localhost:5173

Build the frontend assets:

npm run build --prefix ui

Run checks:

ruff check src tests scripts
pytest -q
npm run lint --prefix ui
npm test --prefix ui
npm run typecheck --prefix ui

Packaging And Releases

The Python package uses Hatchling and reads its version from src/ecm_studio/__init__.py.

Cut a release from a clean working tree:

python scripts/release.py 0.1.1
git push origin master v0.1.1

The publish.yml workflow builds the React UI, stages it into the wheel, checks the distribution with Twine, verifies packaged UI assets, and publishes tagged v* releases to PyPI through trusted publishing.

Open the next development cycle after a release:

python scripts/release.py --post-release 0.1.2.dev0

License

ECM Studio is released under the MIT License.

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

ecm_studio-0.4.0.tar.gz (1.2 MB view details)

Uploaded Source

Built Distribution

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

ecm_studio-0.4.0-py3-none-any.whl (843.8 kB view details)

Uploaded Python 3

File details

Details for the file ecm_studio-0.4.0.tar.gz.

File metadata

  • Download URL: ecm_studio-0.4.0.tar.gz
  • Upload date:
  • Size: 1.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ecm_studio-0.4.0.tar.gz
Algorithm Hash digest
SHA256 94a6aaf89ad5adb214caa16c23211418293517c4cce6c6265e463d18d970240b
MD5 80d4edd027d7210d35ca713d347d7288
BLAKE2b-256 48fa2f0714abef1039dde66fd9f0c95ac8258f14583c71f7c074eee8d374567b

See more details on using hashes here.

Provenance

The following attestation bundles were made for ecm_studio-0.4.0.tar.gz:

Publisher: publish.yml on ThomasRohde/ecm-studio

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

File details

Details for the file ecm_studio-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: ecm_studio-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 843.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ecm_studio-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 43d06f7c1e181ae4daed01c0dfe02b7d58b07adc51e3ad0eafe778a0780142e2
MD5 1a38e4706d76b8151b98287306347344
BLAKE2b-256 86ad7d5a33773b52538be43009310c3ae51e2b3b47ea6fd28c4a86e886e1207b

See more details on using hashes here.

Provenance

The following attestation bundles were made for ecm_studio-0.4.0-py3-none-any.whl:

Publisher: publish.yml on ThomasRohde/ecm-studio

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