dependra
v1.7.0
Published
The Dependra CLI: init a repo, validate + bundle its `.dependra/` manifest, and run the local manifest-authoring MCP. One package, subcommands `init` / `validate` / `bundle` / `mcp`. Also runs inside the Dependra GitHub Action.
Downloads
1,815
Readme
dependra — the Dependra manifest CLI
Declare your architecture where it actually lives — in the repository, next to the code — in a
committed .dependra/manifest.yaml, then sync it to your Dependra landscape. This package is the
authoring toolchain: scaffold a repo, wire a coding agent to a local manifest-authoring MCP,
and validate + bundle the manifest before it syncs.
Everything ships in a single, unscoped npm package — dependra (bin dependra). Run it with
npx; there is nothing to add to your repo — no node_modules, no devDependency.
npx dependra init # wire your agent (local MCP + skill) + scaffold .dependra/manifest.yaml
npx dependra github # GitHub users: scaffold .github/workflows/dependra-sync.yml
npx dependra validate .dependra/manifest.yaml # full layered validation (schema + refs + uniqueness)
npx dependra bundle .dependra/manifest.yaml # preview the { manifest, docs, hashes } transport bundleOnce your manifest is authored and validated, GitHub users add the upload-manifest Action
(dependra-io/upload-manifest@v1) to sync it on every merge and release — see
Syncing from GitHub. The result is a self-maintaining landscape: the
manifest proposes changes at the speed of your codebase, and your team approves them in the same PR
flow.
What's in this repo
This repository is the dependra package at its root. Notable pieces:
| Path | What it is |
| --- | --- |
| src/ | The CLI + the local manifest-authoring MCP server (src/mcp). Path-sandboxed, layered validation. The same core is also bundled into the upload-manifest Action. |
| schema/ | The versioned manifest contract (JSON Schema draft 2020-12) that every piece keys off, plus its snapshot tests. |
| skill/ | The authoring skill (SKILL.md) + wiring (SETUP.md) that point an agent at dependra mcp. init/setup install it. |
| examples/ | A complete golden repo: manifest, referenced docs, in-place README, and the consumer workflow dependra github scaffolds. |
| docs/onboarding.md | The ordered path from an empty repo to a synced landscape in under 30 minutes. |
New here? Start with docs/onboarding.md.
The .dependra/ layout
Your repo carries its landscape in a top-level .dependra/ folder:
your-repo/
├─ .dependra/
│ ├─ manifest.yaml # the root manifest (this is what gets synced)
│ └─ docs/ # curated Markdown referenced from the manifest via file: refs
│ └─ orders.md
├─ .github/
│ └─ workflows/
│ └─ dependra-sync.yml # the consumer workflow (scaffolded by `dependra github`)
└─ README.md # a service README can be referenced in place — no copyThe golden version of this layout lives under examples/.
Manifest format overview
The manifest is a single YAML document (optionally split via include:) describing the
architecture this repo implements. Full contract: schema/README.md.
# yaml-language-server: $schema=https://dependra.io/schema/manifest/v1/manifest.schema.json
schemaVersion: "1.0.0"
tenant: acme
applications:
- id: orders
name: Orders Platform
description: Revenue-critical order-capture platform. # short inline summary (string only)
documentation:
file: ./docs/orders.md # long-form / README home — takes a {file:} ref
lifecycleState: production
criticalityTier: missionCritical
components:
- id: orders-api
name: Orders API
application: orders
description: Public REST API that accepts and orchestrates customer orders.
documentation:
file: ../README.md # README-in-place, referenced not copied
kind: webAPI
runtime: containers
dependencies:
- from: orders-api
to: orders-db
type: readsWrites
mode: hard
broker: orders-events # for messaging edges
source: authoredKey points (see the schema for the full enum tables and every field):
- The authoring dialect is friendly. Entities carry a short
id; dependency edges usefrom/to. Dependra maps this manifest dialect onto your landscape at the ingest boundary, so the friendly form round-trips cleanly — you author readable ids, not opaque ones. - Enum casing is significant —
kind: webAPI,lifecycleState: production,type: readsWrites,mode: hard, and so on. The schema README has the full tables. - Ids and
technicalNames follow^[a-z0-9][a-z0-9._-]*$and are unique within their collection.
description vs documentation, and README-in-place
description is a short inline summary (a one/two-liner) — a plain string only; a {file:}
ref is not valid on it. documentation is the README / long-form home and is the rich-text field
that accepts either an inline string or a reference to a Markdown file:
description: Public REST API that accepts customer orders. # short inline summary (string only)
documentation:
file: ../README.md # reference a service README where it already lives (path relative to THIS file)file: paths for documentation must end in .md; include: sub-manifest refs must end in .yaml
or .yml. This keeps architecture prose beside the code instead of crammed into YAML. Full rules:
schema/README.md.
Endpoints, datasets & technologies
A component can declare the endpoints it exposes, the datasets it handles, and the technologies it runs. These are what the take-inventory agent populates from your code; you can also hand-write them.
components:
- id: orders-api
name: Orders API
application: orders
kind: webAPI
# Component security posture:
egressMode: default
protectionMechanisms: [WAF, RateLimiting]
statusPageUrl: https://status.example.com
# Endpoints this component EXPOSES — its attack surface, inventoried whether or not anything
# consumes them. Each endpoint carries its own transport encryption + accepted auth methods.
endpoints:
- name: public-api
protocol: HTTPS
port: 443
transportEncryption: TLS1.3
authMethods:
- method: OAuth2
# Technologies this component runs, with the PER-COMPONENT version (multi-targeting is fine —
# the same technology can appear on many components at different versions).
technologies:
- technology: dotnet
version: "8.0"
datasets:
- id: orders-data
name: Orders Data
dataClassification: financial # pii | phi | financial | confidential | internal | public | restricted
components: [orders-api, orders-db]
# `technologies:` is a SHARED radar catalogue — identity + category only.
technologies:
- id: dotnet
name: .NET
category: platforms # languagesAndFrameworks | platforms | tools | techniquesAn endpoint is the exposed posture; a dependency edge is a specific consumer's actual connection. Both are useful — the endpoint inventory captures security-critical surface even when nothing currently consumes it. A dependency can bind to a specific target endpoint via
targetEndpoint: <endpoint-name>(paired withendpointAuthMethod).
Mastered components are reconciled to match the manifest. A component you own (top-level
components:) has its endpoints reconciled exactly to what you declare — like its dependencies. So if a component that had endpoints (e.g. added in the Dependra UI) is re-synced from a manifest that omitsendpoints:, those endpoints are removed. Declare the full set you want, or manage them in the UI — not both piecemeal.
Manifests declare FACTS, not portfolio governance. You state which technologies run where and at what version. Radar recommendations (adopt / trial / hold / retire) and EOL target dates are architecture/CIO decisions made inside Dependra — they are deliberately not declarable from a repo, so no repo can unilaterally set portfolio policy by pushing a manifest.
Editor autocomplete ($schema)
Add this as the first line of any manifest file. With the YAML Language Server (bundled with the Red Hat YAML VS Code extension) you get live validation, hover docs, and autocomplete:
# yaml-language-server: $schema=https://dependra.io/schema/manifest/v1/manifest.schema.json
schemaVersion: "1.0.0"Point $schema at the published canonical URL
https://dependra.io/schema/manifest/v1/manifest.schema.json — the authoritative schema, and what the
golden example uses. If you prefer to resolve against your
checkout instead, a relative path to an in-repo copy of the schema also works. All consumers resolve
the same version through schemaVersion.
The subcommands
initruns machine setup (below) and then scaffolds.dependra/manifest.yaml(a small, valid starter) — never overwriting an existing file. It never touches.github/. It's the fastest way to a working repo. Useinit --minimalto scaffold the manifest only (skip machine setup).setupruns machine setup only — it wires the local authoring MCP + skill and the hosted read-onlydependra-liveMCP for your coding agent, and never writes to the repo. Use it to prepare a machine without scaffolding a manifest. (No login is needed at setup time —dependra-liveresolves your login per-repo when the agent spawns it; see Machine setup below.)githubscaffolds.github/workflows/dependra-sync.yml(create-if-absent) — the only command that writes.github/. Run it if you sync from GitHub Actions; the scaffolded workflow already referencesdependra-io/upload-manifest@v1, so there's nothing to edit.validateruns the full validation (schema + referential integrity + doc-ref existence + uniqueness) — the same validation the Action runs — returning every issue withfile:line. Exit 0 = clean.bundleassembles the self-contained{ manifest, docs, hashes }transport bundle the Action ships to Dependra.mcpstarts the local manifest-authoring MCP server (stdio) a coding agent drives to author the manifest for you — seeskill/SETUP.md. It's a local authoring aid that never runs on CI.mcp --liveinstead runs the hosted read-onlydependra-liveproxy (this is whatsetupwires asdependra-live); you don't normally run it by hand.loginsigns you in through your browser (loopback + PKCE) and stores a short-lived (24h), user-scoped token per profile in~/.dependra/config.json. The token is minted invisibly and never printed; re-runloginto renew (there is no refresh token). Actions you take with it are attributed to you in the audit log. Local dev useslogin— not API keys.dependra login --profile prod --api https://dependra.io(default--apiishttps://dependra.io; for a local stack use--api http://localhost:5173). AWS-style profiles:--profile, or the sole profile, ordefault. Runninglogininside a repo also binds that repo to the profile.use <profile>binds the current repo to a login profile without re-authenticating —dependra use prod. The binding lives user-side in~/.dependra/config.json(never in the repo) and is whatdependra-liveandpushconsult to pick the right profile per repo when you work across several tenants. See Profiles & bindings below.pushvalidates + bundles.dependra/manifest.yamland applies it to Dependra. Barepushapplies;push --previewis a read-only diff (git-push mental model). Credential precedence: explicit--api-key/DEPENDRA_API_KEY(CI) → GitHub OIDC (inside Actions) → yourlogintoken. A login-token push is authorized live against your landscape-edit rights; an API key is scope-governed.
Machine setup (shared by setup and init) is user-level, idempotent, and non-destructive: it
detects Claude Code and/or Cursor and wires two stdio MCP servers into ~/.claude.json /
~/.cursor/mcp.json — preserving every other server and key — plus, for Claude Code, the authoring
skill under ~/.claude/skills/:
dependra— the local authoring MCP (npx -y dependra mcp). Edits in-repo files only (the committed.dependra/manifest + docs). No login, no network, nothing to keep running.dependra-live— the hosted, read-only MCP, wired as a stdio proxy (npx -y dependra mcp --live). Your agent re-spawns it per-repo; at spawn it resolves this repo's login profile and its current token and proxies to<apiBaseUrl>/mcp, so an agent can query your live landscape while authoring — matching existing entities and avoiding duplicate stubs.
No token is ever written into the agent config: dependra-live reads your login live on every spawn.
That's why one user-level wiring serves every tenant correctly, and why the 24h token expiry no
longer strands it — you just re-run dependra login (no setup re-run needed). If no agent is
detected, setup prints the MCP JSON snippet to paste.
Neither MCP runs on CI. The hosted
dependra-liveMCP is read-only — an agent can query the live landscape but every change still flows throughdependra push. A manifest edit is never a production change on its own; a human reviews and commits it.
Profiles & bindings (multi-tenant)
Profiles are AWS-style (dependra login --profile <name>); you can be logged into several at once. Which
profile applies in a given repo — for both dependra-live and dependra push — resolves in this order:
- explicit
--profile(push only) → 2.DEPENDRA_PROFILE→ 3. the repo's binding → - the sole profile if you have exactly one → 5.
default.
A binding maps a repo (its manifest root — the dir containing .dependra/manifest.yaml, a
VCS-agnostic anchor) to a profile name. It's set by dependra use <profile> or automatically by running
dependra login --profile <name> inside the repo, and stored user-side in ~/.dependra/config.json
— never in the repo, so nothing is committed and it works regardless of git/SVN/Vault/TFS/none. If you
only ever use one profile, you never touch any of this.
Bindings are keyed by absolute local path, so they're per-machine and don't travel with a clone — each machine binds once (like
~/.aws/configprofiles or kubectl contexts). Moving a repo directory makes its binding stale; it falls back to the default and you rebind withdependra use.
A consumer repo commits only .dependra/ (plus .github/workflows/dependra-sync.yml if you sync
from GitHub). The CLI is invoked on demand via npx (or driven by your agent as an MCP) — it is never
a committed dependency.
Syncing from GitHub
dependra github scaffolds a workflow that uses the upload-manifest Action,
dependra-io/upload-manifest@v1 — a reusable GitHub Action that validates → bundles → authenticates
→ syncs the manifest, posting a dry-run diff comment on pull requests and applying on the default
branch and releases. Its inputs, auth (GitHub OIDC or an API-key fallback), resilience, fork-PR
behaviour, and versioning are documented in the
dependra-io/upload-manifest repository.
The minimal shape (already scaffolded for you):
permissions:
id-token: write # mint the OIDC token exchanged for a scoped Dependra key
contents: read # check out the manifest
pull-requests: write # post the dry-run diff comment on PRs
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dependra-io/upload-manifest@v1
with:
tenant-id: ${{ vars.DEPENDRA_TENANT_ID }}On GitLab or another CI, run npx dependra validate then npx dependra bundle and POST the bundle to
the tenant-addressed ingest endpoint yourself. The manifest itself is portable — only the sync
mechanism differs.
The Action bundle (for maintainers)
This repository is the source of truth for the CLI bundle the upload-manifest Action ships.
npm run bundle produces a single-file esbuild bundle of src/action.ts
(the Action's dedicated entry — re-exporting only runValidate/runBundle/hasErrors, with the MCP
SDK tree-shaken out) plus the co-located schema, written to action-vendor/. The build is
deterministic (idempotent). On release a maintainer copies action-vendor/manifest-cli.mjs +
action-vendor/manifest.schema.json into the upload-manifest repo's root vendor/ and commits them
there.
Capabilities and limits
Be precise about what a passing sync means today:
- Structural freshness — now. You (or a coding agent) author the manifest, and it syncs at the speed of your codebase. Every change lands as a reviewable diff: a dry-run PR comment before merge, an apply on the default branch / release. Your team approves the change in the same PR flow as the code that motivated it. The landscape stays as fresh as the manifest you keep committed.
- Semantic auto-detection — on the roadmap. Automatically inferring dependencies and
components from code analysis is on our roadmap; it is not available today. The schema already
reserves the fields for it (
source: authored | ci-derived, plusconfidence), so adopting it later won't require a schema change — but for now, every edge you sync isauthored.
A green check means "the authored manifest validated and synced" — not "your landscape was auto-discovered and is provably complete." Don't read the check as full semantic sync. Dependra proposes changes at the speed of your codebase; your team approves them.
Learn more at dependra.com.
