@mesh-tech/mesh-cli 0.1.1 → 0.12.1
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/assets/intent/agents-fence.md +10 -0
- package/assets/intent/intent-claude-gate.mjs +255 -0
- package/assets/log-shipper.mjs +94 -0
- package/bin/mesh.mjs +80 -0
- package/dist/bin/mesh.d.ts +7 -9
- package/dist/bin/mesh.d.ts.map +1 -1
- package/dist/bin/mesh.js +20878 -37
- package/dist/bin/mesh.js.map +7 -1
- package/dist/build-info.json +4 -0
- package/dist/src/commands/agent-api-client.d.ts +79 -0
- package/dist/src/commands/agent-api-client.d.ts.map +1 -0
- package/dist/src/commands/agent-api-client.js +170 -0
- package/dist/src/commands/agent-api-client.js.map +1 -0
- package/dist/src/commands/artifacts.d.ts +13 -0
- package/dist/src/commands/artifacts.d.ts.map +1 -0
- package/dist/src/commands/artifacts.js +140 -0
- package/dist/src/commands/artifacts.js.map +1 -0
- package/dist/src/commands/cluster.d.ts +45 -0
- package/dist/src/commands/cluster.d.ts.map +1 -0
- package/dist/src/commands/cluster.js +259 -0
- package/dist/src/commands/cluster.js.map +1 -0
- package/dist/src/commands/conversations.d.ts +61 -0
- package/dist/src/commands/conversations.d.ts.map +1 -0
- package/dist/src/commands/conversations.js +239 -0
- package/dist/src/commands/conversations.js.map +1 -0
- package/dist/src/commands/create-app.d.ts +26 -3
- package/dist/src/commands/create-app.d.ts.map +1 -1
- package/dist/src/commands/create-app.js +465 -107
- package/dist/src/commands/create-app.js.map +1 -1
- package/dist/src/commands/deploy.d.ts +19 -0
- package/dist/src/commands/deploy.d.ts.map +1 -1
- package/dist/src/commands/deploy.js +83 -142
- package/dist/src/commands/deploy.js.map +1 -1
- package/dist/src/commands/dev-doctor.d.ts +137 -0
- package/dist/src/commands/dev-doctor.d.ts.map +1 -0
- package/dist/src/commands/dev-doctor.js +671 -0
- package/dist/src/commands/dev-doctor.js.map +1 -0
- package/dist/src/commands/dev-launch.d.ts +59 -0
- package/dist/src/commands/dev-launch.d.ts.map +1 -0
- package/dist/src/commands/dev-launch.js +118 -0
- package/dist/src/commands/dev-launch.js.map +1 -0
- package/dist/src/commands/dev-token-server.d.ts +32 -0
- package/dist/src/commands/dev-token-server.d.ts.map +1 -0
- package/dist/src/commands/dev-token-server.js +68 -0
- package/dist/src/commands/dev-token-server.js.map +1 -0
- package/dist/src/commands/dev.d.ts +289 -2
- package/dist/src/commands/dev.d.ts.map +1 -1
- package/dist/src/commands/dev.js +2501 -574
- package/dist/src/commands/dev.js.map +1 -1
- package/dist/src/commands/docs.d.ts +3 -0
- package/dist/src/commands/docs.d.ts.map +1 -0
- package/dist/src/commands/docs.js +262 -0
- package/dist/src/commands/docs.js.map +1 -0
- package/dist/src/commands/hub/index.d.ts +99 -0
- package/dist/src/commands/hub/index.d.ts.map +1 -0
- package/dist/src/commands/hub/index.js +452 -0
- package/dist/src/commands/hub/index.js.map +1 -0
- package/dist/src/commands/init.d.ts +65 -0
- package/dist/src/commands/init.d.ts.map +1 -0
- package/dist/src/commands/init.js +370 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/install-shim.d.ts +28 -0
- package/dist/src/commands/install-shim.d.ts.map +1 -0
- package/dist/src/commands/install-shim.js +191 -0
- package/dist/src/commands/install-shim.js.map +1 -0
- package/dist/src/commands/local/auth-provision.d.ts +71 -0
- package/dist/src/commands/local/auth-provision.d.ts.map +1 -0
- package/dist/src/commands/local/auth-provision.js +286 -0
- package/dist/src/commands/local/auth-provision.js.map +1 -0
- package/dist/src/commands/local/dev-local.d.ts +97 -0
- package/dist/src/commands/local/dev-local.d.ts.map +1 -0
- package/dist/src/commands/local/dev-local.js +306 -0
- package/dist/src/commands/local/dev-local.js.map +1 -0
- package/dist/src/commands/local/docker-runner.d.ts +37 -0
- package/dist/src/commands/local/docker-runner.d.ts.map +1 -0
- package/dist/src/commands/local/docker-runner.js +104 -0
- package/dist/src/commands/local/docker-runner.js.map +1 -0
- package/dist/src/commands/local/helpers.d.ts +22 -0
- package/dist/src/commands/local/helpers.d.ts.map +1 -0
- package/dist/src/commands/local/helpers.js +46 -0
- package/dist/src/commands/local/helpers.js.map +1 -0
- package/dist/src/commands/local/hub-local.d.ts +51 -0
- package/dist/src/commands/local/hub-local.d.ts.map +1 -0
- package/dist/src/commands/local/hub-local.js +197 -0
- package/dist/src/commands/local/hub-local.js.map +1 -0
- package/dist/src/commands/local/index.d.ts +23 -0
- package/dist/src/commands/local/index.d.ts.map +1 -0
- package/dist/src/commands/local/index.js +386 -0
- package/dist/src/commands/local/index.js.map +1 -0
- package/dist/src/commands/local/mocks.d.ts +361 -0
- package/dist/src/commands/local/mocks.d.ts.map +1 -0
- package/dist/src/commands/local/mocks.js +756 -0
- package/dist/src/commands/local/mocks.js.map +1 -0
- package/dist/src/commands/local/seed-zitadel.d.ts +151 -0
- package/dist/src/commands/local/seed-zitadel.d.ts.map +1 -0
- package/dist/src/commands/local/seed-zitadel.js +408 -0
- package/dist/src/commands/local/seed-zitadel.js.map +1 -0
- package/dist/src/commands/local/seed.d.ts +106 -0
- package/dist/src/commands/local/seed.d.ts.map +1 -0
- package/dist/src/commands/local/seed.js +252 -0
- package/dist/src/commands/local/seed.js.map +1 -0
- package/dist/src/commands/local/stack.d.ts +173 -0
- package/dist/src/commands/local/stack.d.ts.map +1 -0
- package/dist/src/commands/local/stack.js +499 -0
- package/dist/src/commands/local/stack.js.map +1 -0
- package/dist/src/commands/login.d.ts +256 -12
- package/dist/src/commands/login.d.ts.map +1 -1
- package/dist/src/commands/login.js +978 -50
- package/dist/src/commands/login.js.map +1 -1
- package/dist/src/commands/peer-addressing.d.ts +51 -0
- package/dist/src/commands/peer-addressing.d.ts.map +1 -0
- package/dist/src/commands/peer-addressing.js +64 -0
- package/dist/src/commands/peer-addressing.js.map +1 -0
- package/dist/src/commands/port-ownership.d.ts +69 -0
- package/dist/src/commands/port-ownership.d.ts.map +1 -0
- package/dist/src/commands/port-ownership.js +161 -0
- package/dist/src/commands/port-ownership.js.map +1 -0
- package/dist/src/commands/registry-publish.d.ts +3 -0
- package/dist/src/commands/registry-publish.d.ts.map +1 -0
- package/dist/src/commands/registry-publish.js +161 -0
- package/dist/src/commands/registry-publish.js.map +1 -0
- package/dist/src/commands/registry.d.ts +146 -2
- package/dist/src/commands/registry.d.ts.map +1 -1
- package/dist/src/commands/registry.js +541 -85
- package/dist/src/commands/registry.js.map +1 -1
- package/dist/src/commands/secrets/index.d.ts.map +1 -1
- package/dist/src/commands/secrets/index.js +15 -1
- package/dist/src/commands/secrets/index.js.map +1 -1
- package/dist/src/commands/secrets/migrate-config.d.ts +24 -0
- package/dist/src/commands/secrets/migrate-config.d.ts.map +1 -0
- package/dist/src/commands/secrets/migrate-config.js +277 -0
- package/dist/src/commands/secrets/migrate-config.js.map +1 -0
- package/dist/src/commands/secrets/set.d.ts +1 -0
- package/dist/src/commands/secrets/set.d.ts.map +1 -1
- package/dist/src/commands/secrets/set.js +96 -2
- package/dist/src/commands/secrets/set.js.map +1 -1
- package/dist/src/commands/skills.d.ts +34 -0
- package/dist/src/commands/skills.d.ts.map +1 -0
- package/dist/src/commands/skills.js +207 -0
- package/dist/src/commands/skills.js.map +1 -0
- package/dist/src/commands/stack.d.ts.map +1 -1
- package/dist/src/commands/stack.js +361 -23
- package/dist/src/commands/stack.js.map +1 -1
- package/dist/src/commands/temporal.d.ts +15 -0
- package/dist/src/commands/temporal.d.ts.map +1 -0
- package/dist/src/commands/temporal.js +781 -0
- package/dist/src/commands/temporal.js.map +1 -0
- package/dist/src/commands/tenant.d.ts +56 -0
- package/dist/src/commands/tenant.d.ts.map +1 -0
- package/dist/src/commands/tenant.js +233 -0
- package/dist/src/commands/tenant.js.map +1 -0
- package/dist/src/commands/tunnel/index.d.ts +49 -3
- package/dist/src/commands/tunnel/index.d.ts.map +1 -1
- package/dist/src/commands/tunnel/index.js +331 -8
- package/dist/src/commands/tunnel/index.js.map +1 -1
- package/dist/src/commands/vcs/clone.d.ts +3 -0
- package/dist/src/commands/vcs/clone.d.ts.map +1 -0
- package/dist/src/commands/vcs/clone.js +20 -0
- package/dist/src/commands/vcs/clone.js.map +1 -0
- package/dist/src/commands/vcs/common.d.ts +21 -0
- package/dist/src/commands/vcs/common.d.ts.map +1 -0
- package/dist/src/commands/vcs/common.js +62 -0
- package/dist/src/commands/vcs/common.js.map +1 -0
- package/dist/src/commands/vcs/drafts.d.ts +13 -0
- package/dist/src/commands/vcs/drafts.d.ts.map +1 -0
- package/dist/src/commands/vcs/drafts.js +45 -0
- package/dist/src/commands/vcs/drafts.js.map +1 -0
- package/dist/src/commands/vcs/get.d.ts +8 -0
- package/dist/src/commands/vcs/get.d.ts.map +1 -0
- package/dist/src/commands/vcs/get.js +61 -0
- package/dist/src/commands/vcs/get.js.map +1 -0
- package/dist/src/commands/vcs/index.d.ts +3 -0
- package/dist/src/commands/vcs/index.d.ts.map +1 -0
- package/dist/src/commands/vcs/index.js +58 -0
- package/dist/src/commands/vcs/index.js.map +1 -0
- package/dist/src/commands/vcs/propose.d.ts +23 -0
- package/dist/src/commands/vcs/propose.d.ts.map +1 -0
- package/dist/src/commands/vcs/propose.js +94 -0
- package/dist/src/commands/vcs/propose.js.map +1 -0
- package/dist/src/commands/vcs/review.d.ts +15 -0
- package/dist/src/commands/vcs/review.d.ts.map +1 -0
- package/dist/src/commands/vcs/review.js +35 -0
- package/dist/src/commands/vcs/review.js.map +1 -0
- package/dist/src/commands/vcs-enrich.d.ts +15 -0
- package/dist/src/commands/vcs-enrich.d.ts.map +1 -0
- package/dist/src/commands/vcs-enrich.js +28 -0
- package/dist/src/commands/vcs-enrich.js.map +1 -0
- package/dist/src/commands/vpn/index.d.ts +24 -0
- package/dist/src/commands/vpn/index.d.ts.map +1 -0
- package/dist/src/commands/vpn/index.js +543 -0
- package/dist/src/commands/vpn/index.js.map +1 -0
- package/dist/src/commands/vpn/tunnel.d.ts +11 -0
- package/dist/src/commands/vpn/tunnel.d.ts.map +1 -0
- package/dist/src/commands/vpn/tunnel.js +188 -0
- package/dist/src/commands/vpn/tunnel.js.map +1 -0
- package/dist/src/commands/workflow.d.ts +24 -0
- package/dist/src/commands/workflow.d.ts.map +1 -0
- package/dist/src/commands/workflow.js +577 -0
- package/dist/src/commands/workflow.js.map +1 -0
- package/dist/src/docs/assemble.d.ts +217 -0
- package/dist/src/docs/assemble.d.ts.map +1 -0
- package/dist/src/docs/assemble.js +739 -0
- package/dist/src/docs/assemble.js.map +1 -0
- package/dist/src/docs/cli-reference.d.ts +93 -0
- package/dist/src/docs/cli-reference.d.ts.map +1 -0
- package/dist/src/docs/cli-reference.js +256 -0
- package/dist/src/docs/cli-reference.js.map +1 -0
- package/dist/src/docs/discover.d.ts +60 -0
- package/dist/src/docs/discover.d.ts.map +1 -0
- package/dist/src/docs/discover.js +233 -0
- package/dist/src/docs/discover.js.map +1 -0
- package/dist/src/docs/portal.d.ts +79 -0
- package/dist/src/docs/portal.d.ts.map +1 -0
- package/dist/src/docs/portal.js +242 -0
- package/dist/src/docs/portal.js.map +1 -0
- package/dist/src/docs/registry-docs.d.ts +43 -0
- package/dist/src/docs/registry-docs.d.ts.map +1 -0
- package/dist/src/docs/registry-docs.js +138 -0
- package/dist/src/docs/registry-docs.js.map +1 -0
- package/dist/src/docs/schema.d.ts +48 -0
- package/dist/src/docs/schema.d.ts.map +1 -0
- package/dist/src/docs/schema.js +96 -0
- package/dist/src/docs/schema.js.map +1 -0
- package/dist/src/docs/serve.d.ts +27 -0
- package/dist/src/docs/serve.d.ts.map +1 -0
- package/dist/src/docs/serve.js +102 -0
- package/dist/src/docs/serve.js.map +1 -0
- package/dist/src/docs/start.d.ts +80 -0
- package/dist/src/docs/start.d.ts.map +1 -0
- package/dist/src/docs/start.js +313 -0
- package/dist/src/docs/start.js.map +1 -0
- package/dist/src/eval/agent-eval.d.mts +14 -0
- package/dist/src/eval/agent-eval.d.mts.map +1 -0
- package/dist/src/eval/agent-eval.mjs +273 -0
- package/dist/src/eval/agent-eval.mjs.map +1 -0
- package/dist/src/index.js +624 -7
- package/dist/src/index.js.map +7 -1
- package/dist/src/program.d.ts +26 -0
- package/dist/src/program.d.ts.map +1 -0
- package/dist/src/program.js +76 -0
- package/dist/src/program.js.map +1 -0
- package/dist/src/utils/auth-preflight.d.ts +159 -0
- package/dist/src/utils/auth-preflight.d.ts.map +1 -0
- package/dist/src/utils/auth-preflight.js +298 -0
- package/dist/src/utils/auth-preflight.js.map +1 -0
- package/dist/src/utils/aws-auth.d.ts +181 -0
- package/dist/src/utils/aws-auth.d.ts.map +1 -0
- package/dist/src/utils/aws-auth.js +527 -0
- package/dist/src/utils/aws-auth.js.map +1 -0
- package/dist/src/utils/bastion.d.ts +1 -1
- package/dist/src/utils/bastion.d.ts.map +1 -1
- package/dist/src/utils/bastion.js +29 -8
- package/dist/src/utils/bastion.js.map +1 -1
- package/dist/src/utils/build-info.d.ts +33 -0
- package/dist/src/utils/build-info.d.ts.map +1 -0
- package/dist/src/utils/build-info.js +102 -0
- package/dist/src/utils/build-info.js.map +1 -0
- package/dist/src/utils/capture-history.d.ts +62 -0
- package/dist/src/utils/capture-history.d.ts.map +1 -0
- package/dist/src/utils/capture-history.js +94 -0
- package/dist/src/utils/capture-history.js.map +1 -0
- package/dist/src/utils/deploy-preflight.d.ts +52 -0
- package/dist/src/utils/deploy-preflight.d.ts.map +1 -0
- package/dist/src/utils/deploy-preflight.js +183 -0
- package/dist/src/utils/deploy-preflight.js.map +1 -0
- package/dist/src/utils/errors.d.ts +75 -0
- package/dist/src/utils/errors.d.ts.map +1 -0
- package/dist/src/utils/errors.js +106 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/first-party-contexts.d.ts +40 -0
- package/dist/src/utils/first-party-contexts.d.ts.map +1 -0
- package/dist/src/utils/first-party-contexts.js +53 -0
- package/dist/src/utils/first-party-contexts.js.map +1 -0
- package/dist/src/utils/index.d.ts +2 -0
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +2 -0
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/kubeconfig.d.ts +62 -0
- package/dist/src/utils/kubeconfig.d.ts.map +1 -0
- package/dist/src/utils/kubeconfig.js +118 -0
- package/dist/src/utils/kubeconfig.js.map +1 -0
- package/dist/src/utils/log.d.ts +27 -1
- package/dist/src/utils/log.d.ts.map +1 -1
- package/dist/src/utils/log.js +59 -5
- package/dist/src/utils/log.js.map +1 -1
- package/dist/src/utils/pid.d.ts +47 -0
- package/dist/src/utils/pid.d.ts.map +1 -0
- package/dist/src/utils/pid.js +83 -0
- package/dist/src/utils/pid.js.map +1 -0
- package/dist/src/utils/pulumi-run.d.ts +23 -0
- package/dist/src/utils/pulumi-run.d.ts.map +1 -0
- package/dist/src/utils/pulumi-run.js +112 -0
- package/dist/src/utils/pulumi-run.js.map +1 -0
- package/dist/src/utils/pulumi.d.ts +15 -0
- package/dist/src/utils/pulumi.d.ts.map +1 -1
- package/dist/src/utils/pulumi.js +35 -0
- package/dist/src/utils/pulumi.js.map +1 -1
- package/dist/src/utils/reachability.d.ts +29 -0
- package/dist/src/utils/reachability.d.ts.map +1 -0
- package/dist/src/utils/reachability.js +81 -0
- package/dist/src/utils/reachability.js.map +1 -0
- package/dist/src/utils/recover-conversation.d.ts +154 -0
- package/dist/src/utils/recover-conversation.d.ts.map +1 -0
- package/dist/src/utils/recover-conversation.js +314 -0
- package/dist/src/utils/recover-conversation.js.map +1 -0
- package/dist/src/utils/registry-broker.d.ts +148 -0
- package/dist/src/utils/registry-broker.d.ts.map +1 -0
- package/dist/src/utils/registry-broker.js +180 -0
- package/dist/src/utils/registry-broker.js.map +1 -0
- package/dist/src/utils/socks-forward.d.ts +40 -0
- package/dist/src/utils/socks-forward.d.ts.map +1 -0
- package/dist/src/utils/socks-forward.js +97 -0
- package/dist/src/utils/socks-forward.js.map +1 -0
- package/dist/src/utils/stack-flag.d.ts +23 -0
- package/dist/src/utils/stack-flag.d.ts.map +1 -0
- package/dist/src/utils/stack-flag.js +41 -0
- package/dist/src/utils/stack-flag.js.map +1 -0
- package/dist/src/utils/tailscale-targets.d.ts +52 -0
- package/dist/src/utils/tailscale-targets.d.ts.map +1 -0
- package/dist/src/utils/tailscale-targets.js +93 -0
- package/dist/src/utils/tailscale-targets.js.map +1 -0
- package/dist/src/utils/tailscale.d.ts +277 -0
- package/dist/src/utils/tailscale.d.ts.map +1 -0
- package/dist/src/utils/tailscale.js +1007 -0
- package/dist/src/utils/tailscale.js.map +1 -0
- package/dist/src/utils/temporal-auth.d.ts +43 -0
- package/dist/src/utils/temporal-auth.d.ts.map +1 -0
- package/dist/src/utils/temporal-auth.js +176 -0
- package/dist/src/utils/temporal-auth.js.map +1 -0
- package/dist/src/utils/temporal-codec.d.ts +101 -0
- package/dist/src/utils/temporal-codec.d.ts.map +1 -0
- package/dist/src/utils/temporal-codec.js +319 -0
- package/dist/src/utils/temporal-codec.js.map +1 -0
- package/dist/src/utils/tunnel-ownership.d.ts +130 -0
- package/dist/src/utils/tunnel-ownership.d.ts.map +1 -0
- package/dist/src/utils/tunnel-ownership.js +274 -0
- package/dist/src/utils/tunnel-ownership.js.map +1 -0
- package/dist/src/utils/vpn-join.d.ts +32 -0
- package/dist/src/utils/vpn-join.d.ts.map +1 -0
- package/dist/src/utils/vpn-join.js +62 -0
- package/dist/src/utils/vpn-join.js.map +1 -0
- package/dist/src/utils/vpn.d.ts +62 -0
- package/dist/src/utils/vpn.d.ts.map +1 -0
- package/dist/src/utils/vpn.js +183 -0
- package/dist/src/utils/vpn.js.map +1 -0
- package/dist/src/utils/workflow-fingerprint.d.ts +49 -0
- package/dist/src/utils/workflow-fingerprint.d.ts.map +1 -0
- package/dist/src/utils/workflow-fingerprint.js +135 -0
- package/dist/src/utils/workflow-fingerprint.js.map +1 -0
- package/dist/src/utils/worktree-identity.d.ts +86 -0
- package/dist/src/utils/worktree-identity.d.ts.map +1 -0
- package/dist/src/utils/worktree-identity.js +164 -0
- package/dist/src/utils/worktree-identity.js.map +1 -0
- package/fragments/agents/AGENTS.md.hbs +92 -0
- package/fragments/agents/CLAUDE.md.hbs +8 -0
- package/fragments/base/Pulumi.dev.yaml.hbs +10 -0
- package/fragments/base/Pulumi.yaml.hbs +9 -0
- package/fragments/base/index.ts.hbs +107 -0
- package/fragments/base/package.json.hbs +22 -0
- package/{templates/api-web-db/api → fragments/base}/tsconfig.json +3 -4
- package/fragments/bucket/api/src/storage.ts.hbs +81 -0
- package/fragments/database/api/src/db.ts.hbs +23 -0
- package/fragments/database/prisma/schema.prisma.hbs +18 -0
- package/{templates/api-web-db → fragments/service}/api/.dockerignore +2 -0
- package/fragments/service/api/package.json.hbs +40 -0
- package/fragments/service/api/src/index.ts.hbs +58 -0
- package/{templates/api-web-db → fragments/service/api}/tsconfig.json +5 -3
- package/fragments/temporal/worker/.dockerignore +4 -0
- package/fragments/temporal/worker/Dockerfile +15 -0
- package/{templates/temporal-api-worker → fragments/temporal}/worker/package.json.hbs +3 -2
- package/fragments/temporal/worker/src/activities.ts.hbs +14 -0
- package/fragments/temporal/worker/src/worker.ts.hbs +27 -0
- package/fragments/temporal/worker/src/workflows.ts.hbs +24 -0
- package/fragments/temporal/worker/tsconfig.json +13 -0
- package/package.json +36 -22
- package/skills/core/SKILL.md +365 -0
- package/skills/pull-remote-agent-context/SKILL.md +194 -0
- package/stack/docker-compose.hub.yml +134 -0
- package/stack/docker-compose.yml +447 -0
- package/stack/hub/Dockerfile.api +18 -0
- package/stack/hub/Dockerfile.auth +10 -0
- package/stack/hub/Dockerfile.ui +10 -0
- package/stack/init/01-databases.sql +12 -0
- package/stack/observability/blackbox.yml +20 -0
- package/stack/observability/otel-collector.yaml +73 -0
- package/stack/observability/prometheus.yml +36 -0
- package/stack/observability/tempo.yaml +25 -0
- package/stack/temporal/local.yaml +44 -0
- package/templates/api-auth/AGENTS.md.hbs +16 -0
- package/templates/api-auth/Pulumi.dev.yaml.hbs +8 -0
- package/templates/api-auth/Pulumi.yaml.hbs +8 -0
- package/templates/api-auth/README.md.hbs +67 -0
- package/templates/api-auth/api/package.json.hbs +28 -0
- package/templates/api-auth/api/src/index.ts.hbs +96 -0
- package/templates/api-auth/api/src/schema.ts.hbs +35 -0
- package/templates/api-auth/api/src/seed-authz.ts.hbs +48 -0
- package/templates/api-auth/api/src/spicedb-http-provider.ts.hbs +89 -0
- package/templates/api-auth/index.ts.hbs +65 -0
- package/templates/api-auth/package.json.hbs +20 -0
- package/templates/api-auth/skills/develop/SKILL.md.hbs +32 -0
- package/templates/api-role-gating/AGENTS.md.hbs +20 -0
- package/templates/api-role-gating/Pulumi.dev.yaml.hbs +8 -0
- package/templates/api-role-gating/Pulumi.yaml.hbs +8 -0
- package/templates/api-role-gating/README.md.hbs +64 -0
- package/templates/api-role-gating/api/Dockerfile +17 -0
- package/templates/api-role-gating/api/package.json.hbs +28 -0
- package/templates/api-role-gating/api/src/authn.ts.hbs +29 -0
- package/templates/api-role-gating/api/src/authz.ts.hbs +12 -0
- package/templates/api-role-gating/api/src/main.ts.hbs +58 -0
- package/templates/api-role-gating/api/src/schema.ts.hbs +22 -0
- package/templates/api-role-gating/api/tsconfig.json +13 -0
- package/templates/api-role-gating/index.ts.hbs +107 -0
- package/templates/api-role-gating/package.json.hbs +21 -0
- package/templates/api-role-gating/skills/develop/SKILL.md.hbs +60 -0
- package/templates/api-role-gating/tsconfig.json +10 -0
- package/templates/apps-repo/README.md.hbs +24 -0
- package/templates/apps-repo/gitignore +41 -0
- package/templates/apps-repo/npmrc.hbs +7 -0
- package/templates/apps-repo/package.json.hbs +15 -0
- package/templates/apps-repo/pnpm-workspace.yaml +3 -0
- package/templates/apps-repo/tsconfig.json +18 -0
- package/templates/external-service/AGENTS.md.hbs +20 -0
- package/templates/external-service/Pulumi.dev.yaml.hbs +8 -0
- package/templates/external-service/Pulumi.yaml.hbs +8 -0
- package/templates/external-service/README.md.hbs +56 -0
- package/templates/external-service/api/Dockerfile +15 -0
- package/templates/external-service/api/package.json.hbs +25 -0
- package/templates/external-service/api/src/index.ts.hbs +81 -0
- package/templates/external-service/index.ts.hbs +82 -0
- package/templates/external-service/mocks/vendorpay/package.json.hbs +9 -0
- package/templates/external-service/mocks/vendorpay/server.mjs.hbs +61 -0
- package/templates/external-service/package.json.hbs +34 -0
- package/templates/external-service/skills/develop/SKILL.md.hbs +55 -0
- package/templates/external-service/tsconfig.json +10 -0
- package/templates/platform-repo/AGENTS.md.hbs +18 -0
- package/templates/platform-repo/README.md.hbs +38 -0
- package/templates/platform-repo/core/Pulumi.yaml.hbs +12 -0
- package/templates/platform-repo/core/Pulumi.{{tenant}}-{{env}}.yaml.hbs +57 -0
- package/templates/platform-repo/core/index.ts +62 -0
- package/templates/platform-repo/core/package.json.hbs +22 -0
- package/templates/platform-repo/core/tsconfig.json +8 -0
- package/templates/platform-repo/package.json.hbs +15 -0
- package/templates/platform-repo/platform/Pulumi.yaml.hbs +12 -0
- package/templates/platform-repo/platform/Pulumi.{{tenant}}-{{env}}.yaml.hbs +59 -0
- package/templates/platform-repo/platform/index.ts +95 -0
- package/templates/platform-repo/platform/package.json.hbs +26 -0
- package/templates/platform-repo/platform/tsconfig.json +8 -0
- package/templates/platform-repo/pnpm-workspace.yaml +3 -0
- package/templates/workflow/AGENTS.md.hbs +15 -0
- package/templates/workflow/Pulumi.dev.yaml.hbs +8 -0
- package/templates/workflow/Pulumi.yaml.hbs +8 -0
- package/templates/workflow/README.md.hbs +45 -0
- package/templates/workflow/api/.dockerignore +4 -0
- package/templates/workflow/api/Dockerfile +15 -0
- package/templates/{temporal-api-worker → workflow}/api/package.json.hbs +8 -6
- package/templates/workflow/api/src/index.ts.hbs +130 -0
- package/templates/workflow/api/tsconfig.json +14 -0
- package/templates/workflow/index.ts.hbs +67 -0
- package/templates/workflow/package.json.hbs +20 -0
- package/templates/workflow/skills/develop/SKILL.md.hbs +32 -0
- package/templates/workflow/tsconfig.json +10 -0
- package/templates/workflow/worker/.dockerignore +4 -0
- package/templates/workflow/worker/Dockerfile +13 -0
- package/templates/workflow/worker/package.json.hbs +25 -0
- package/templates/workflow/worker/src/worker.ts.hbs +24 -0
- package/templates/workflow/worker/tsconfig.json +14 -0
- package/dist/src/commands/devbox.d.ts +0 -22
- package/dist/src/commands/devbox.d.ts.map +0 -1
- package/dist/src/commands/devbox.js +0 -463
- package/dist/src/commands/devbox.js.map +0 -1
- package/templates/api-web-db/api/Dockerfile +0 -16
- package/templates/api-web-db/api/package.json.hbs +0 -21
- package/templates/api-web-db/api/src/index.ts.hbs +0 -123
- package/templates/api-web-db/package.json.hbs +0 -27
- package/templates/api-web-db/sst.config.ts.hbs +0 -151
- package/templates/api-web-db/web/.dockerignore +0 -3
- package/templates/api-web-db/web/Dockerfile +0 -17
- package/templates/api-web-db/web/app/lib/db.server.ts +0 -36
- package/templates/api-web-db/web/app/root.tsx +0 -29
- package/templates/api-web-db/web/app/routes/home.tsx.hbs +0 -114
- package/templates/api-web-db/web/app/routes.ts +0 -3
- package/templates/api-web-db/web/package.json.hbs +0 -30
- package/templates/api-web-db/web/prisma/schema.prisma +0 -25
- package/templates/api-web-db/web/prisma.config.ts +0 -18
- package/templates/api-web-db/web/react-router.config.ts +0 -5
- package/templates/api-web-db/web/tsconfig.json +0 -19
- package/templates/api-web-db/web/vite.config.ts +0 -9
- package/templates/temporal-api-worker/README.md.hbs +0 -133
- package/templates/temporal-api-worker/api/src/index.ts.hbs +0 -145
- package/templates/temporal-api-worker/package.json.hbs +0 -29
- package/templates/temporal-api-worker/sst.config.ts.hbs +0 -161
- package/templates/temporal-api-worker/worker/Dockerfile +0 -11
- package/templates/temporal-api-worker/worker/src/bundle-workflows.ts +0 -38
- package/templates/temporal-api-worker/worker/src/worker.ts.hbs +0 -93
- /package/templates/{temporal-api-worker → api-auth}/api/.dockerignore +0 -0
- /package/templates/{temporal-api-worker → api-auth}/api/Dockerfile +0 -0
- /package/templates/{temporal-api-worker → api-auth}/api/tsconfig.json +0 -0
- /package/templates/{temporal-api-worker → api-auth}/tsconfig.json +0 -0
- /package/templates/{temporal-api-worker/worker → api-role-gating/api}/.dockerignore +0 -0
- /package/templates/{temporal-api-worker/worker → external-service/api}/tsconfig.json +0 -0
- /package/templates/{temporal-api-worker → workflow}/api/src/encryption-codec.ts +0 -0
- /package/templates/{temporal-api-worker → workflow}/worker/src/activities.ts.hbs +0 -0
- /package/templates/{temporal-api-worker → workflow}/worker/src/encryption-codec.ts +0 -0
- /package/templates/{temporal-api-worker → workflow}/worker/src/workflows.ts.hbs +0 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: core
|
|
3
|
+
description: >
|
|
4
|
+
The `mesh` developer CLI (@mesh-tech/mesh-cli) — Zitadel/OIDC login,
|
|
5
|
+
CodeArtifact registry auth, Pulumi deploy/stack passthrough, app scaffolding
|
|
6
|
+
(create-app), local dev orchestration (dev), SSM tunnels (tunnel), DB access
|
|
7
|
+
(db), Secrets Manager (secrets), Headscale VPN (vpn), Temporal inspection
|
|
8
|
+
(temporal), workflow IR extraction (workflow), agent artifact export
|
|
9
|
+
(artifacts), reading deployed-agent conversations (conversations), and both
|
|
10
|
+
app API docs and the generated developer portal / CLI reference (docs).
|
|
11
|
+
Activate when running any `mesh ...`
|
|
12
|
+
command, scaffolding a tenant app, opening a bastion/DB tunnel, deploying a
|
|
13
|
+
Pulumi stack via the deployer role, wiring local dev, or building the docs
|
|
14
|
+
portal.
|
|
15
|
+
metadata:
|
|
16
|
+
version: '0.1'
|
|
17
|
+
category: 'tooling'
|
|
18
|
+
type: core
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# `@mesh-tech/mesh-cli`
|
|
22
|
+
|
|
23
|
+
Developer CLI for Mesh Platform. Binary name is **`mesh`**. Installed standalone or
|
|
24
|
+
transitively via the app-kit bundle.
|
|
25
|
+
|
|
26
|
+
## Running it (MESH-2261)
|
|
27
|
+
|
|
28
|
+
**In this monorepo the CLI runs from TypeScript source — there is no build step and
|
|
29
|
+
no `dist/` to go stale.** The `bin` is a launcher (`bin/mesh.mjs`) that runs
|
|
30
|
+
`bin/mesh.ts` under `tsx`, so you always get the local source of whatever
|
|
31
|
+
worktree/app you're in. (At publish time `build-for-publish` rewrites the `bin` to
|
|
32
|
+
the built `./dist/bin/mesh.js` for consumers.)
|
|
33
|
+
|
|
34
|
+
- **Any cwd:** `pnpm exec mesh <cmd>` — works in the repo root, any worktree, or an
|
|
35
|
+
app subdir, even in a never-built worktree (no `pnpm build` needed).
|
|
36
|
+
- **Repo/worktree root:** `pnpm mesh <cmd>` (the root `"mesh"` script).
|
|
37
|
+
- **Bare `mesh <cmd>`:** run `pnpm exec mesh install-shim` **once** — it writes a tiny
|
|
38
|
+
cwd-aware resolver to `~/.local/bin/mesh` (build-free; survives worktree switches
|
|
39
|
+
and pulls). After that, `mesh dev` etc. run the local source directly. The shim is
|
|
40
|
+
**not** version-pinned: it walks up from your cwd to the nearest
|
|
41
|
+
`node_modules/.bin/mesh`, so it always runs the mesh-cli the **current workspace**
|
|
42
|
+
resolves — the worktree's live source in-repo, or the repo's pinned published
|
|
43
|
+
version in a standalone consumer repo. One global shim, correct local version.
|
|
44
|
+
- **NEVER** run `node …/dist/bin/mesh.js` directly — that path doesn't exist in-repo
|
|
45
|
+
(the CLI isn't built here) and, if it does from a stray publish, it's stale. Use one
|
|
46
|
+
of the forms above.
|
|
47
|
+
- **Suspect you're running a stale copy?** `mesh --version` prints provenance
|
|
48
|
+
(MESH-2479): `source @ <commit> <date>` means this checkout's TypeScript source;
|
|
49
|
+
`published build <date>, commit <commit>` means a packaged install. If the commit
|
|
50
|
+
isn't your checkout's HEAD (or it says `published build` inside a worktree), your
|
|
51
|
+
resolution is stale — remedy: re-run the scoped install so `.bin/mesh` exists here
|
|
52
|
+
(`pnpm install --frozen-lockfile --filter @mesh-tech/mesh-cli...`), then invoke via
|
|
53
|
+
`pnpm exec mesh` (or re-run `pnpm exec mesh install-shim` once if the shim itself
|
|
54
|
+
was overwritten).
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Standalone consumer repo (published package, runs built dist):
|
|
58
|
+
npm i -D @mesh-tech/mesh-cli # or pnpm add -D
|
|
59
|
+
pnpm exec mesh --help
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Built on `commander`. Most commands auto-detect tenant/env/stack from Pulumi config
|
|
63
|
+
in the cwd or its parents; AWS-touching commands resolve credentials in this order:
|
|
64
|
+
ambient env creds (CI) → cached Zitadel JWT from `mesh login` (`AssumeRoleWithWebIdentity`) → AWS SSO profile (`AssumeRole`).
|
|
65
|
+
|
|
66
|
+
> **`mesh registry login` is the exception, and tries a step *before* all three:**
|
|
67
|
+
> the Zitadel-gated **registry-auth broker**. It exchanges the id token `mesh login`
|
|
68
|
+
> already cached for a CodeArtifact read token minted with the broker's own AWS
|
|
69
|
+
> identity, so installing `@mesh-tech/*` needs **no AWS account, no AWS CLI and no
|
|
70
|
+
> `~/.aws/config`** — only a Mesh account holding the `registry:read` role. The three
|
|
71
|
+
> AWS paths remain the fallback (CI, client-owned tenant accounts, publishing).
|
|
72
|
+
> See [`docs/guides/new-developer-setup.md`](../../../../docs/guides/new-developer-setup.md).
|
|
73
|
+
|
|
74
|
+
> **`mesh` is the front door — don't run raw `pulumi` or `aws`.** Every Pulumi op
|
|
75
|
+
> goes through `mesh deploy <op>` (up/preview/destroy/refresh/import/state/cancel/
|
|
76
|
+
> stack output) and stack lifecycle through `mesh stack init`/`rm` — all assume the
|
|
77
|
+
> stack's deployer role with an up-front **login preflight** (a clear "run `mesh login
|
|
78
|
+
> --device`" instead of a raw AWS error). This works in a sandbox with **no `~/.aws`
|
|
79
|
+
> access**: creds are passed as env vars (deploy/db/secrets), `mesh dev` writes its
|
|
80
|
+
> self-refreshing profile under the session scratch dir, and `mesh login --export`
|
|
81
|
+
> falls back to a mesh-managed AWS config when `~/.aws` isn't writable. The one
|
|
82
|
+
> genuine bootstrap that still needs raw pulumi: setting the initial
|
|
83
|
+
> `mesh:deployerRole` on a brand-new stack.
|
|
84
|
+
|
|
85
|
+
## Command reference
|
|
86
|
+
|
|
87
|
+
Top-level commands (each `register*` is wired in `src/program.ts`, which `bin/mesh.ts` runs):
|
|
88
|
+
|
|
89
|
+
| Command | Subcommands | Does | Key flags / args |
|
|
90
|
+
|---|---|---|---|
|
|
91
|
+
| `mesh login <context>` | (also `mesh logout <context>`) | Zitadel OIDC PKCE or device-code auth; caches creds in `~/.config/mesh/`. Context like `mesh.dev`. Auto-discovers config via SSM then HTTPS `.well-known/mesh.json`. | `--status` (reports the cached Zitadel session, or — when there isn't one — the AWS identity the credential chain resolves, so an SSO profile or a key/secret pair passes too; non-zero only when neither works), `--device`, `--export` (print AWS `export`s for `eval`), `--role <arn>`, `--region <r>` |
|
|
92
|
+
| `mesh registry` | `login [context]`, `status`, `publish` | CodeArtifact auth → refreshes `~/.npmrc` token (12h) + adds `@mesh-tech` scope to project `.npmrc` + **strips an unscoped CodeArtifact `registry=` line from `~/.npmrc`** (after writing `~/.npmrc.bak-<ts>`) — that line is what a raw CodeArtifact sign-in *without* `--namespace @mesh-tech` leaves behind, and it makes CodeArtifact your DEFAULT registry so every *public* install 401s at the 12h expiry. Skipped under `--ci`, where the unscoped login is deliberate. `status` probes the registry rather than grepping the file: expired/missing token or a hijack exits 1, an unreachable registry warns and exits 0. **Step 0 is the Zitadel-gated broker:** with a context (`mesh registry login mesh.dev`) the CLI POSTs the cached id token to the platform's `registry-auth` service, which returns a CodeArtifact read token minted with its OWN AWS identity — so this path needs no AWS account, CLI or profile at all. It writes the same two `~/.npmrc` lines the AWS path does. Falls back to the AWS chain when the platform publishes no broker, when the broker is unreachable, or with `--no-broker`; a 403 (a valid Mesh account without the `registry:read` role) is fatal and does **not** fall through. `--publish` and `--profile` deliberately skip the broker — both are AWS-identity paths. `--profile mesh-dev` auto-runs the AWS SSO login when the session is stale. Also runs automatically after `mesh login {tenant}.{env}` (F2). `login --publish` assumes the registry's publisher role (from `--role` or the registry SSM export); `publish` pushes package snapshots. | `login`: `--no-broker`, `--profile <sso>`, `--role <arn>`, `--ci`, `--skip-npmrc`, `--publish`; `publish`: `--snapshot` |
|
|
93
|
+
| `mesh db` | `connect`, `credentials`(alias `creds`), `env`, `psql`, `exec <command...>` | Access tenant DBs through an SSM bastion tunnel. `env` prints `export`s for `eval`; `exec` runs a command with `DATABASE_URL` injected. | `-t/--tenant`, `-e/--env`, `-a/--app`, `--app-tenant`, `--app-stage`; `exec` also: `--secret <arn>`, `--ssl <require\|no-verify\|disable>`, `--port <n>` |
|
|
94
|
+
| `mesh deploy ...` | passthrough | Runs `pulumi` with the stack's `mesh:deployerRole` assumed. Unknown opts/args pass through; defaults to `up` if no subcommand. | `-s/--stack <name>` (stripped before pulumi `up`); everything else → pulumi (`preview`, `up --yes`, `destroy`, `stack output …`) |
|
|
95
|
+
| `mesh dev` | `logs <service>`, `restart <service>`, `list`, `test-user [name]` | Two modes. **Tethered** (deployed stack): reads the Pulumi stack dev output, opens tunnels, injects Secrets Manager secrets; needs VPN/AWS creds. **Local** (`--local`, auto when the app has no `Pulumi.yaml`): synthesizes services from the app layout (subdirs with a `dev` script) and wires them to the `mesh start` platform (Temporal `local-dev`, app DB, Zitadel, ministack via `AWS_ENDPOINT_URL`) — zero AWS/VPN/Pulumi. `--externals` (local mode; `--mock` is an alias) also realizes the app's declared external services (package.json → `mesh.externals`; legacy `mesh.mocks` still read). Each declaration runs in one of three MODES — `mock` (the service is emulated: `openapi` → a Prism mock server from a spec, or `src` → a mock process), `local` (a local version of the real service: a `compose` file + published `port`, e.g. a vendor-shaped DB — up `--wait` before the app's services; a realization another checkout already started is **adopted** instead of failing — declared port already served **by a container this compose file defines** → adopt as-is (a publisher the file doesn't define — a native install or unrelated container — is a hard **conflict**, never adopted, since credentials would seed against the wrong service); a stopped foreign container holding the compose `container_name` → `docker start` + adopt — so startup order across checkouts doesn't matter; adopted externals stay out of session state and `--kill` tears down only externals this session created, volumes kept), `remote` (connect to the ACTUAL service: inline vendor `credentials`, or the credentials the app's tenant environment is configured with via `remote.env`). A declaration may carry SEVERAL realizations; `mode` picks the default and `--externals name=mode` overrides it per run (`--externals plaid-db=remote,plaid`). Remote externals get a blackbox uptime probe against their real endpoint. Failing to realize a remote external is fatal only when you named it; a bare `--externals` warns and keeps going, so the local loop still works with no AWS identity. Every realization seeds its ExternalService credential secret (`{{url}}`/`{{host}}`/`{{port}}` from the stand-in's endpoint, `{{env:VAR}}` from the shell) so `resolveCredentials()` runs the deployed code path against the stand-in. Runners: tmux (default) or `--runner docker` (CI/headless — services run as a docker compose project with host networking; parity `--status`/`--kill`/`logs`/`restart`). | root: `--local`, `--externals [name[=mode],…]` (alias `--mock`), `--runner <tmux\|docker>`, `--app <path>`, `--stage`, `--headless`, `--kill`, `--status`, `--json`, `--session <name>`, `--profile <sso>`; `logs`: `--tail <n>`; `test-user`: `--tenant/--env/--region` |
|
|
96
|
+
| `mesh start` / `mesh stop` / `mesh status` | — | Full-local Mesh platform via docker compose (project `mesh-local`, assets ship in the CLI package): Postgres, Temporal (+UI), Zitadel, SpiceDB, ministack (local AWS fabric: SSM/Secrets/S3 registry), memcached, OpenSearch, **and the hosted observability backends** (OTel collector + Loki + Tempo + Prometheus — the Hub's logs/traces/metrics views run unchanged). Seeds tenant `local`/env `dev` on first boot and reconciles every Zitadel-provisioned app tenant into the registry. **No AWS creds, VPN, or Pulumi state needed — Docker only.** The **Hub is included by default** — three overlay services, `hub-api` + `hub-ui` + `hub-auth` (an oauth2-proxy; it is what binds the front-door port and proxies to `hub-ui`, so front-door 401s/redirect loops are in ITS logs, not `hub-api`'s) — the front door at http://localhost:9000 — `MESH_HUB_PORT=<port>` publishes it elsewhere when 9000 is taken; export it for `mesh status` too (images build once from the published @mesh-tech/hub tarball; needs `mesh registry login` the first time; `--no-hub` opts out). Auth contract (MESH-2479): `--with-hub` refreshes to the latest published hub after preflighting the CodeArtifact token — with an expired/missing token it falls back to the already-built local images (warn + fixing command), or fails fast naming `mesh registry login --profile mesh-dev` when none exist; the default (no-flag) path with an expired/missing token starts hub-less and names the same fix. Non-TTY runs (CI, agents, piped output) get an `[HH:MM:SS]` prefix on every step line plus a heartbeat during long fetches/builds — `MESH_LOG_TIMESTAMPS=1/0` forces the prefix on/off (default: on when stderr is not a TTY). | `start`: `--no-seed`, `--no-hub`, `--with-hub`; `stop`: `--destroy` (drops volumes/seeds); `status`: `--json` |
|
|
97
|
+
| `mesh hub` | `dev` | One-command local Hub over a running dev-local stack. Launches the CURRENT-CODE Hub (apps/hub api+ui from a mesh-platform checkout) pointed at an existing `mesh dev` session — auto-assembles `HUB_TENANT`/`HUB_SCOPE_ENV`/`HUB_SCOPE_TENANTS` (session platform context), `TEMPORAL_ADDRESS` (session tunnel), `AWS_*` (session scratch profile), `DEV_USER_*`+`DEV_USER_TOKEN_URL` (session dev identity; starts its own token-server if the session predates it, so tokens stay fresh past ~1h). Refuses to launch with an empty tenant scope (which the Hub renders as silently blank). Runs in tmux session `mesh-hub-dev`. | `dev`: `--session <name>`, `--tenants <csv>`, `--port` (or `MESH_HUB_DEV_PORT`, default 9000; the containerized `mesh start` Hub uses the separate `MESH_HUB_PORT`), `--api-port <3002>`, `--platform-dir <dir>` (or `MESH_PLATFORM_DIR`), `--print-env`, `--kill` |
|
|
98
|
+
| `mesh create-app` | — | Scaffold a tenant app. Composable mode (primitives) or legacy template mode. Interactive when TTY + missing flags. Run at the root of an **empty** `{tenant}-mesh-apps` git clone (a `.git` with no `package.json`/`apps/`/`tenants/` and no enclosing pnpm workspace), it first generates the repo-level shape — `pnpm-workspace.yaml` over `apps/*`, private root `package.json`, scoped-registry `.npmrc`, base `tsconfig.json`, `.gitignore`, `README.md`, `apps/` — then scaffolds the app. Never overwrites an existing file. | `--tenant`, `--name`, `--primitives <csv>` (`service,database,temporal,bucket`), `--template <workflow\|api-auth\|api-role-gating\|external-service>`, `--test` (writes to `tests/tenants/`) |
|
|
99
|
+
| `mesh init` | `app-tenant` | The repo doctor (A1–A3): read-only check pipeline — CLI auth, registry access, public npm not hijacked, platform reachable (Hub API), app-tenant registration, deployer role, repo shape, agent skills — each failure names the exact `mesh` fix. **Registry access** is a live probe of the CodeArtifact token, not a grep of `~/.npmrc`: an expired token `fail`s (it used to `pass`), an unreachable registry `warn`s (a network fault is not an auth fault). **Public npm not hijacked** fails when `~/.npmrc` carries an unscoped `registry=<codeartifact>` line, which makes CodeArtifact your default registry — one `mesh registry login` fixes both. Exit 0 iff all pass; re-run any time. `--fix` applies developer-scope fixes (registry token, skills sync); operator actions stay remediations — and `--profile <p>` is the SSO profile `--fix` logs into CodeArtifact with, echoed back in the `fix:` command each check prints so the advertised command is the one that runs. | `app-tenant`: `--tenant <name>`, `--context <ctx>` (default `local`), `--hub-url <url>`, `--fix`, `--profile <sso>`, `--json` |
|
|
100
|
+
| `mesh skills` | `sync` | Agent-skill distribution (D1/D2): installs the base building-with-Mesh skills into the repo's `.claude/skills/mesh-*/` (managed-marker files) and wires TanStack-Intent discovery for the pattern skills shipping inside `@mesh-tech/*` packages (`.intent/hooks/` gate + `.claude/settings.json` SessionStart hook + AGENTS.md fence — the PR #2356 mechanism, vendored). Idempotent; runs automatically after `mesh create-app`. | `sync`: `--check` (CI/doctor: exit 1 when missing/stale), `--root <path>` |
|
|
101
|
+
| `mesh docs` | `build`, `portal`, `cli-reference` | `build` builds/validates an **app's** OpenAPI specs from `docs/docs.config.json` (file copy or SymXchange generation). `start`/`stop`/`list` are the simple front door: `start` serves the docs on loopback — DETACHED in a tmux session named `mesh-docs` by default (prints the bare URL once live; `stop` kills the session; `--foreground` or any non-TTY runs in the foreground) — serving the working tree in a mesh-platform checkout, or the published `@mesh-tech/docs` artifact fetched from the role-gated CodeArtifact registry anywhere else (docs version == the @mesh-tech/* baseline it describes; `-v` pins, default latest; cached under `~/.cache/mesh/docs/`). `list` shows the published docs versions. `portal` assembles the **Mesh developer portal** (docs.meshtech.io) from every `docs.json`-opted-in doc root in the repo — a directory publishes its markdown iff it holds a `docs.json`; route/title/order/nav derive from the tree and each file, so adding a doc is adding one file — then hands the assembled tree to Zudoku (`apps/docs/`): default runs `zudoku build`, `--serve` runs `zudoku dev`, `--assemble-only`/`-o` stop after assembly. Links between published files are rewritten to routes; links to unpublished repo files become blob links. Reserved directory names (`plans/`, `designs/`, `incidents/`, … the frozen list in `src/docs/schema.ts`) are excluded at any depth. `cli-reference` regenerates `docs/portal/generated/cli-reference.md` from THIS command tree, so it can't document a flag the binary lacks. `portal --check` is the CI gate (`pnpm check:docs-portal`): docs.json schema validation, reserved-segment fail-close, broken links, and CLI-reference staleness; `--diff-base <ref>` prints the publish-set diff for PR job summaries. Hidden commands and `--version` are excluded from the reference. | `build`: `-c/--config <path>` (default `docs/docs.config.json`); `portal`: `-o/--out <dir>`, `--assemble-only`, `--serve`, `-p/--port <n>` (default `3000`), `--check`, `--print-manifest`, `--diff-base <ref>`, `--manifest-out <path>`; `cli-reference`: `-o/--out <path>`, `--check`; `start`: `-v/--version <v>` (default: latest), `-p/--port <n>` (default `4400`; `0` is foreground-only), `--dev` (foreground HMR), `--foreground`; `stop`: no flags; `list`: no flags |
|
|
102
|
+
| `mesh stack` | `init`, `rm <name>` | `init` creates a personal dev stack `dev-{github-user}`, copying base-stack config, setting `mesh:deploy: false`, inheriting KMS secrets provider; `--worktree` appends the git-worktree token (`dev-{user}-{token}`) so concurrent worktrees deploy to **distinct** stacks (SSM paths, Temporal namespace, Nexus endpoint all derive from the stack name → one discriminator isolates all three; no-op on the primary checkout). `rm <name>` removes a personal stack (backend state + local config), credentialed. Both assume the deployer role — no raw `pulumi` / manual creds needed. | `init`: `--from <stack>`, `--name <stack>`, `--worktree`; `rm`: `--yes` |
|
|
103
|
+
| `mesh tenant` | `add <name>`, `list` | Register/inspect app tenants on a platform stack. Run from the **platform layer** of a tenant platform repo (e.g. `mesh-sandbox/platform`). `add` inserts the tenant under `mesh:tenants` in `Pulumi.<stack>.yaml` via a comment-preserving YAML round-trip (untouched lines don't reformat), refuses a tenant that is already declared (an existing entry may carry fields a re-add would drop), derives the `{name}-{env}` subdomain from the stack name (echoed in the success line), and guards against running on the core layer or an app dir; it then prints the deploy + verify sequence — `mesh deploy up` is what makes the registration live. `list` prints what the stack config declares, so "is it registered?" is answerable without opening YAML (warns when the project doesn't look like a platform layer, so an empty result isn't mistaken for "no tenants"). | `add`: `--display-name <name>`, `--subdomain <sub>`, `--zitadel-org-id <id>`, `--stack <stack>`, `--json`; `list`: `--stack <stack>`, `--json` |
|
|
104
|
+
| `mesh tunnel [group]` | `external <name>` | SSM port-forward to platform services. Groups: `dev` (temporal+db), `temporal`. **`external <name>`** tunnels to a *registered* `ExternalService`: host/port are read from its credential secret (`mesh/{app-tenant}/{app-stage}/external/{name}`) — the same values deployed apps resolve at runtime — so anything the bastion can reach is tunnelable with no per-service CLI entry and no bastion services-map change. `-t/-e` are **optional everywhere** — they fall back to the same Pulumi/SST context detection `mesh dev` uses, and `AWS_REGION`/`AWS_PROFILE` default from the nearest Pulumi config + the `{tenant}-{env}` profile convention (region falls back to the effective profile's own `region` — the `[default]` profile when none was resolved — before the platform default us-east-2). | root: `-t/--tenant`, `-e/--env`, `-l/--list`, `-s/--services <csv\|group>`, `--db-port`, `--temporal-ui-port`, `--temporal-frontend-port`; `external`: `-p/--port` (default: the remote port), `-k/--key <key>` (multi-instance `credentials.keyedBy` externals), `--app-tenant`/`--app-stage` (credential axis; default to `-t`/`-e`) |
|
|
105
|
+
| `mesh secrets` | `exec <command...>`, `set [service]`, `migrate-config` | Manage external-service creds in Secrets Manager. `exec` injects secrets as env; `set` reads field schema from SSM and prompts (or `--json`). | `set`: `--key <id>` (multi-instance), `--all`, `--json <str>`, `--stage`, `--region`; `migrate-config`: `--force`, `--dry-run`, `--stage`, `--region` |
|
|
106
|
+
| `mesh artifacts` | `get <ref>` | Download workflow artifact files from an AI-agent conversation. Ref `<conversationId>:<artifactId>` (artifactId defaults to `workflow-artifact`). | `-o/--output <dir>`, `--target <name>`, `--api-url <url>`, `--context <ctx>` (default `mesh.dev`) |
|
|
107
|
+
| `mesh conversations` (alias `conv`) | `list`, `show <id>`, `artifacts <id>` | Read a deployed Mesh agent's conversations: list the caller's conversations, render a transcript, or list a conversation's artifacts. Resolves against the same `agent-targets` registry the MCP `agent_*` tools use. | all three: `--target <name>`, `--api-url <url>` (overrides `--target`), `--context <ctx>` (used with `--api-url`, default `mesh.dev`), `--json` (default when stdout isn't a TTY) |
|
|
108
|
+
| `mesh vpn` | `connect <context>`, `disconnect`, `status`, `tunnel <up\|down\|status>`, `api-key`, `pre-auth-key`, `users` | Headscale VPN mgmt via Tailscale + kubectl. **`connect` now defaults to the userspace `tailscaled`** (brew formula, NOT the GUI Tailscale.app) — the same daemon `mesh dev --transport tailscale` / `mesh vpn tunnel` use, so it **runs headless / under the sandbox** and exposes a local SOCKS5 proxy (route a tool via `ALL_PROXY=socks5://127.0.0.1:<port>`). It relays a one-time browser-register URL for Zitadel auth. `--system` opts into the whole-machine GUI Tailscale.app (system TUN) — needs the app installed and **cannot run headless/sandboxed** (Sparkle.framework abort). For auto-forwarded VPC services (Temporal/RDS) prefer **`mesh vpn tunnel up`** or `mesh dev`. `tunnel status` reports runner **ownership** (`Runner: owned (verified)` vs `NOT OWNED (<reason>)` — a port answering a dial is not proof it's mesh's, MESH-2407); `--json` adds `owned` (bool) + `ownership` (reason string). Admin subcommands `exec` into the `headscale-0` pod. | root: `-t/--tenant` (default `mesh`), `-e/--env` (default `dev`), `-n/--namespace`; `connect`/`disconnect`: `--system`; `tunnel up`: `--context <ctx>`; `tunnel down`: `--stop` (stop daemon, keep login), `--logout`; `tunnel status`: `--json`; `pre-auth-key`: `-u/--user` (**required**), `--expiration <24h>`, `--reusable`, `--ephemeral` |
|
|
109
|
+
| `mesh workflow` | `extract-ir <path>` | Parse Temporal workflow TS source → WorkflowIR graph (nodes+edges). Prints JSON or uploads to S3. | `--app <name>`, `--upload <bucket>` (both required together for S3) |
|
|
110
|
+
| `mesh temporal` | `describe <wfId> [runId]`, `history <wfId> [runId]`, `recover-conversation <wfId> [runId]`, `capture-history <wfId> [runId]` | Inspect Temporal workflows for the current app/stack; reconstruct an agent conversation transcript from durable history when the worker can't replay it; capture a full history to a local replay fixture. | shared: `--stack`, `--address`, `--namespace`; `history`: `-n/--limit <200>`, `-f/--follow`, `--no-compact`, `-p/--show-payloads` (decrypts via `TEMPORAL_ENCODING_KEY` from the K8s secret); `recover-conversation`: `--out <path>`, `--json`, `--snapshot` (structured `{conversationId,messages,artifacts,focus}` blob); `capture-history`: `--out <path>` (default `~/.mesh/replay-histories/<wfId>.json`, do not commit) | <!-- skill-lint-disable-next-line — row documents the mesh-owned kubectl wrappers; the backticked `aws eks get-token` describes what the CLI runs internally, not an operator step -->
|
|
111
|
+
| `mesh kubectl` / `mesh logs` / `mesh exec` | `kubectl [args…]`, `logs [service\|deployment/x\|k=v]`, `exec <service> -- <cmd>` | Cluster access for a **deployed** app — debug CrashLoops/logs without broader creds. Assumes the app's `mesh:deployerRole`, builds a session kubeconfig from the platform `eks` SSM export (`aws eks get-token` — no `eks:DescribeCluster` / `~/.kube/config` needed), shells out to kubectl. Defaults the namespace to the app's own (deployer RBAC is tenant-namespace-scoped). **Use `--stack <name>` to target the deployed stack (e.g. `dev`, not `dev-local`).** | `--stack <name>`; `logs`: `-f/--follow`, `--tail <200>`, `-c/--container`, `--previous`; `exec`: `-c/--container` |
|
|
112
|
+
|
|
113
|
+
## Core workflows
|
|
114
|
+
|
|
115
|
+
### 1. Onboard: auth + install dependencies
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
mesh login mesh.dev # OIDC; auto-uses device flow in remote/headless envs
|
|
119
|
+
mesh login mesh.dev --device # FORCE device flow (browser callback times out over SSH/tailscale)
|
|
120
|
+
mesh registry login mesh.dev # registry token via the Zitadel broker (no AWS needed) + project .npmrc scope
|
|
121
|
+
pnpm install # now resolves @mesh-tech/* from CodeArtifact
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 1b. Run the platform fully locally (no cloud)
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
mesh start # docker compose up + health waits + first-boot seed
|
|
128
|
+
# (seeds: tenant registry, hub DB, Temporal ns local-dev,
|
|
129
|
+
# Zitadel org/CLI app/test users, artifacts bucket;
|
|
130
|
+
# reconciles Zitadel app tenants into the Hub registry)
|
|
131
|
+
# → open http://localhost:9000 — the Hub, your local operations dashboard
|
|
132
|
+
# (sign in via the local Zitadel: admin@local.mesh or dev@local.mesh / LocalDev1!)
|
|
133
|
+
mesh login local # PKCE against the seeded Zitadel (dev@local.mesh / LocalDev1!)
|
|
134
|
+
mesh status # per-component health, endpoints, ports (--json for agents)
|
|
135
|
+
cd <your app> && mesh dev # local mode auto-wires services to this stack:
|
|
136
|
+
# per-app Temporal namespace {tenant}-dev-{app}, auth
|
|
137
|
+
# auto-provisioning, self-registration in the Hub, and
|
|
138
|
+
# service logs shipped to Loki (Hub logs view)
|
|
139
|
+
mesh stop --destroy # tear down incl. volumes (resets seeds)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**The local platform is a machine-wide singleton** — one compose project
|
|
143
|
+
(`mesh-local`), one set of host ports — shared by every checkout and project
|
|
144
|
+
on the machine. App/tenant work composes safely on top of it: `mesh dev
|
|
145
|
+
--local` provisions only tenant-scoped state (Zitadel org, Temporal
|
|
146
|
+
namespace, registry/secret prefixes, per-app mock compose projects), so
|
|
147
|
+
concurrent projects coexist on one running stack. Only `mesh start`/`mesh
|
|
148
|
+
stop` mutate the shared containers, and both refuse to act on a stack a
|
|
149
|
+
DIFFERENT checkout started (compose config drift would recreate shared
|
|
150
|
+
containers out from under the other project) — `mesh start --takeover` /
|
|
151
|
+
`mesh stop --force` override deliberately.
|
|
152
|
+
Device flow prints a URL + short code (e.g. `identity.dev.mesh-platform.trabian.com/device?user_code=XXXX-XXXX`);
|
|
153
|
+
open it, enter the code, wait for `✓ Logged in as …`. Over SSH always use `--device` — the
|
|
154
|
+
browser-callback flow times out. After login, `mesh dev`/`mesh deploy` resolve AWS creds via a
|
|
155
|
+
self-refreshing credential_process (the deployer role), so no separate `--export` eval is needed for those.
|
|
156
|
+
|
|
157
|
+
### 2. Scaffold and run an app locally
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
mesh create-app --tenant acme --name billing --primitives service,database,temporal
|
|
161
|
+
cd tenants/acme/apps/billing && pnpm install
|
|
162
|
+
mesh stack init # personal dev-{github-user} stack (deploy:false)
|
|
163
|
+
mesh deploy up --yes # pulumi up via mesh:deployerRole
|
|
164
|
+
mesh dev # tunnels + secrets + tmux (needs VPN for VPC access)
|
|
165
|
+
mesh dev logs api # tail one service; mesh dev --kill to stop
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 2b. Watch your dev-local stack in the Hub (`mesh hub dev`)
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
cd <your app repo> # a repo with a running `mesh dev` session
|
|
172
|
+
mesh hub dev # → local current-code Hub at http://localhost:9000
|
|
173
|
+
# scoped to this session's tenant: workflow types with
|
|
174
|
+
# live run counts, execution timelines incl. child slices
|
|
175
|
+
mesh hub dev --print-env # inspect the assembled env without launching
|
|
176
|
+
mesh hub dev --kill # tear down (tmux session mesh-hub-dev)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Zero hand-set env vars: the command reads the `mesh dev` session's state file
|
|
180
|
+
and tmux environment — Temporal tunnel address, AWS scratch profile, dev-user
|
|
181
|
+
identity, per-session token-server — and derives the Hub scope
|
|
182
|
+
(`HUB_TENANT`/`HUB_SCOPE_ENV`/`HUB_SCOPE_TENANTS`) from the session's platform
|
|
183
|
+
context. Needs a mesh-platform checkout for the Hub's source (auto-detected
|
|
184
|
+
when you're inside one; otherwise `--platform-dir` / `MESH_PLATFORM_DIR`).
|
|
185
|
+
An empty tenant scope is a loud error, never a blank Hub. On the full-local
|
|
186
|
+
platform (`mesh start`) use its built-in containerized Hub instead.
|
|
187
|
+
|
|
188
|
+
### 3. Concurrent `mesh dev` across git worktrees and sibling apps (auto-isolation)
|
|
189
|
+
|
|
190
|
+
Run the **same plain `mesh dev`** from each worktree's app dir — there is nothing special to
|
|
191
|
+
configure. `mesh dev` derives a deterministic token from the worktree path and threads it through
|
|
192
|
+
the tmux session name, the tmpdir session-state + env-file dir and the Temporal task-queue suffix, so
|
|
193
|
+
two worktrees don't kill each other's session — as long as their directory basenames differ, since the
|
|
194
|
+
session name carries the worktree's sanitized basename, not the hash. The reserved **service-port
|
|
195
|
+
block is derived from (worktree, app)**, not the worktree alone — a repo can hold several apps whose
|
|
196
|
+
sessions run concurrently (e.g. `scu-mesh-apps`' `plaid-token-manager` + `plaid-reporting`), and one
|
|
197
|
+
block per worktree handed both the same ports.
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# worktree A
|
|
201
|
+
cd .worktrees/feature-a/tests/tenants/acme/apps/demo-agent
|
|
202
|
+
mesh dev --dry-run # preview: session name, port block, state/env paths, task queue
|
|
203
|
+
mesh dev # launch (attaches tmux; --headless to skip)
|
|
204
|
+
|
|
205
|
+
# worktree B — SAME command, different shell; auto-isolated
|
|
206
|
+
cd .worktrees/feature-b/tests/tenants/acme/apps/demo-agent
|
|
207
|
+
mesh dev
|
|
208
|
+
|
|
209
|
+
# sibling app in worktree A — same worktree, still its own port block
|
|
210
|
+
cd .worktrees/feature-a/tests/tenants/acme/apps/silverlake-demo
|
|
211
|
+
mesh dev
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
- The **primary checkout** keeps its historical identity (`${project}-dev` session, the app's
|
|
215
|
+
preferred ports). Only **linked worktrees** get an offset session name + a port block in the 40000+
|
|
216
|
+
range. `mesh dev --dry-run` labels which you are (`primary checkout` vs `linked worktree (block N)`).
|
|
217
|
+
- **Port blocks are disjoint by default, not by construction.** The block is a hash bucketed into 63
|
|
218
|
+
slots, so two `(worktree, app)` pairs *can* land on the same block; the in-block free-port probe and
|
|
219
|
+
the ephemeral-port fallback are the backstop when they do — but that backstop is the same
|
|
220
|
+
check-then-bind probe that raced two still-booting sessions onto one port before #2889, so treat a
|
|
221
|
+
shared block as a live hazard, not a handled case. Two consequences worth knowing before you
|
|
222
|
+
debug a collision as a regression:
|
|
223
|
+
- Sibling apps in the **primary checkout** are deliberately excluded — they keep preferred-port
|
|
224
|
+
semantics (block 0) and rely on that probe, so run them from linked worktrees if you need them
|
|
225
|
+
isolated. This is the layout most tenant app repos use day to day.
|
|
226
|
+
- App-scoping raises the number of hashed entities from *#worktrees* to *#worktrees × #apps*, so
|
|
227
|
+
bucket collisions get likelier as you add apps.
|
|
228
|
+
|
|
229
|
+
A deterministic, collision-free allocator that also folds primary checkouts back in is tracked as
|
|
230
|
+
**MESH-2375**.
|
|
231
|
+
- **Do NOT force a shared `--session`** across worktrees — that defeats the auto-isolation and
|
|
232
|
+
reintroduces the collision. Omit `--session` and let it derive per worktree.
|
|
233
|
+
- `mesh dev --kill` / `--status` act only on the current worktree's session.
|
|
234
|
+
- If the stack was last deployed from a *different* worktree, `mesh dev` **refuses** to launch a service
|
|
235
|
+
whose source resolves outside the current worktree (guards against silently running stale code) — re-run
|
|
236
|
+
`mesh deploy up` in this worktree.
|
|
237
|
+
- **Deploying isolated stacks per worktree?** The `mesh dev` isolation above is local-only. To
|
|
238
|
+
`mesh deploy up` a `deploy:false` personal stack from several worktrees at once, give each worktree
|
|
239
|
+
its own stack with `mesh stack init --worktree` — otherwise they collide on SSM export paths
|
|
240
|
+
(`ParameterAlreadyExists`) and the Temporal namespace (both derive from the stack name).
|
|
241
|
+
`mesh deploy up`/`destroy` **warns** when it sees a shared (non-worktree) stack name in a linked worktree.
|
|
242
|
+
|
|
243
|
+
### 4. Deploy (pulumi passthrough)
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
mesh deploy preview
|
|
247
|
+
mesh deploy up --yes
|
|
248
|
+
mesh deploy stack output dev --json
|
|
249
|
+
mesh deploy destroy
|
|
250
|
+
# Requires `mesh:deployerRole` in Pulumi.<stack>.yaml:
|
|
251
|
+
# pulumi config set mesh:deployerRole arn:aws:iam::<acct>:role/<tenant>-<env>-apps-deployer
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`<env>` is the **platform environment** (`dev`, `prod`), which is not always your
|
|
255
|
+
Pulumi stack name — a stack called `dev-jane` still deploys against the `dev`
|
|
256
|
+
platform and so assumes `…-dev-apps-deployer`. The distinction is load-bearing
|
|
257
|
+
beyond the role name: the deployer's KMS-alias grant is scoped to
|
|
258
|
+
`alias/{tenant}-{env}-*`, so an app that creates an alias has to prefix it the
|
|
259
|
+
same way. See [Naming resources so the deployer can create them](https://github.com/mesh-tech/mesh-platform/blob/main/libs/infra-components/docs/concepts/deploying.md#naming-resources-so-the-deployer-can-create-them).
|
|
260
|
+
|
|
261
|
+
### 5. Database access
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
mesh db exec --ssl=require -- npx prisma migrate dev --name init
|
|
265
|
+
mesh db psql # interactive session through the bastion
|
|
266
|
+
eval "$(mesh db env)" # load DATABASE_URL / DB_* into the shell
|
|
267
|
+
mesh db exec --secret <arn> -- node seed.js # direct mode, skips SSM discovery
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### 6. External secrets
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
mesh secrets set external/symitar # interactive (schema from SSM)
|
|
274
|
+
mesh secrets set external/symitar --json '{"baseUrl":"…"}'
|
|
275
|
+
mesh secrets set external/symitar --key 12345 --json '{…}' # multi-instance (key = FI id)
|
|
276
|
+
mesh secrets exec -- node ./script.js # secrets injected as env
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### 7. Read a remote agent's conversation context
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
mesh conversations list --target fub # discover conversation ids
|
|
283
|
+
mesh conversations show <id> --target fub # transcript
|
|
284
|
+
mesh conversations artifacts <id> --target fub
|
|
285
|
+
mesh artifacts get <id>:<artifactId> --target fub
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
`--target` resolves the same `~/.config/mesh/agent-targets.json` registry the
|
|
289
|
+
MCP `agent_*` tools use; see the dedicated
|
|
290
|
+
`libs/mesh-cli/skills/pull-remote-agent-context` skill for the full recipe
|
|
291
|
+
(registry format, auth model, the `conversation_unavailable` → `mesh temporal
|
|
292
|
+
recover-conversation` break-glass path, and the MCP-vs-CLI relationship).
|
|
293
|
+
|
|
294
|
+
### 8. Relaunch safety — don't strand live conversations
|
|
295
|
+
|
|
296
|
+
For a **code-only** change, prefer a scoped `mesh dev restart <service>` over a full
|
|
297
|
+
`mesh dev` relaunch — it's faster and touches only that service. Restart the
|
|
298
|
+
**worker** only when you actually changed worker/workflow code.
|
|
299
|
+
|
|
300
|
+
Both a relaunch and a `restart <worker>` recreate the Temporal worker onto current
|
|
301
|
+
code. If the **workflow** source (`agent-sdk` / `workflow-interpreter` /
|
|
302
|
+
`agent-contracts`) changed since the session started, in-flight conversations replay
|
|
303
|
+
against the new code — a replay-incompatible change **strands** them. `mesh dev` now
|
|
304
|
+
fingerprints that source at launch and **warns + refuses (use `--force`)** when it
|
|
305
|
+
changed on a relaunch/worker-restart. The fix is not `--force`: keep the change
|
|
306
|
+
replay-compatible — gate it with `wf.patched()` and regenerate the replay goldens
|
|
307
|
+
(see the `temporal-workflow-safety` skill + the CI replay gate). Restarting unchanged
|
|
308
|
+
code, or a non-worker service (ui/api), never warns.
|
|
309
|
+
|
|
310
|
+
For **config/deploy** changes (not code): `mesh dev restart <svc> --refresh-env`
|
|
311
|
+
re-reads stack/SSM output; if the *topology* changed, run `mesh deploy up` first
|
|
312
|
+
(`mesh dev doctor` flags config staleness).
|
|
313
|
+
|
|
314
|
+
## Config / environment requirements
|
|
315
|
+
|
|
316
|
+
| Need | Source |
|
|
317
|
+
|---|---|
|
|
318
|
+
| Tenant / env / stage | flags (`-t/-e`, `--stage`) → `MESH_TENANT`/`MESH_STAGE`/`SST_STAGE` env → Pulumi config in cwd/parents → defaults (`mesh`/`dev`) |
|
|
319
|
+
| AWS creds | ambient env → cached Zitadel JWT (`mesh login`) → AWS SSO profile; region from `AWS_REGION`/`AWS_DEFAULT_REGION` else `us-east-2` |
|
|
320
|
+
| Login config | `~/.config/mesh/config.json`; creds cache `~/.config/mesh/credentials.json` |
|
|
321
|
+
| Deploy role | `mesh:deployerRole` (and optional `mesh:adminDeployerRole`) in `Pulumi.<stack>.yaml` |
|
|
322
|
+
| Login role for `--export` | `--role` → `MESH_AWS_ROLE` → cached `defaultRole` for the context |
|
|
323
|
+
| Registry | `@mesh-tech` scope; CodeArtifact token written to `~/.npmrc` (12h TTL) |
|
|
324
|
+
| `vpn`, `temporal --show-payloads` | a working `kubectl` kubeconfig for the target EKS cluster |
|
|
325
|
+
| Temporal client / S3 upload | optional deps `@temporalio/client`, `@aws-sdk/client-s3` (lazy-loaded) |
|
|
326
|
+
|
|
327
|
+
## Failure modes / gotchas
|
|
328
|
+
|
|
329
|
+
| Symptom | Cause | Fix |
|
|
330
|
+
|---|---|---|
|
|
331
|
+
| `No Pulumi.yaml found` | run outside a Pulumi app dir | cd into the app (deploy/stack/temporal use `findAppRoot`) |
|
|
332
|
+
| `No mesh:deployerRole found` | stack config missing the role | `mesh deploy config set mesh:deployerRole <arn>` |
|
|
333
|
+
| `Could not determine stack` (deploy) | no selected stack & no `--stack` | `mesh deploy stack select <name>` or pass `--stack` |
|
|
334
|
+
| `artifacts get` → ECONNREFUSED / 404 | agent API down or convo expired | start API (`mesh dev`) or pass `--api-url`; restart API after code changes |
|
|
335
|
+
| `login` config not found | context not discoverable | a known first-party short context (`mesh.dev`) resolves anonymously — no AWS needed. Otherwise use the platform's full domain (`mesh login dev.<tenant>.meshtech.io`). Only if neither works: ensure AWS SSO is active + the platform is deployed (SSM `cliClientId`), or add config to `~/.config/mesh/config.json` |
|
|
336
|
+
| `vpn`/`temporal --show-payloads` fail | kubeconfig not set / expired creds | refresh the tenant cluster kubeconfig (`mesh vpn connect <ctx>` wires it; kubeconfig absorption into `mesh deploy` is planned) then retry | <!-- skill-lint-disable-next-line — next row's backticked `kubectl …` is a quoted ERROR SYMPTOM, not an operator command; the row's fix column already routes through mesh dev -->|
|
|
337
|
+
| `kubectl could not read a kubeconfig … macOS blocks it` (from `mesh kubectl`/`logs`/`exec`/`temporal` in a bare shell) | macOS Full-Disk-Access blocks reading `~/.kube` from a shell outside the `mesh dev` session | run the command **inside** the `mesh dev` tmux window, or `export KUBECONFIG=$TMPDIR/mesh-dev-sessions/<session>.kubeconfig` first |
|
|
338
|
+
| `mesh temporal …` won't authenticate against a **deployed** Temporal | passing `--address` (or `TEMPORAL_ADDRESS`) skips the app/stack resolution that mints a Zitadel **Bearer** — auth falls back to ambient env | omit `--address` and run from the app dir so `mesh temporal` resolves the authenticated frontend over the tunnel; use `--address` only for a local/unauthenticated Temporal |
|
|
339
|
+
| `mesh dev` chose "VPN direct" then api/worker spin on `ECONNREFUSED …:27233` | tailnet-blind VPN *presence* check picked direct routing the mesh VPC doesn't actually serve | **no manual fallback needed** — current `mesh dev` TCP-probes the frontend and auto-falls back to SSM tunnels (MESH-2016); if still stuck, force `--transport ssm` (or `--no-vpn`) |
|
|
340
|
+
| `mesh dev` / `mesh vpn tunnel up` → `Tunnel port(s) for tenant '<t>' are bound by a process mesh does not own` | a foreign or orphaned listener holds a forwarder port; mesh refuses to adopt it rather than route traffic to the wrong upstream (MESH-2407) | `mesh vpn -t <t> tunnel down --stop` to reap mesh-owned runners; if the port is still held, `lsof -nP -iTCP:<port> -sTCP:LISTEN` and stop that process (if it names another mesh runner, it belongs to a different tenant — tear that one down). `mesh vpn -t <t> tunnel status` shows `Runner: owned (verified)` when healthy |
|
|
341
|
+
| `mesh vpn tunnel down`/`up` or `mesh dev` → `Refusing to signal <the tunnel supervisor pid \| the tunnel runner process group \| the VPN daemon pid> recorded for tenant '<t>' — …`, or `Refusing to signal a tunnel runner pid discovered from 'ps' for tenant '<t>' — …` | the pid is corrupt or stale — from `tunnel-state.json` / `runner.json` / `daemon.json` (truncated write, hand edit, older build) for the first three, or from the live `ps` argv scan for the fourth. POSIX `kill(2)` overloads the pid argument and teardown negates before signalling, so a `1` there would SIGTERM every process you can signal — mesh refuses it instead | usually **nothing** — it is a warning, the rest of the teardown still runs and the state file is cleared, so re-running the command is clean. If it recurs: **when the message names a file**, `rm` that exact path; **the `discovered from 'ps'` variant names none** — there is no state file to clear, so just re-run. Either way finish with `mesh vpn -t <t> tunnel status` to confirm |
|
|
342
|
+
| `mesh kubectl`/`logs`/`exec` → `Could not resolve the EKS cluster … Parameter tried: /mesh-platform/<name>/<env>/core/eks`; `mesh dev` → `EKS cluster resolve failed (/mesh-platform/<name>/<env>/core/eks): …` | the platform segment of the SSM path is wrong (or the platform core layer isn't deployed) — cluster data lives under the app's HUB platform name, and an `AccessDeniedException` here usually means the wrong path, not missing SSM permissions | check `mesh:platform` in the app's `Pulumi.<stack>.yaml` (its `name` is the hub, e.g. `trabian`) and log into that platform's context (`mesh login <platform>.<env>`) |
|
|
343
|
+
| 401/403 installing `@mesh-tech/*` | stale CodeArtifact token | `mesh registry login` (or `--ci` in CI) |
|
|
344
|
+
| 401 installing a **public** package (`npm view lodash version` fails) | an unscoped `registry=<codeartifact>` line in `~/.npmrc` makes CodeArtifact the DEFAULT registry, so public packages resolve through it and 401 at the 12h token expiry | `mesh registry login` — it removes the line after backing `~/.npmrc` up; confirm with `npm config get registry` (expect `https://registry.npmjs.org/`) |
|
|
345
|
+
| `--export` prints nothing | no role resolved | pass `--role <arn>` or set `MESH_AWS_ROLE` |
|
|
346
|
+
| `--export` / `EPERM … ~/.aws` in a sandbox | `~/.aws` not writable | it now auto-falls back to a mesh-managed config (`~/.config/mesh/aws-config`) and also exports `AWS_CONFIG_FILE`; or prefer `mesh deploy <op>` (no shell profile needed) |
|
|
347
|
+
| `workflow extract-ir` no S3 upload | only one of `--app`/`--upload` given | pass both, or omit both to print JSON |
|
|
348
|
+
|
|
349
|
+
## Programmatic API
|
|
350
|
+
|
|
351
|
+
`@mesh-tech/mesh-cli` re-exports its utils (`src/utils/index.ts`):
|
|
352
|
+
|
|
353
|
+
```ts
|
|
354
|
+
import { detectContext, getPlatformBastionInfo } from "@mesh-tech/mesh-cli";
|
|
355
|
+
const ctx = detectContext(); // { tenant, stage, ... }
|
|
356
|
+
const bastion = await getPlatformBastionInfo(ctx.tenant, ctx.platformEnv);
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Exports include `detectContext`, `getPlatformBastionInfo` (bastion), credentials,
|
|
360
|
+
pulumi, vpn, and log helpers.
|
|
361
|
+
|
|
362
|
+
## See also
|
|
363
|
+
|
|
364
|
+
- `@mesh-tech/app-kit#core` — app-kit bundles this CLI; consumers usually invoke it as `pnpm mesh <cmd>`
|
|
365
|
+
- `@mesh-tech/credentials#core` — credential resolution the auth/deploy flows build on
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pull-remote-agent-context
|
|
3
|
+
description: >
|
|
4
|
+
Read a deployed Mesh agent's conversation history, artifacts, or workflow
|
|
5
|
+
design from the `mesh` CLI. Activate when asked to pull/read/inspect a
|
|
6
|
+
hosted agent's conversation transcript, list its conversations, fetch a
|
|
7
|
+
workflow artifact/design it produced, or when the `agent_*` MCP tools
|
|
8
|
+
(agent_list_conversations, agent_check_conversation, agent_get_artifacts,
|
|
9
|
+
agent_get_workflow_design) are unavailable and the same read needs to
|
|
10
|
+
happen via the CLI instead.
|
|
11
|
+
metadata:
|
|
12
|
+
version: '0.1'
|
|
13
|
+
category: 'tooling'
|
|
14
|
+
type: intent
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Pull a deployed agent's conversation context
|
|
18
|
+
|
|
19
|
+
`mesh conversations` (alias `mesh conv`) reads a deployed Mesh agent's
|
|
20
|
+
conversations directly from its agent-api, over the same read surface the
|
|
21
|
+
`agent_*` MCP tools use. This is the CLI-native path when those MCP tools
|
|
22
|
+
aren't wired up, or when you're already in a shell.
|
|
23
|
+
|
|
24
|
+
## The recipe
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
mesh conversations list --target <name> # discover conversation ids
|
|
28
|
+
mesh conversations show <id> --target <name> # render the transcript
|
|
29
|
+
mesh conversations artifacts <id> --target <name> # list its artifacts
|
|
30
|
+
mesh artifacts get <id>:<artifactId> --target <name> # download artifact files
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## One-shot: `mesh conversations pull` (recommended)
|
|
34
|
+
|
|
35
|
+
To pull a whole conversation + everything it produced into a session bundle in
|
|
36
|
+
one command — the fast path when you're feeding a workflow-builder conversation
|
|
37
|
+
into a coding session:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
mesh conversations pull <id> --target <name> -o <dir>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
It writes:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
<dir>/
|
|
47
|
+
index.json # conversation meta, artifact map, saveLocations, subagent tree, warnings[]
|
|
48
|
+
conversation.md # the transcript (intent)
|
|
49
|
+
designs/<slug>/
|
|
50
|
+
design-ir.json # the LIVE design IR (authoritative; resolved server-side)
|
|
51
|
+
manifest.json # realized bindings (signals + service ops) — from the design's vcs folder
|
|
52
|
+
README.md # + any other docs the design's folder holds, verbatim
|
|
53
|
+
design-ir.saved.json # ONLY if the saved IR drifted from live (a warning is emitted)
|
|
54
|
+
ui/<slug>.json # agent-built UI specs
|
|
55
|
+
subagents/<childId>.md # recursive delegate transcripts (childId "/" → "__")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Key behaviors:
|
|
59
|
+
|
|
60
|
+
- **Designs come from the agent-api**, which resolves the latest IR itself — no
|
|
61
|
+
draft-branch guessing for the IR.
|
|
62
|
+
- **Each design also pulls its OWN vcs folder verbatim** (a scoped shallow clone
|
|
63
|
+
of just that design's repo, resolving the `drafts/*` ref that carries it), so
|
|
64
|
+
docs/notes beyond the IR ride along. `--no-vcs` skips this (IR-only).
|
|
65
|
+
- **Everything else the conversation referenced is cataloged, never cloned** —
|
|
66
|
+
any tenant's knowledge-base / context repo (a `resource: vcs` drive-ref,
|
|
67
|
+
whatever it's named) and any other artifact kind appears in
|
|
68
|
+
`index.json.references[]` with a ready-to-run `pullHint`, but its content is
|
|
69
|
+
not pulled. Pull a **specific** doc on demand (one path, not the whole repo)
|
|
70
|
+
with `mesh vcs get <repo> <path> --target <name>` (CLI) or `agent_get_repo_doc`
|
|
71
|
+
(MCP) — browse `conversation.md` to see which docs matter.
|
|
72
|
+
- **Subagents recurse by default** (cycle-guarded); `--no-recursive` for direct
|
|
73
|
+
delegates only.
|
|
74
|
+
- **Best-effort**: nothing aborts the pull — per-unit failures land in
|
|
75
|
+
`index.json.warnings[]`.
|
|
76
|
+
|
|
77
|
+
Reach for the granular verbs below when you want just the transcript, just the
|
|
78
|
+
artifact list, or a single artifact's files.
|
|
79
|
+
|
|
80
|
+
`list`/`show`/`artifacts` all accept the same `--target <name>` /
|
|
81
|
+
`--api-url <url>` / `--context <ctx>` / `--json` options (`mesh artifacts get`
|
|
82
|
+
takes `--target`/`--api-url`/`--context` plus `-o/--output <dir>`, no
|
|
83
|
+
`--json` — it always writes files). Start with `list` unless you already have
|
|
84
|
+
a conversation id.
|
|
85
|
+
|
|
86
|
+
## The shared registry (`--target`)
|
|
87
|
+
|
|
88
|
+
`--target <name>` resolves against `~/.config/mesh/agent-targets.json`
|
|
89
|
+
(override with env `MESH_AGENT_TARGETS`) — **the exact same registry and
|
|
90
|
+
names the MCP `agent_*` tools use** (`@mesh-tech/agent-targets`, consumed by
|
|
91
|
+
both `mesh-cli` and `@mesh-tech/mesh-mcp`). `--target fub` on the CLI and
|
|
92
|
+
`target: "fub"` on `agent_send_message` hit the same origin with the same
|
|
93
|
+
identity. A registry entry looks like:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"defaultTarget": "hub",
|
|
98
|
+
"targets": {
|
|
99
|
+
"fub": {
|
|
100
|
+
"apiBaseUrl": "https://...",
|
|
101
|
+
"conversationPathPrefix": "/c",
|
|
102
|
+
"tenant": "fub",
|
|
103
|
+
"env": "dev",
|
|
104
|
+
"loginContext": "mesh.dev"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**`mesh agent-targets add/refresh/list` (the SSM-backed generator) is NOT
|
|
111
|
+
shipped yet.** Do not tell a user or agent to run it. Until it exists:
|
|
112
|
+
- If the registry file already has the target you need, just pass
|
|
113
|
+
`--target <name>`.
|
|
114
|
+
- If it doesn't (or the file doesn't exist), either hand-author an entry in
|
|
115
|
+
`~/.config/mesh/agent-targets.json` (schema above; see
|
|
116
|
+
`packages/agent-remote/agent-targets.example.json` for a fuller example),
|
|
117
|
+
or skip the registry entirely and pass `--api-url <url>` (+ `--context <ctx>`,
|
|
118
|
+
default `mesh.dev`) ad hoc — no registry lookup happens in that case.
|
|
119
|
+
|
|
120
|
+
Resolution precedence: `--api-url` (if given) > `--target` (if given,
|
|
121
|
+
resolved from the registry) > the registry's `defaultTarget` > the
|
|
122
|
+
`AGENT_API_URL`/`API_URL` env vars > `http://localhost:8787`. An unknown
|
|
123
|
+
`--target` name errors listing the available names.
|
|
124
|
+
|
|
125
|
+
## Auth model
|
|
126
|
+
|
|
127
|
+
Auth is a Zitadel bearer, the same one `mesh login <context>` already caches
|
|
128
|
+
— no AWS role needed just to read. Each registry entry's `loginContext`
|
|
129
|
+
picks which cached login to use (default `mesh.dev`); with `--api-url`,
|
|
130
|
+
pass `--context <ctx>` to pick it explicitly. One `mesh login mesh.dev`
|
|
131
|
+
(device flow works headless) reaches any deployed agent through its
|
|
132
|
+
oauth2-proxy. A 401/403/redirect from an agent-api call means auth didn't
|
|
133
|
+
reach it — re-run `mesh login <that context>`.
|
|
134
|
+
|
|
135
|
+
## MCP tools unavailable? Same registry, direct CLI path
|
|
136
|
+
|
|
137
|
+
When the `agent_*` MCP tools (`agent_list_conversations`,
|
|
138
|
+
`agent_check_conversation`, `agent_get_artifacts`,
|
|
139
|
+
`agent_get_workflow_design`, `agent_list_targets`, ...) aren't reachable —
|
|
140
|
+
no MCP server configured, or you're a plain shell/CLI agent — `mesh
|
|
141
|
+
conversations` reaches the identical agent-api directly, with the same
|
|
142
|
+
`--target` name and the same login. Nothing is lost by going CLI-only:
|
|
143
|
+
list → show → artifacts covers list/read/artifacts; `mesh artifacts get`
|
|
144
|
+
covers file export; workflow-design (the MCP's `agent_get_workflow_design`)
|
|
145
|
+
has no direct CLI verb yet — get it via `mesh conversations artifacts <id>`
|
|
146
|
+
(artifact index) plus `mesh artifacts get <id>:<artifactId>` for the IR/files.
|
|
147
|
+
|
|
148
|
+
## Transcript break-glass: `conversation_unavailable`
|
|
149
|
+
|
|
150
|
+
`mesh conversations show <id>` reads the **live** worker (fast, decoded).
|
|
151
|
+
If the worker can no longer replay that workflow (code drift), it 503s with
|
|
152
|
+
`conversation_unavailable` and the CLI's error message already includes the
|
|
153
|
+
next step:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
mesh temporal recover-conversation <id>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
This reconstructs the transcript from durable Temporal history instead
|
|
160
|
+
(needs the Temporal encoding key; see the `core` skill's `temporal` row).
|
|
161
|
+
Add `--snapshot` for a structured, store-ready `{ messages, artifacts,
|
|
162
|
+
focus }` blob instead of a markdown transcript.
|
|
163
|
+
|
|
164
|
+
## Output
|
|
165
|
+
|
|
166
|
+
- Piped or redirected (non-TTY), or `--json` passed: compact JSON, one line,
|
|
167
|
+
field names mirroring the agent-api payload — parse this.
|
|
168
|
+
- A TTY without `--json`: an aligned table (`list`: double-space-padded
|
|
169
|
+
columns, `ID TITLE UPDATED` — NOT `·`-separated; `artifacts`:
|
|
170
|
+
`ARTIFACT-ID · KIND · TITLE` + a ready-to-copy `mesh artifacts
|
|
171
|
+
get <id>:<artifactId>` download line; `show`: `role: content` blocks with
|
|
172
|
+
`tool-calls:`/`artifacts:` notes).
|
|
173
|
+
|
|
174
|
+
An agent scripting this should just pipe (`mesh conversations list --target
|
|
175
|
+
fub | jq ...`) rather than pass `--json` — output auto-detects non-TTY.
|
|
176
|
+
|
|
177
|
+
## Errors, decoded
|
|
178
|
+
|
|
179
|
+
| Symptom | Meaning | Fix |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| `auth did not reach the agent` | 401/403/redirect | `mesh login <loginContext>` (the target's, or `--context`) |
|
|
182
|
+
| `conversation/artifact not found ... (<id>)` | 404, or not owned by this identity | `mesh conversations list --target <name>` to see valid ids |
|
|
183
|
+
| `... conversation_unavailable ... try: mesh temporal recover-conversation <id>` | 503, worker can't replay | run the suggested `recover-conversation` |
|
|
184
|
+
| `Unknown target "<name>". Available: ...` | `--target` not in the registry | pick a listed name, hand-author the entry, or use `--api-url` |
|
|
185
|
+
| `No agent target given and no registry ...` | no `--target`/`--api-url` and no registry file | pass `--api-url <url>`, or hand-author `~/.config/mesh/agent-targets.json` |
|
|
186
|
+
| `Registry at <path> is invalid: ...` | the JSON fails schema validation | fix the file, or pass `--api-url` |
|
|
187
|
+
|
|
188
|
+
## See also
|
|
189
|
+
|
|
190
|
+
- `libs/mesh-cli/skills/core/SKILL.md` — full `mesh` command reference,
|
|
191
|
+
including the `conversations`/`artifacts`/`temporal` rows this skill
|
|
192
|
+
builds on.
|
|
193
|
+
- `packages/agent-remote/agent-targets.example.json` — a worked registry
|
|
194
|
+
file with `hub`/`fub`/`acme`/`local` entries.
|