stackcanvas 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# stackcanvas
|
|
2
2
|
|
|
3
|
-
Live infrastructure canvas for [Claude Code](https://claude.com/claude-code).
|
|
3
|
+
Live infrastructure canvas for AI coding agents — any agent that speaks [MCP](https://modelcontextprotocol.io) ([Claude Code](https://claude.com/claude-code) is the CI-verified path).
|
|
4
4
|
The agent writes and plans your Terraform — stackcanvas shows it as a living
|
|
5
5
|
diagram. Drag new resources onto the canvas; the agent turns them into
|
|
6
6
|
idiomatic HCL. No SaaS, no credentials leave your machine: everything runs on
|
|
@@ -23,7 +23,13 @@ localhost, reading your local state and plan.
|
|
|
23
23
|
canvas highlights what will change. Only the agent executes Terraform —
|
|
24
24
|
the canvas has no apply button by design.
|
|
25
25
|
|
|
26
|
-
## Install
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
stackcanvas is a standard MCP stdio server (`npx -y stackcanvas`) — point any
|
|
29
|
+
MCP-capable coding agent at it. The paths below, in order of how battle-tested
|
|
30
|
+
they are:
|
|
31
|
+
|
|
32
|
+
### Claude Code (CI-verified)
|
|
27
33
|
|
|
28
34
|
claude plugin marketplace add pshenok/stackcanvas
|
|
29
35
|
claude plugin install stackcanvas@stackcanvas
|
|
@@ -42,12 +48,12 @@ Or without the plugin system:
|
|
|
42
48
|
Then, inside a repo with Terraform, just ask: *open the stackcanvas canvas
|
|
43
49
|
for this repo*.
|
|
44
50
|
|
|
45
|
-
|
|
51
|
+
### Other MCP clients
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
work
|
|
50
|
-
|
|
53
|
+
The snippets below are **reported to work; not yet CI-verified** — only the
|
|
54
|
+
Claude Code path above is exercised in CI. Codex CLI and other MCP-capable
|
|
55
|
+
agents should work with the equivalent stdio config (`npx -y stackcanvas`) —
|
|
56
|
+
untested, reports welcome in issues.
|
|
51
57
|
|
|
52
58
|
**Cursor** (`.cursor/mcp.json`):
|
|
53
59
|
|
|
@@ -78,11 +84,14 @@ What's provider-specific is only the curation layer, shipped as **provider packs
|
|
|
78
84
|
|
|
79
85
|
- a palette pack (`packages/ui/src/resource-palette.ts`) — curated drag-and-drop types
|
|
80
86
|
- containment rules (`DEFAULT_CONTAINMENT_RULES` in `@stackcanvas/core`) — which
|
|
81
|
-
resources render as visual containers (AWS VPC/subnet
|
|
87
|
+
resources render as visual containers (AWS VPC/subnet, GCP network/subnetwork,
|
|
88
|
+
Azure subnet, Cloudflare zone today)
|
|
82
89
|
- icon patterns (`packages/ui/src/icons.tsx`)
|
|
83
90
|
|
|
84
|
-
|
|
85
|
-
|
|
91
|
+
Four packs ship today: **AWS** (complete — the reference pack) and **GCP /
|
|
92
|
+
Azure / Cloudflare starter packs** covering the common resource types per
|
|
93
|
+
provider. Rounding out a starter pack, or adding a new provider entirely, is
|
|
94
|
+
pure data and makes a great first PR.
|
|
86
95
|
|
|
87
96
|
## OpenTofu
|
|
88
97
|
|
|
@@ -103,7 +112,7 @@ to pin it — both take precedence over auto-detection.
|
|
|
103
112
|
|
|
104
113
|
## Demo
|
|
105
114
|
|
|
106
|
-
`examples/demo` contains a small AWS config. Run `terraform init && terraform plan -out=tfplan && terraform show -json tfplan > .stackcanvas/plan.json` there and open the canvas to see create-highlighting. `plan` does not create or modify any resources — nothing is provisioned until `terraform apply` (note: the AWS provider still needs credentials and makes read-only API calls during plan).
|
|
115
|
+
`examples/local-demo` is a **zero-credential** playground: `terraform init && terraform apply -auto-approve` creates real state using only local providers (no cloud account touched), and the canvas renders it — including sensitive masking on the generated password. `examples/demo` contains a small AWS config. Run `terraform init && terraform plan -out=tfplan && terraform show -json tfplan > .stackcanvas/plan.json` there and open the canvas to see create-highlighting. `plan` does not create or modify any resources — nothing is provisioned until `terraform apply` (note: the AWS provider still needs credentials and makes read-only API calls during plan).
|
|
107
116
|
|
|
108
117
|
## Telemetry
|
|
109
118
|
|
package/dist/cli.js
CHANGED
|
@@ -40,7 +40,15 @@ function deriveEdges(nodes) {
|
|
|
40
40
|
}
|
|
41
41
|
var DEFAULT_CONTAINMENT_RULES = [
|
|
42
42
|
{ containerType: "aws_vpc", memberAttr: "vpc_id", kind: "vpc" },
|
|
43
|
-
{ containerType: "aws_subnet", memberAttr: "subnet_id", kind: "subnet" }
|
|
43
|
+
{ containerType: "aws_subnet", memberAttr: "subnet_id", kind: "subnet" },
|
|
44
|
+
// GCP networks/subnetworks are referenced by `self_link`, not `id`.
|
|
45
|
+
{ containerType: "google_compute_network", memberAttr: "network", kind: "vpc", containerIdAttr: "self_link" },
|
|
46
|
+
{ containerType: "google_compute_subnetwork", memberAttr: "subnetwork", kind: "subnet", containerIdAttr: "self_link" },
|
|
47
|
+
{ containerType: "azurerm_subnet", memberAttr: "subnet_id", kind: "subnet" },
|
|
48
|
+
// Cloudflare zones aren't a network container, but they group the
|
|
49
|
+
// resources scoped to them the same way a VPC groups its members — reuse
|
|
50
|
+
// the 'vpc' kind rather than introducing a one-off styling kind.
|
|
51
|
+
{ containerType: "cloudflare_zone", memberAttr: "zone_id", kind: "vpc" }
|
|
44
52
|
];
|
|
45
53
|
function deriveContainment(g, rules = DEFAULT_CONTAINMENT_RULES) {
|
|
46
54
|
const groups = [...g.groups];
|
|
@@ -48,7 +56,7 @@ function deriveContainment(g, rules = DEFAULT_CONTAINMENT_RULES) {
|
|
|
48
56
|
for (const rule of rules) {
|
|
49
57
|
const groupByPhysicalId = /* @__PURE__ */ new Map();
|
|
50
58
|
for (const n of nodes.filter((n2) => n2.type === rule.containerType)) {
|
|
51
|
-
const pid = n.attributes["id"];
|
|
59
|
+
const pid = n.attributes[rule.containerIdAttr ?? "id"];
|
|
52
60
|
if (typeof pid !== "string") continue;
|
|
53
61
|
const gid = `${rule.kind}:${n.id}`;
|
|
54
62
|
groups.push({ id: gid, label: n.name, kind: rule.kind, parent: n.group });
|
|
@@ -926,7 +934,7 @@ function openBrowser(url) {
|
|
|
926
934
|
}
|
|
927
935
|
|
|
928
936
|
// src/version.ts
|
|
929
|
-
var VERSION = "0.2.
|
|
937
|
+
var VERSION = "0.2.3";
|
|
930
938
|
|
|
931
939
|
// src/server.ts
|
|
932
940
|
function looksLikeTerraformRoot(dir) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stackcanvas",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@types/node": "^22.0.0",
|
|
30
30
|
"tsup": "^8.0.0"
|
|
31
31
|
},
|
|
32
|
-
"description": "Live infrastructure canvas for
|
|
32
|
+
"description": "Live infrastructure canvas for AI coding agents (MCP): see what your agent is about to do to your Terraform \u2014 and approve it \u2014 before it happens. Local-first, credentials never leave your machine.",
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|