@zivis/cli 0.1.0-alpha.5 → 0.1.0-alpha.52
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/LICENSE +201 -0
- package/README.md +31 -0
- package/dist/commands/app/index.d.ts +0 -8
- package/dist/commands/app/index.js +8 -18
- package/dist/commands/assurance/index.d.ts +35 -0
- package/dist/commands/assurance/index.js +154 -0
- package/dist/commands/auth/bind.d.ts +4 -0
- package/dist/commands/auth/bind.js +97 -0
- package/dist/commands/auth/index.js +21 -2
- package/dist/commands/auth/init.d.ts +2 -0
- package/dist/commands/auth/init.js +248 -96
- package/dist/commands/auth/login.d.ts +2 -0
- package/dist/commands/auth/login.js +136 -18
- package/dist/commands/auth/logout.js +19 -7
- package/dist/commands/auth/sessions.js +7 -4
- package/dist/commands/auth/status.js +33 -12
- package/dist/commands/auth/token.d.ts +4 -0
- package/dist/commands/auth/token.js +73 -0
- package/dist/commands/check/index.d.ts +2 -0
- package/dist/commands/check/index.js +463 -0
- package/dist/commands/credits/index.js +2 -3
- package/dist/commands/gate/index.d.ts +2 -0
- package/dist/commands/gate/index.js +171 -0
- package/dist/commands/inspect/index.d.ts +2 -0
- package/dist/commands/inspect/index.js +136 -0
- package/dist/commands/mcp/index.js +113 -14
- package/dist/commands/open/index.d.ts +0 -8
- package/dist/commands/open/index.js +0 -11
- package/dist/commands/run/index.d.ts +2 -0
- package/dist/commands/run/index.js +206 -0
- package/dist/commands/scan/index.js +3 -8
- package/dist/commands/share/index.d.ts +14 -0
- package/dist/commands/share/index.js +100 -0
- package/dist/commands/sync/index.d.ts +2 -0
- package/dist/commands/sync/index.js +193 -0
- package/dist/commands/target/index.js +0 -3
- package/dist/commands/test/index.d.ts +2 -0
- package/dist/commands/test/index.js +198 -0
- package/dist/commands/threatmodel/index.d.ts +2 -0
- package/dist/commands/threatmodel/index.js +167 -0
- package/dist/index.js +28 -3
- package/dist/internal/application-binding.d.ts +8 -0
- package/dist/internal/application-binding.js +167 -0
- package/dist/internal/binding-token-mint.d.ts +33 -0
- package/dist/internal/binding-token-mint.js +174 -0
- package/dist/internal/change-recommendation.d.ts +6 -0
- package/dist/internal/change-recommendation.js +113 -0
- package/dist/internal/cli-output.d.ts +16 -0
- package/dist/internal/cli-output.js +39 -0
- package/dist/internal/devx-run.d.ts +129 -0
- package/dist/internal/devx-run.js +39 -0
- package/dist/internal/extractor/adapters/go/index.d.ts +0 -4
- package/dist/internal/extractor/adapters/go/index.js +0 -6
- package/dist/internal/extractor/adapters/go/manifest.d.ts +0 -17
- package/dist/internal/extractor/adapters/go/manifest.js +19 -25
- package/dist/internal/extractor/adapters/go/parser.d.ts +0 -4
- package/dist/internal/extractor/adapters/go/parser.js +0 -5
- package/dist/internal/extractor/adapters/go/scanner.d.ts +0 -20
- package/dist/internal/extractor/adapters/go/scanner.js +0 -43
- package/dist/internal/extractor/adapters/python/index.d.ts +0 -3
- package/dist/internal/extractor/adapters/python/index.js +0 -4
- package/dist/internal/extractor/adapters/python/manifest.d.ts +0 -8
- package/dist/internal/extractor/adapters/python/manifest.js +21 -18
- package/dist/internal/extractor/adapters/python/parser.d.ts +0 -3
- package/dist/internal/extractor/adapters/python/parser.js +0 -4
- package/dist/internal/extractor/adapters/python/scanner.d.ts +0 -18
- package/dist/internal/extractor/adapters/python/scanner.js +1 -54
- package/dist/internal/extractor/adapters/typescript/index.d.ts +0 -7
- package/dist/internal/extractor/adapters/typescript/index.js +1 -21
- package/dist/internal/extractor/adapters/typescript/manifest.d.ts +0 -14
- package/dist/internal/extractor/adapters/typescript/manifest.js +26 -17
- package/dist/internal/extractor/adapters/typescript/parser.d.ts +0 -8
- package/dist/internal/extractor/adapters/typescript/parser.js +0 -9
- package/dist/internal/extractor/adapters/typescript/scanner.d.ts +0 -24
- package/dist/internal/extractor/adapters/typescript/scanner.js +0 -43
- package/dist/internal/extractor/graph-builder.d.ts +10 -0
- package/dist/internal/extractor/graph-builder.js +245 -0
- package/dist/internal/extractor/graph-types.d.ts +89 -0
- package/dist/internal/extractor/graph-types.js +1 -0
- package/dist/internal/extractor/index.d.ts +0 -14
- package/dist/internal/extractor/index.js +0 -13
- package/dist/internal/extractor/types.d.ts +0 -45
- package/dist/internal/extractor/types.js +0 -27
- package/dist/internal/extractor/walker.d.ts +0 -18
- package/dist/internal/extractor/walker.js +0 -18
- package/dist/internal/gate-evaluate.d.ts +50 -0
- package/dist/internal/gate-evaluate.js +111 -0
- package/dist/internal/gate-policy.d.ts +38 -0
- package/dist/internal/gate-policy.js +167 -0
- package/dist/internal/git-metadata.d.ts +8 -0
- package/dist/internal/git-metadata.js +38 -0
- package/dist/internal/git.d.ts +9 -0
- package/dist/internal/git.js +45 -0
- package/dist/internal/github-linkage-prompt.d.ts +7 -0
- package/dist/internal/github-linkage-prompt.js +95 -0
- package/dist/internal/ide-setup.d.ts +17 -7
- package/dist/internal/ide-setup.js +379 -46
- package/dist/internal/inventory-sync.d.ts +74 -0
- package/dist/internal/inventory-sync.js +189 -0
- package/dist/internal/org-picker.d.ts +11 -0
- package/dist/internal/org-picker.js +34 -0
- package/dist/internal/orgs.js +0 -1
- package/dist/internal/packs/cache.d.ts +8 -0
- package/dist/internal/packs/cache.js +60 -0
- package/dist/internal/packs/index.d.ts +10 -0
- package/dist/internal/packs/index.js +8 -0
- package/dist/internal/packs/integrity.d.ts +9 -0
- package/dist/internal/packs/integrity.js +24 -0
- package/dist/internal/packs/jcs.d.ts +2 -0
- package/dist/internal/packs/jcs.js +57 -0
- package/dist/internal/packs/local-paths.d.ts +4 -0
- package/dist/internal/packs/local-paths.js +26 -0
- package/dist/internal/packs/npm-registry-client.d.ts +14 -0
- package/dist/internal/packs/npm-registry-client.js +87 -0
- package/dist/internal/packs/registry-client.d.ts +9 -0
- package/dist/internal/packs/registry-client.js +25 -0
- package/dist/internal/packs/resolve.d.ts +8 -0
- package/dist/internal/packs/resolve.js +89 -0
- package/dist/internal/packs/semver.d.ts +9 -0
- package/dist/internal/packs/semver.js +57 -0
- package/dist/internal/packs/signing.d.ts +5 -0
- package/dist/internal/packs/signing.js +56 -0
- package/dist/internal/packs/types.d.ts +77 -0
- package/dist/internal/packs/types.js +20 -0
- package/dist/internal/project-binding.d.ts +1 -0
- package/dist/internal/project-binding.js +16 -11
- package/dist/internal/resolve-init-session.d.ts +8 -0
- package/dist/internal/resolve-init-session.js +36 -0
- package/dist/internal/run-workdir.d.ts +2 -0
- package/dist/internal/run-workdir.js +19 -0
- package/dist/internal/security-context.d.ts +63 -0
- package/dist/internal/security-context.js +50 -0
- package/dist/internal/sync-outbox.d.ts +40 -0
- package/dist/internal/sync-outbox.js +66 -0
- package/dist/internal/target-auth/api-config.d.ts +0 -17
- package/dist/internal/target-auth/api-config.js +0 -18
- package/dist/internal/target-auth/config.d.ts +0 -12
- package/dist/internal/target-auth/config.js +0 -13
- package/dist/internal/target-auth/index.d.ts +0 -18
- package/dist/internal/target-auth/index.js +0 -19
- package/dist/internal/target-auth/keychain.d.ts +0 -18
- package/dist/internal/target-auth/keychain.js +3 -23
- package/dist/internal/target-auth/types.d.ts +0 -26
- package/dist/internal/target-auth/types.js +0 -10
- package/dist/internal/target-auth/workos.d.ts +0 -15
- package/dist/internal/target-auth/workos.js +9 -18
- package/dist/internal/test-scope.d.ts +99 -0
- package/dist/internal/test-scope.js +101 -0
- package/dist/internal/threatmodel-run-state.d.ts +15 -0
- package/dist/internal/threatmodel-run-state.js +43 -0
- package/dist/internal/threatmodel-run.d.ts +85 -0
- package/dist/internal/threatmodel-run.js +159 -0
- package/dist/internal/trust-room-link.d.ts +10 -0
- package/dist/internal/trust-room-link.js +15 -0
- package/dist/internal/zivis-local-state.d.ts +1 -0
- package/dist/internal/zivis-local-state.js +22 -0
- package/package.json +21 -5
- package/dist/commands/app/index.js.map +0 -1
- package/dist/commands/auth/index.js.map +0 -1
- package/dist/commands/auth/init.js.map +0 -1
- package/dist/commands/auth/login.js.map +0 -1
- package/dist/commands/auth/logout.js.map +0 -1
- package/dist/commands/auth/sessions.js.map +0 -1
- package/dist/commands/auth/status.js.map +0 -1
- package/dist/commands/credits/index.js.map +0 -1
- package/dist/commands/mcp/index.js.map +0 -1
- package/dist/commands/open/index.js.map +0 -1
- package/dist/commands/scan/index.js.map +0 -1
- package/dist/commands/target/index.js.map +0 -1
- package/dist/commands/tm/index.d.ts +0 -2
- package/dist/commands/tm/index.js +0 -266
- package/dist/commands/tm/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal/extractor/adapters/go/index.js.map +0 -1
- package/dist/internal/extractor/adapters/go/manifest.js.map +0 -1
- package/dist/internal/extractor/adapters/go/parser.js.map +0 -1
- package/dist/internal/extractor/adapters/go/scanner.js.map +0 -1
- package/dist/internal/extractor/adapters/python/index.js.map +0 -1
- package/dist/internal/extractor/adapters/python/manifest.js.map +0 -1
- package/dist/internal/extractor/adapters/python/parser.js.map +0 -1
- package/dist/internal/extractor/adapters/python/scanner.js.map +0 -1
- package/dist/internal/extractor/adapters/typescript/index.js.map +0 -1
- package/dist/internal/extractor/adapters/typescript/manifest.js.map +0 -1
- package/dist/internal/extractor/adapters/typescript/parser.js.map +0 -1
- package/dist/internal/extractor/adapters/typescript/scanner.js.map +0 -1
- package/dist/internal/extractor/index.js.map +0 -1
- package/dist/internal/extractor/types.js.map +0 -1
- package/dist/internal/extractor/walker.js.map +0 -1
- package/dist/internal/ide-setup.js.map +0 -1
- package/dist/internal/orgs.js.map +0 -1
- package/dist/internal/project-binding.js.map +0 -1
- package/dist/internal/target-auth/api-config.js.map +0 -1
- package/dist/internal/target-auth/config.js.map +0 -1
- package/dist/internal/target-auth/index.js.map +0 -1
- package/dist/internal/target-auth/keychain.js.map +0 -1
- package/dist/internal/target-auth/types.js.map +0 -1
- package/dist/internal/target-auth/workos.js.map +0 -1
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import * as readline from "node:readline/promises";
|
|
2
|
-
import { login, getStorageName, saveSessionEntry
|
|
3
|
-
import { DEFAULT_CONFIG } from "@zivis/mcp/types";
|
|
2
|
+
import { login, getStorageName, saveSessionEntry } from "@zivis/mcp/auth";
|
|
3
|
+
import { credentialStorageFromConfig, DEFAULT_CONFIG } from "@zivis/mcp/types";
|
|
4
|
+
import { resolveConfigFromBinding } from "@zivis/mcp/project-binding";
|
|
4
5
|
import { fetchUserOrgs, extractEmail } from "../../internal/orgs.js";
|
|
5
6
|
import { ensureProjectBinding } from "../../internal/project-binding.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import { ensureApplicationBinding } from "../../internal/application-binding.js";
|
|
8
|
+
import { discardOauthAfterLogin, tryAutoMintBindingTokenAfterLogin, } from "../../internal/binding-token-mint.js";
|
|
9
|
+
import { decodeJwtPayload } from "@zivis/mcp/auth/jwt";
|
|
10
|
+
import { detectIdesInRepo, writeGuidance } from "../../internal/ide-setup.js";
|
|
11
|
+
import { buildLinkagePrompt } from "../../internal/github-linkage-prompt.js";
|
|
12
|
+
import { resolveExistingSessionAuth } from "../../internal/resolve-init-session.js";
|
|
13
|
+
async function maybePromptGitHubLinkage(config) {
|
|
14
|
+
try {
|
|
15
|
+
const msg = await buildLinkagePrompt({ config });
|
|
16
|
+
if (msg)
|
|
17
|
+
console.log(msg);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
}
|
|
10
21
|
}
|
|
11
22
|
async function prompt(question) {
|
|
12
23
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
@@ -17,119 +28,260 @@ async function prompt(question) {
|
|
|
17
28
|
rl.close();
|
|
18
29
|
}
|
|
19
30
|
}
|
|
31
|
+
async function offerGuidanceInstall(cwd) {
|
|
32
|
+
const detectedIdes = detectIdesInRepo(cwd);
|
|
33
|
+
const otherIdes = detectedIdes.filter((ide) => ide !== "claude-code-cli");
|
|
34
|
+
const targets = ["claude-code-cli", ...otherIdes];
|
|
35
|
+
const ideLabels = {
|
|
36
|
+
cursor: "Cursor",
|
|
37
|
+
"claude-code-cli": "Claude Code (CLAUDE.md) / Codex (AGENTS.md)",
|
|
38
|
+
"vscode-copilot": "VS Code (Copilot)",
|
|
39
|
+
"vscode-claude": "VS Code (Claude)",
|
|
40
|
+
cline: "Cline",
|
|
41
|
+
windsurf: "Windsurf",
|
|
42
|
+
};
|
|
43
|
+
const ideNames = targets.map((ide) => ideLabels[ide] ?? ide).join(", ");
|
|
44
|
+
console.log(`\nSet up AI agent guidance for: ${ideNames}`);
|
|
45
|
+
const ans = await prompt("Add ZIVIS guidance so your AI agent knows to run `zivis test` / `zivis threatmodel` when asked?\n" +
|
|
46
|
+
"(Adds a small managed block — your own content is preserved, remove anytime with `zivis mcp uninstall`.) [Y/n] ");
|
|
47
|
+
if (ans.toLowerCase() === "n" || ans.toLowerCase() === "no") {
|
|
48
|
+
console.log(" Skipped. Run 'zivis mcp install --client <ide> --with-guidance' anytime to add later.");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const written = [];
|
|
52
|
+
for (const ide of targets) {
|
|
53
|
+
try {
|
|
54
|
+
const files = writeGuidance({ cwd, client: ide });
|
|
55
|
+
written.push(...files);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.warn(` Warning: Could not write guidance for ${ide}: ${err instanceof Error ? err.message : err}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (written.length > 0) {
|
|
62
|
+
console.log(`✓ Wrote guidance files:`);
|
|
63
|
+
for (const f of written)
|
|
64
|
+
console.log(` ${f}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
20
67
|
export async function initCommand(opts) {
|
|
21
|
-
const config =
|
|
68
|
+
const config = {
|
|
69
|
+
...DEFAULT_CONFIG,
|
|
70
|
+
...resolveConfigFromBinding(process.cwd()),
|
|
71
|
+
};
|
|
22
72
|
const session = opts.session || "default";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
73
|
+
const envLabel = config.apiBaseUrl.includes("staging") ? "staging" : "production";
|
|
74
|
+
console.log(`Environment: ${envLabel} (${config.apiBaseUrl})`);
|
|
75
|
+
console.log("");
|
|
76
|
+
let tokens;
|
|
77
|
+
let existingOrgId;
|
|
78
|
+
let existingEmail;
|
|
79
|
+
const existing = await resolveExistingSessionAuth(config, session, process.cwd());
|
|
80
|
+
if (existing) {
|
|
81
|
+
console.log("Existing session found — reusing stored credentials.");
|
|
82
|
+
console.log("(Run `zivis auth logout` first to switch accounts.)\n");
|
|
83
|
+
tokens = { access_token: existing.accessToken, id_token: existing.idToken };
|
|
84
|
+
existingOrgId = existing.organizationId;
|
|
85
|
+
existingEmail = existing.email;
|
|
31
86
|
}
|
|
32
87
|
else {
|
|
33
|
-
console.log("
|
|
88
|
+
console.log("Opening browser for authentication...");
|
|
89
|
+
console.log("Log into the org you want to bind this project to.\n");
|
|
34
90
|
try {
|
|
35
|
-
|
|
36
|
-
bootstrapToken = tokens.access_token;
|
|
37
|
-
const email = extractEmail(tokens.id_token);
|
|
38
|
-
console.log(`✓ Authenticated as ${email}`);
|
|
91
|
+
tokens = await login(config, session, undefined, { skipConfirm: true });
|
|
39
92
|
}
|
|
40
93
|
catch (err) {
|
|
41
94
|
console.error("Login failed:", err instanceof Error ? err.message : err);
|
|
42
95
|
process.exit(1);
|
|
43
96
|
}
|
|
44
97
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
98
|
+
const email = existingEmail ?? extractEmail(tokens.id_token);
|
|
99
|
+
const claims = decodeJwtPayload(tokens.access_token);
|
|
100
|
+
const jwtOrgId = existingOrgId ?? claims?.org_id;
|
|
101
|
+
if (jwtOrgId) {
|
|
102
|
+
let orgName;
|
|
103
|
+
try {
|
|
104
|
+
const orgs = await fetchUserOrgs(config, tokens.access_token);
|
|
105
|
+
orgName = orgs.find((o) => o.workosOrgId === jwtOrgId)?.name;
|
|
106
|
+
if (!orgName && orgs.length > 0) {
|
|
107
|
+
console.log(`\n ⚠ WorkOS org ${jwtOrgId} is not registered in ZIVIS.`);
|
|
108
|
+
console.log(` Your ZIVIS orgs: ${orgs.map((o) => `${o.name} (${o.workosOrgId})`).join(", ")}`);
|
|
109
|
+
console.log(` Try logging into ${config.apiBaseUrl} in your browser first, then re-run init.\n`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
console.error(` (note: org name lookup failed — ${e instanceof Error ? e.message : e})`);
|
|
114
|
+
}
|
|
115
|
+
const orgLabel = orgName ?? `unknown org (${jwtOrgId})`;
|
|
116
|
+
console.log(`\nAuthenticated as: ${email}`);
|
|
117
|
+
console.log(`Org: ${orgLabel}`);
|
|
118
|
+
console.log(`Environment: ${envLabel} (${config.apiBaseUrl})\n`);
|
|
119
|
+
const confirm = await prompt(`Bind this project to "${orgLabel}"? [Y/n] `);
|
|
120
|
+
if (confirm.toLowerCase() === "n" || confirm.toLowerCase() === "no") {
|
|
121
|
+
console.log("");
|
|
122
|
+
const retry = await prompt("Retry login in a private/incognito window? [Y/n] ");
|
|
123
|
+
if (retry.toLowerCase() !== "n" && retry.toLowerCase() !== "no") {
|
|
124
|
+
console.log("\nOpening a private/incognito window — log into the correct org...\n");
|
|
125
|
+
let retryTokens;
|
|
126
|
+
try {
|
|
127
|
+
retryTokens = await login(config, session, undefined, { skipConfirm: true, incognito: true });
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
console.error("Login failed:", err instanceof Error ? err.message : err);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
tokens = retryTokens;
|
|
134
|
+
const retryClaims = decodeJwtPayload(retryTokens.access_token);
|
|
135
|
+
const retryOrgId = retryClaims?.org_id;
|
|
136
|
+
if (!retryOrgId) {
|
|
137
|
+
console.error("JWT returned no org scope. Try `zivis auth logout` then `zivis auth init` again.");
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
let retryOrgName;
|
|
141
|
+
try {
|
|
142
|
+
const retryOrgs = await fetchUserOrgs(config, retryTokens.access_token);
|
|
143
|
+
retryOrgName = retryOrgs.find((o) => o.workosOrgId === retryOrgId)?.name;
|
|
144
|
+
}
|
|
145
|
+
catch (e) {
|
|
146
|
+
console.error(` (note: org name lookup failed — ${e instanceof Error ? e.message : e})`);
|
|
147
|
+
}
|
|
148
|
+
const retryLabel = retryOrgName ?? retryOrgId;
|
|
149
|
+
const retryEmail = extractEmail(retryTokens.id_token);
|
|
150
|
+
console.log(`\nAuthenticated as: ${retryEmail}`);
|
|
151
|
+
console.log(`Org: ${retryLabel}\n`);
|
|
152
|
+
const retryConfirm = await prompt(`Bind this project to "${retryLabel}"? [Y/n] `);
|
|
153
|
+
if (retryConfirm.toLowerCase() === "n" || retryConfirm.toLowerCase() === "no") {
|
|
154
|
+
console.log("Aborted.");
|
|
155
|
+
process.exit(0);
|
|
156
|
+
}
|
|
157
|
+
const storageName2 = getStorageName();
|
|
158
|
+
await saveSessionEntry(session, retryEmail, credentialStorageFromConfig(config));
|
|
159
|
+
console.log(`\n✓ Logged in as ${retryEmail} → ${retryLabel}`);
|
|
160
|
+
console.log(`✓ Credentials stored in ${storageName2}`);
|
|
161
|
+
await ensureProjectBinding({
|
|
162
|
+
config, session, accessToken: retryTokens.access_token,
|
|
163
|
+
organizationId: retryOrgId, cwd: process.cwd(), autoBind: true, skipBind: false, force: true,
|
|
164
|
+
});
|
|
165
|
+
await ensureApplicationBinding({ config, accessToken: retryTokens.access_token, cwd: process.cwd(), explicitApplication: opts.application });
|
|
166
|
+
await tryAutoMintBindingTokenAfterLogin({
|
|
167
|
+
cwd: process.cwd(),
|
|
168
|
+
sessionName: session,
|
|
169
|
+
accessToken: retryTokens.access_token,
|
|
170
|
+
skip: opts.skipMintKey === true,
|
|
171
|
+
warnOnFailure: true,
|
|
172
|
+
});
|
|
173
|
+
await discardOauthAfterLogin({ session, config });
|
|
174
|
+
await offerGuidanceInstall(process.cwd());
|
|
175
|
+
await maybePromptGitHubLinkage(config);
|
|
176
|
+
process.exit(0);
|
|
177
|
+
}
|
|
178
|
+
console.log("\nAborted. Switch orgs in your browser then run `zivis auth logout && zivis auth init`.");
|
|
179
|
+
process.exit(0);
|
|
67
180
|
}
|
|
68
|
-
|
|
181
|
+
const storageName = getStorageName();
|
|
182
|
+
await saveSessionEntry(session, email, credentialStorageFromConfig(config));
|
|
183
|
+
console.log(`\n✓ Logged in as ${email} → ${orgLabel}`);
|
|
184
|
+
console.log(`✓ Credentials stored in ${storageName}`);
|
|
185
|
+
await ensureProjectBinding({
|
|
186
|
+
config,
|
|
187
|
+
session,
|
|
188
|
+
accessToken: tokens.access_token,
|
|
189
|
+
organizationId: jwtOrgId,
|
|
190
|
+
cwd: process.cwd(),
|
|
191
|
+
autoBind: true,
|
|
192
|
+
skipBind: false,
|
|
193
|
+
force: true,
|
|
194
|
+
});
|
|
195
|
+
await ensureApplicationBinding({ config, accessToken: tokens.access_token, cwd: process.cwd(), explicitApplication: opts.application });
|
|
196
|
+
await tryAutoMintBindingTokenAfterLogin({
|
|
197
|
+
cwd: process.cwd(),
|
|
198
|
+
sessionName: session,
|
|
199
|
+
accessToken: tokens.access_token,
|
|
200
|
+
skip: opts.skipMintKey === true,
|
|
201
|
+
warnOnFailure: true,
|
|
202
|
+
});
|
|
203
|
+
await discardOauthAfterLogin({ session, config });
|
|
204
|
+
await offerGuidanceInstall(process.cwd());
|
|
205
|
+
await maybePromptGitHubLinkage(config);
|
|
69
206
|
}
|
|
70
207
|
else {
|
|
71
|
-
console.log(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
console.error(`Org "${selectedOrg.name}" has no WorkOS organization ID — cannot scope login.`);
|
|
75
|
-
process.exit(1);
|
|
76
|
-
}
|
|
77
|
-
// Attempt org-scoped login, with graceful handling for browser-session mismatches
|
|
78
|
-
let scopedTokens;
|
|
79
|
-
let finalOrgId = selectedOrg.workosOrgId;
|
|
80
|
-
let finalOrgName = selectedOrg.name;
|
|
81
|
-
for (let attempt = 0; attempt < 2; attempt++) {
|
|
82
|
-
console.log(`\n${stored ? "Step 1/1" : "Step 2/2"}: Logging in to ${finalOrgName} (browser will open)...`);
|
|
208
|
+
console.log("\nYour account isn't scoped to a specific org yet.");
|
|
209
|
+
console.log("Fetching your organizations...\n");
|
|
210
|
+
let orgs;
|
|
83
211
|
try {
|
|
84
|
-
|
|
85
|
-
orgName: finalOrgName,
|
|
86
|
-
skipConfirm: true,
|
|
87
|
-
});
|
|
88
|
-
break; // success
|
|
212
|
+
orgs = await fetchUserOrgs(config, tokens.access_token);
|
|
89
213
|
}
|
|
90
214
|
catch (err) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
215
|
+
console.error("Failed to fetch organizations:", err instanceof Error ? err.message : err);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
if (orgs.length === 0) {
|
|
219
|
+
console.error("No organizations found. Contact support.");
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
if (orgs.length === 1) {
|
|
223
|
+
console.log(`One org found: ${orgs[0].name}. Re-authenticating scoped to that org...`);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
console.log("Your organizations:");
|
|
227
|
+
orgs.forEach((org, i) => console.log(` ${i + 1}. ${org.name}`));
|
|
228
|
+
const answer = await prompt(`\nSelect org to bind this project to [1-${orgs.length}]: `);
|
|
229
|
+
const idx = parseInt(answer, 10) - 1;
|
|
230
|
+
if (isNaN(idx) || idx < 0 || idx >= orgs.length) {
|
|
231
|
+
console.error("Invalid selection.");
|
|
95
232
|
process.exit(1);
|
|
96
233
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
console.error(`\n⚠ Browser authenticated to "${receivedName}" instead of "${finalOrgName}".`);
|
|
101
|
-
console.error(` This happens when your browser's active session is for a different org.\n`);
|
|
102
|
-
if (attempt >= 1) {
|
|
103
|
-
console.error("Still mismatched after retry. Run `zivis auth init` again after switching orgs in your browser.");
|
|
234
|
+
const selected = orgs[idx];
|
|
235
|
+
if (!selected.workosOrgId) {
|
|
236
|
+
console.error(`Org "${selected.name}" has no WorkOS org ID.`);
|
|
104
237
|
process.exit(1);
|
|
105
238
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
239
|
+
console.log(`\nRe-opening browser scoped to ${selected.name}...`);
|
|
240
|
+
console.log("(Tip: if your browser logs into the wrong org, use option 2 to get a URL for a private/incognito window)\n");
|
|
241
|
+
try {
|
|
242
|
+
const scopedTokens = await login(config, session, selected.workosOrgId, {
|
|
243
|
+
orgName: selected.name,
|
|
244
|
+
skipConfirm: true,
|
|
245
|
+
});
|
|
246
|
+
const storageName2 = getStorageName();
|
|
247
|
+
await saveSessionEntry(session, email, credentialStorageFromConfig(config));
|
|
248
|
+
console.log(`\n✓ Logged in as ${email} → ${selected.name}`);
|
|
249
|
+
console.log(`✓ Credentials stored in ${storageName2}`);
|
|
250
|
+
await ensureProjectBinding({
|
|
251
|
+
config,
|
|
252
|
+
session,
|
|
253
|
+
accessToken: scopedTokens.access_token,
|
|
254
|
+
organizationId: selected.workosOrgId,
|
|
255
|
+
cwd: process.cwd(),
|
|
256
|
+
autoBind: true,
|
|
257
|
+
skipBind: false,
|
|
258
|
+
force: true,
|
|
259
|
+
});
|
|
260
|
+
await ensureApplicationBinding({ config, accessToken: scopedTokens.access_token, cwd: process.cwd(), explicitApplication: opts.application });
|
|
261
|
+
await tryAutoMintBindingTokenAfterLogin({
|
|
262
|
+
cwd: process.cwd(),
|
|
263
|
+
sessionName: session,
|
|
264
|
+
accessToken: scopedTokens.access_token,
|
|
265
|
+
skip: opts.skipMintKey === true,
|
|
266
|
+
warnOnFailure: true,
|
|
267
|
+
});
|
|
268
|
+
await discardOauthAfterLogin({ session, config });
|
|
269
|
+
await offerGuidanceInstall(process.cwd());
|
|
270
|
+
}
|
|
271
|
+
catch (err) {
|
|
272
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
273
|
+
const m = msg.match(/received (org_\w+)/);
|
|
274
|
+
if (m) {
|
|
275
|
+
console.error(`\n⚠ Browser authenticated to a different org than selected.`);
|
|
276
|
+
console.error(` Your browser has an active session for a different org.\n`);
|
|
277
|
+
console.error(` To fix: run \`zivis auth init\` again and paste the URL into a private/incognito window.`);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
console.error("Login failed:", msg);
|
|
281
|
+
}
|
|
282
|
+
process.exit(1);
|
|
110
283
|
}
|
|
111
|
-
// Retry scoped to what the browser actually has
|
|
112
|
-
finalOrgId = receivedOrgId;
|
|
113
|
-
finalOrgName = receivedName;
|
|
114
284
|
}
|
|
115
285
|
}
|
|
116
|
-
if (!scopedTokens) {
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
const email = extractEmail(scopedTokens.id_token);
|
|
120
|
-
const storageName = getStorageName();
|
|
121
|
-
await saveSessionEntry(session, email);
|
|
122
|
-
console.log(`\n✓ Logged in as ${email} → ${finalOrgName}`);
|
|
123
|
-
console.log(`✓ Credentials stored in ${storageName}`);
|
|
124
|
-
await ensureProjectBinding({
|
|
125
|
-
config,
|
|
126
|
-
session,
|
|
127
|
-
accessToken: scopedTokens.access_token,
|
|
128
|
-
organizationId: finalOrgId,
|
|
129
|
-
cwd: process.cwd(),
|
|
130
|
-
autoBind: true,
|
|
131
|
-
skipBind: false,
|
|
132
|
-
});
|
|
133
286
|
process.exit(0);
|
|
134
287
|
}
|
|
135
|
-
//# sourceMappingURL=init.js.map
|
|
@@ -1,60 +1,161 @@
|
|
|
1
|
+
import * as readline from "node:readline/promises";
|
|
1
2
|
import { login } from "@zivis/mcp/auth";
|
|
2
3
|
import { getStorageName } from "@zivis/mcp/auth";
|
|
3
4
|
import { saveSessionEntry } from "@zivis/mcp/auth";
|
|
4
|
-
import { detectProjectBinding } from "@zivis/mcp/project-binding";
|
|
5
|
-
import { DEFAULT_CONFIG } from "@zivis/mcp/types";
|
|
5
|
+
import { detectProjectBinding, resolveConfigFromBinding } from "@zivis/mcp/project-binding";
|
|
6
|
+
import { credentialStorageFromConfig, DEFAULT_CONFIG } from "@zivis/mcp/types";
|
|
6
7
|
import { extractEmail } from "../../internal/orgs.js";
|
|
8
|
+
import { pickOrg } from "../../internal/org-picker.js";
|
|
7
9
|
import { ensureProjectBinding } from "../../internal/project-binding.js";
|
|
8
|
-
import {
|
|
10
|
+
import { discardOauthAfterLogin, tryAutoMintBindingTokenAfterLogin, } from "../../internal/binding-token-mint.js";
|
|
11
|
+
import { setupCursorWorkspace, setupVsCodeClaude, setupVsCodeCopilot, setupClaudeCodeCli, } from "../../internal/ide-setup.js";
|
|
12
|
+
import { buildLinkagePrompt } from "../../internal/github-linkage-prompt.js";
|
|
13
|
+
async function confirm(question) {
|
|
14
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
15
|
+
try {
|
|
16
|
+
const answer = (await rl.question(question)).trim().toLowerCase();
|
|
17
|
+
return answer !== "n" && answer !== "no";
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
rl.close();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
9
23
|
export async function loginCommand(opts) {
|
|
10
|
-
const config =
|
|
24
|
+
const config = {
|
|
25
|
+
...DEFAULT_CONFIG,
|
|
26
|
+
...resolveConfigFromBinding(process.cwd()),
|
|
27
|
+
};
|
|
11
28
|
const detected = detectProjectBinding(process.cwd());
|
|
12
29
|
const session = opts.session || detected?.binding.session || config.session;
|
|
13
|
-
|
|
14
|
-
|
|
30
|
+
const sessionName = session || "default";
|
|
31
|
+
let organizationId;
|
|
32
|
+
let orgName;
|
|
33
|
+
let writeMode = "no-write";
|
|
34
|
+
if (opts.org) {
|
|
35
|
+
organizationId = opts.org;
|
|
36
|
+
orgName = detected?.binding.orgName && detected.binding.workosOrgId === opts.org
|
|
37
|
+
? detected.binding.orgName
|
|
38
|
+
: undefined;
|
|
39
|
+
if (opts.rebind) {
|
|
40
|
+
writeMode = "replace";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else if (opts.rebind) {
|
|
44
|
+
const picked = await runIdentityThenPicker(config, sessionName, {
|
|
45
|
+
currentOrgId: detected?.binding.workosOrgId ?? undefined,
|
|
46
|
+
header: detected?.binding.workosOrgId
|
|
47
|
+
? "Switch this project to which org?"
|
|
48
|
+
: "Your organizations:",
|
|
49
|
+
});
|
|
50
|
+
if (detected?.binding.workosOrgId && detected.binding.workosOrgId === picked.workosOrgId) {
|
|
51
|
+
console.log(`Project is already bound to ${picked.name}. Nothing to change.`);
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
if (detected?.binding.workosOrgId) {
|
|
55
|
+
const fromLabel = detected.binding.orgName
|
|
56
|
+
? `${detected.binding.orgName} (${detected.binding.workosOrgId})`
|
|
57
|
+
: detected.binding.workosOrgId;
|
|
58
|
+
const toLabel = `${picked.name} (${picked.workosOrgId})`;
|
|
59
|
+
if (!opts.yes) {
|
|
60
|
+
const ok = await confirm(`Change project binding from "${fromLabel}" to "${toLabel}"? [Y/n] `);
|
|
61
|
+
if (!ok) {
|
|
62
|
+
console.log("Aborted.");
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
writeMode = "replace";
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
writeMode = "create";
|
|
70
|
+
}
|
|
71
|
+
organizationId = picked.workosOrgId;
|
|
72
|
+
orgName = picked.name;
|
|
73
|
+
}
|
|
74
|
+
else if (detected?.binding.workosOrgId) {
|
|
15
75
|
organizationId = detected.binding.workosOrgId;
|
|
16
|
-
|
|
76
|
+
orgName = detected.binding.orgName;
|
|
77
|
+
console.log(`Using org from project binding: ${organizationId}${orgName ? ` (${orgName})` : ""}`);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const picked = await runIdentityThenPicker(config, sessionName, {
|
|
81
|
+
header: "Your organizations:",
|
|
82
|
+
});
|
|
83
|
+
organizationId = picked.workosOrgId;
|
|
84
|
+
orgName = picked.name;
|
|
85
|
+
writeMode = "create";
|
|
86
|
+
}
|
|
87
|
+
if (!organizationId) {
|
|
88
|
+
console.error("Internal error: no organization resolved for login.");
|
|
89
|
+
process.exit(1);
|
|
17
90
|
}
|
|
18
91
|
if (detected?.binding.session && !opts.session) {
|
|
19
92
|
console.log(`Using session from project binding: ${session}`);
|
|
20
93
|
}
|
|
21
94
|
try {
|
|
22
95
|
const tokens = await login(config, session, organizationId, {
|
|
23
|
-
orgName
|
|
24
|
-
skipConfirm: opts.yes === true,
|
|
96
|
+
orgName,
|
|
97
|
+
skipConfirm: opts.yes === true || writeMode !== "no-write",
|
|
25
98
|
});
|
|
26
99
|
const storageName = getStorageName();
|
|
27
100
|
const email = extractEmail(tokens.id_token);
|
|
28
|
-
|
|
29
|
-
await saveSessionEntry(sessionName, email);
|
|
101
|
+
await saveSessionEntry(sessionName, email, credentialStorageFromConfig(config));
|
|
30
102
|
const sessionLabel = session ? ` (session: ${session})` : "";
|
|
31
103
|
console.log(`✓ Logged in as ${email}${sessionLabel}`);
|
|
32
104
|
console.log(`✓ Credentials stored in ${storageName}`);
|
|
33
|
-
|
|
34
|
-
|
|
105
|
+
console.log(`✓ JWT scoped to organization: ${organizationId}${orgName ? ` (${orgName})` : ""}`);
|
|
106
|
+
try {
|
|
107
|
+
await setupCursorWorkspace();
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
console.log(` WARNING: Failed to update .cursor/mcp.json: ${err instanceof Error ? err.message : err}`);
|
|
35
111
|
}
|
|
36
112
|
try {
|
|
37
|
-
await setupVsCodeClaude(
|
|
38
|
-
await setupVsCodeCopilot(
|
|
113
|
+
await setupVsCodeClaude();
|
|
114
|
+
await setupVsCodeCopilot();
|
|
39
115
|
}
|
|
40
116
|
catch (err) {
|
|
41
117
|
console.log(` WARNING: Failed to update .vscode/mcp.json: ${err instanceof Error ? err.message : err}`);
|
|
42
118
|
}
|
|
43
119
|
try {
|
|
44
|
-
await setupClaudeCodeCli(
|
|
120
|
+
await setupClaudeCodeCli();
|
|
45
121
|
}
|
|
46
122
|
catch (err) {
|
|
47
123
|
console.log(` WARNING: Failed to update Claude Code CLI config: ${err instanceof Error ? err.message : err}`);
|
|
48
124
|
}
|
|
125
|
+
if (writeMode === "create" && !opts.yes && !opts.noBind) {
|
|
126
|
+
const orgLabel = orgName ? `${orgName} (${organizationId})` : organizationId;
|
|
127
|
+
const ok = await confirm(`Bind this project to ${orgLabel}? [Y/n] `);
|
|
128
|
+
if (!ok) {
|
|
129
|
+
console.log("Login succeeded but project was not bound.");
|
|
130
|
+
await discardOauthAfterLogin({ session, config });
|
|
131
|
+
process.exit(0);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
49
134
|
await ensureProjectBinding({
|
|
50
135
|
config,
|
|
51
136
|
session: sessionName,
|
|
52
137
|
accessToken: tokens.access_token,
|
|
53
138
|
organizationId,
|
|
54
139
|
cwd: process.cwd(),
|
|
55
|
-
autoBind: opts.bind === true,
|
|
140
|
+
autoBind: opts.bind === true || writeMode !== "no-write",
|
|
56
141
|
skipBind: opts.noBind === true,
|
|
142
|
+
force: writeMode === "replace",
|
|
57
143
|
});
|
|
144
|
+
await tryAutoMintBindingTokenAfterLogin({
|
|
145
|
+
cwd: process.cwd(),
|
|
146
|
+
sessionName,
|
|
147
|
+
accessToken: tokens.access_token,
|
|
148
|
+
skip: opts.skipMintKey === true,
|
|
149
|
+
warnOnFailure: true,
|
|
150
|
+
});
|
|
151
|
+
await discardOauthAfterLogin({ session, config });
|
|
152
|
+
try {
|
|
153
|
+
const linkagePrompt = await buildLinkagePrompt({ config });
|
|
154
|
+
if (linkagePrompt)
|
|
155
|
+
console.log(linkagePrompt);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
}
|
|
58
159
|
process.exit(0);
|
|
59
160
|
}
|
|
60
161
|
catch (err) {
|
|
@@ -62,4 +163,21 @@ export async function loginCommand(opts) {
|
|
|
62
163
|
process.exit(1);
|
|
63
164
|
}
|
|
64
165
|
}
|
|
65
|
-
|
|
166
|
+
async function runIdentityThenPicker(config, session, pickOpts) {
|
|
167
|
+
console.log("Opening browser to identify your account (no org scope yet)...");
|
|
168
|
+
let identity;
|
|
169
|
+
try {
|
|
170
|
+
identity = await login(config, session, undefined, { skipConfirm: true });
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
console.error("Login failed:", err instanceof Error ? err.message : err);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
return await pickOrg(config, identity.access_token, pickOpts);
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
console.error(err instanceof Error ? err.message : err);
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import { keychainClearAll, keychainClearSession } from "@zivis/mcp/auth";
|
|
1
|
+
import { keychainClearAll, keychainClearSession, keychainDelete, keychainRead } from "@zivis/mcp/auth";
|
|
2
2
|
import { removeSessionEntry } from "@zivis/mcp/auth";
|
|
3
|
+
import { detectProjectBinding, resolveConfigFromBinding } from "@zivis/mcp/project-binding";
|
|
4
|
+
import { credentialStorageFromConfig } from "@zivis/mcp/types";
|
|
3
5
|
export async function logoutCommand(opts) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const config = resolveConfigFromBinding(process.cwd());
|
|
7
|
+
const st = credentialStorageFromConfig(config);
|
|
8
|
+
const sessionName = opts.session ??
|
|
9
|
+
detectProjectBinding(process.cwd())?.binding.session;
|
|
10
|
+
if (sessionName) {
|
|
11
|
+
await keychainClearSession(sessionName, st);
|
|
12
|
+
const apiKeyAccount = `apikey.${sessionName}`;
|
|
13
|
+
const hadApiKey = !!(await keychainRead(apiKeyAccount, st).catch(() => null));
|
|
14
|
+
if (hadApiKey) {
|
|
15
|
+
await keychainDelete(apiKeyAccount, st);
|
|
16
|
+
console.log(`✓ Local Project Binding Token cleared for session "${sessionName}"`);
|
|
17
|
+
console.log(` Note: To revoke the key server-side, visit Settings → API Tokens in the ZIVIS UI.`);
|
|
18
|
+
}
|
|
19
|
+
await removeSessionEntry(sessionName, st);
|
|
20
|
+
console.log(`✓ Session "${sessionName}" credentials cleared`);
|
|
8
21
|
return;
|
|
9
22
|
}
|
|
10
|
-
await keychainClearAll();
|
|
23
|
+
await keychainClearAll(st);
|
|
11
24
|
console.log("✓ Default credentials cleared");
|
|
12
25
|
console.log(" Note: Named sessions are not affected. Use 'zivis auth sessions' to list them.");
|
|
13
26
|
}
|
|
14
|
-
//# sourceMappingURL=logout.js.map
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { listSessions, removeSessionEntry, keychainClearSession } from "@zivis/mcp/auth";
|
|
2
|
+
import { resolveConfigFromBinding } from "@zivis/mcp/project-binding";
|
|
3
|
+
import { credentialStorageFromConfig } from "@zivis/mcp/types";
|
|
2
4
|
export async function sessionsCommand(opts) {
|
|
5
|
+
const config = resolveConfigFromBinding(process.cwd());
|
|
6
|
+
const st = credentialStorageFromConfig(config);
|
|
3
7
|
if (opts.remove) {
|
|
4
|
-
await keychainClearSession(opts.remove);
|
|
5
|
-
await removeSessionEntry(opts.remove);
|
|
8
|
+
await keychainClearSession(opts.remove, st);
|
|
9
|
+
await removeSessionEntry(opts.remove, st);
|
|
6
10
|
console.log(`✓ Session "${opts.remove}" removed`);
|
|
7
11
|
return;
|
|
8
12
|
}
|
|
9
|
-
const sessions = await listSessions();
|
|
13
|
+
const sessions = await listSessions(st);
|
|
10
14
|
const activeSession = process.env.ZIVIS_SESSION;
|
|
11
15
|
if (sessions.length === 0) {
|
|
12
16
|
console.log("No sessions stored.");
|
|
@@ -27,4 +31,3 @@ export async function sessionsCommand(opts) {
|
|
|
27
31
|
console.log("To use a session in a project, add to .mcp.json:");
|
|
28
32
|
console.log(' "env": { "ZIVIS_SESSION": "<session-name>" }');
|
|
29
33
|
}
|
|
30
|
-
//# sourceMappingURL=sessions.js.map
|