@sellable/install 0.1.216 → 0.1.217
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/bin/sellable-install.mjs +96 -21
- package/package.json +1 -1
- package/skill-templates/create-campaign.md +5 -1
package/README.md
CHANGED
|
@@ -35,8 +35,9 @@ Campaign creation, foundation memory, content capture/ideation, and post
|
|
|
35
35
|
drafting run inside Claude Code or Codex, where the Sellable MCP tools and
|
|
36
36
|
approval flows are available.
|
|
37
37
|
|
|
38
|
-
Install is auth-free by default.
|
|
39
|
-
Sellable
|
|
38
|
+
Install is auth-free by default. The normal path is first-run login: launch a
|
|
39
|
+
Sellable workflow in Claude Code or Codex and the agent handles Sellable
|
|
40
|
+
sign-in with a browser magic-link handoff.
|
|
40
41
|
|
|
41
42
|
The installer uses package stdio MCP by default:
|
|
42
43
|
|
|
@@ -64,14 +65,15 @@ verification in one path:
|
|
|
64
65
|
curl -fsSL "https://app.sellable.dev/api/v2/cli/install" | sh
|
|
65
66
|
```
|
|
66
67
|
|
|
67
|
-
For
|
|
68
|
+
For scripted fallback after browser login, paste the command shown by Sellable:
|
|
68
69
|
|
|
69
|
-
```
|
|
70
|
-
|
|
70
|
+
```bash
|
|
71
|
+
sellable auth set <token> --workspace-id <workspace_id>
|
|
71
72
|
```
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
`SELLABLE_WORKSPACE_ID`.
|
|
74
|
+
For CI/env-only installs, operators can still pass `--token` / `SELLABLE_TOKEN`
|
|
75
|
+
plus `--workspace-id` / `SELLABLE_WORKSPACE_ID`. Do not use env vars as the
|
|
76
|
+
primary human setup path.
|
|
75
77
|
|
|
76
78
|
Auth is stored once at:
|
|
77
79
|
|
package/bin/sellable-install.mjs
CHANGED
|
@@ -419,13 +419,26 @@ async function loadAuthIfPresent(opts) {
|
|
|
419
419
|
return opts;
|
|
420
420
|
}
|
|
421
421
|
|
|
422
|
+
function redactTokensForLog(value) {
|
|
423
|
+
if (Array.isArray(value)) {
|
|
424
|
+
return value.map((item) => redactTokensForLog(item));
|
|
425
|
+
}
|
|
426
|
+
if (value && typeof value === "object") {
|
|
427
|
+
return Object.fromEntries(
|
|
428
|
+
Object.entries(value).map(([key, item]) => [
|
|
429
|
+
key,
|
|
430
|
+
key.toLowerCase().includes("token") && typeof item === "string"
|
|
431
|
+
? redact(item)
|
|
432
|
+
: redactTokensForLog(item),
|
|
433
|
+
])
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
return value;
|
|
437
|
+
}
|
|
438
|
+
|
|
422
439
|
function writeJson(path, data, opts) {
|
|
423
440
|
if (VERBOSE) {
|
|
424
|
-
const redacted = JSON.stringify(
|
|
425
|
-
{ ...data, token: redact(data.token) },
|
|
426
|
-
null,
|
|
427
|
-
2
|
|
428
|
-
);
|
|
441
|
+
const redacted = JSON.stringify(redactTokensForLog(data), null, 2);
|
|
429
442
|
logVerbose(`${C.grey}Writing ${path}: ${redacted}${C.reset}`);
|
|
430
443
|
}
|
|
431
444
|
if (opts.dryRun) return;
|
|
@@ -442,6 +455,56 @@ function readExisting(path) {
|
|
|
442
455
|
}
|
|
443
456
|
}
|
|
444
457
|
|
|
458
|
+
function mergeAuthConfig(raw, auth) {
|
|
459
|
+
const existing =
|
|
460
|
+
raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
461
|
+
const authFields = {
|
|
462
|
+
token: auth.token,
|
|
463
|
+
activeWorkspaceId: auth.activeWorkspaceId,
|
|
464
|
+
apiUrl: auth.apiUrl,
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
if (existing.activeEnv && existing.environments) {
|
|
468
|
+
const activeEnv = existing.activeEnv;
|
|
469
|
+
const envConfig = existing.environments[activeEnv];
|
|
470
|
+
if (
|
|
471
|
+
!envConfig ||
|
|
472
|
+
typeof envConfig !== "object" ||
|
|
473
|
+
Array.isArray(envConfig)
|
|
474
|
+
) {
|
|
475
|
+
throw new Error(
|
|
476
|
+
`Unknown active environment '${activeEnv}' in ${authPath()}`
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
return {
|
|
480
|
+
...existing,
|
|
481
|
+
environments: {
|
|
482
|
+
...existing.environments,
|
|
483
|
+
[activeEnv]: {
|
|
484
|
+
...envConfig,
|
|
485
|
+
...authFields,
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return {
|
|
492
|
+
...existing,
|
|
493
|
+
...authFields,
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function writeAuthSetConfig({ token, workspaceId, apiUrl, dryRun }) {
|
|
498
|
+
const configPath = authPath();
|
|
499
|
+
const raw = readExisting(configPath) || {};
|
|
500
|
+
const config = mergeAuthConfig(raw, {
|
|
501
|
+
token,
|
|
502
|
+
activeWorkspaceId: workspaceId || null,
|
|
503
|
+
apiUrl,
|
|
504
|
+
});
|
|
505
|
+
writeJson(configPath, config, { dryRun });
|
|
506
|
+
}
|
|
507
|
+
|
|
445
508
|
function sellableHostEnvPath() {
|
|
446
509
|
return join(homedir(), ".local", "sellable", "app-sellable-dev", ".env");
|
|
447
510
|
}
|
|
@@ -3665,18 +3728,31 @@ async function main() {
|
|
|
3665
3728
|
}
|
|
3666
3729
|
const token = rawArgs[2];
|
|
3667
3730
|
const authSetFlags = rawArgs.slice(3);
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3731
|
+
let dryRun = false;
|
|
3732
|
+
let workspaceId = "";
|
|
3733
|
+
for (let i = 0; i < authSetFlags.length; i += 1) {
|
|
3734
|
+
const flag = authSetFlags[i];
|
|
3735
|
+
if (flag === "--dry-run") {
|
|
3736
|
+
dryRun = true;
|
|
3737
|
+
continue;
|
|
3738
|
+
}
|
|
3739
|
+
if (flag === "--workspace-id") {
|
|
3740
|
+
const value = authSetFlags[i + 1];
|
|
3741
|
+
if (!value || value.startsWith("--")) {
|
|
3742
|
+
console.error("Missing value for --workspace-id");
|
|
3743
|
+
process.exit(2);
|
|
3744
|
+
}
|
|
3745
|
+
workspaceId = value;
|
|
3746
|
+
i += 1;
|
|
3747
|
+
continue;
|
|
3748
|
+
}
|
|
3749
|
+
console.error(`Unknown auth set option: ${flag}`);
|
|
3674
3750
|
process.exit(2);
|
|
3675
3751
|
}
|
|
3676
3752
|
if (!token) {
|
|
3677
3753
|
console.error(
|
|
3678
|
-
"Usage: sellable auth set <token
|
|
3679
|
-
"
|
|
3754
|
+
"Usage: sellable auth set <token> [--workspace-id <id>]\n" +
|
|
3755
|
+
"Use this only when the Sellable browser login page shows a manual fallback command."
|
|
3680
3756
|
);
|
|
3681
3757
|
process.exit(2);
|
|
3682
3758
|
}
|
|
@@ -3688,23 +3764,22 @@ async function main() {
|
|
|
3688
3764
|
);
|
|
3689
3765
|
process.exit(2);
|
|
3690
3766
|
}
|
|
3691
|
-
// Bypass writeAuth()
|
|
3692
|
-
//
|
|
3693
|
-
//
|
|
3767
|
+
// Bypass writeAuth() because auth-set is a first-run browser fallback:
|
|
3768
|
+
// the workspace id is optional for legacy fallback pages, and existing
|
|
3769
|
+
// config metadata must be preserved.
|
|
3694
3770
|
// Skip installSelfShim() — by definition the user has the shim already
|
|
3695
3771
|
// (they invoked `sellable auth set` from it).
|
|
3696
3772
|
const apiUrl = process.env.SELLABLE_API_URL || DEFAULT_API_URL;
|
|
3697
|
-
|
|
3698
|
-
authPath(),
|
|
3699
|
-
{ token, activeWorkspaceId: null, apiUrl },
|
|
3700
|
-
{ dryRun }
|
|
3701
|
-
);
|
|
3773
|
+
writeAuthSetConfig({ token, workspaceId, apiUrl, dryRun });
|
|
3702
3774
|
if (dryRun) {
|
|
3703
3775
|
console.log(`Dry run: token would be saved to ${authPath()}`);
|
|
3704
3776
|
} else {
|
|
3705
3777
|
console.log(`✓ Token saved to ${authPath()}`);
|
|
3706
3778
|
}
|
|
3707
3779
|
console.log(` apiUrl: ${apiUrl}`);
|
|
3780
|
+
if (workspaceId) {
|
|
3781
|
+
console.log(` activeWorkspaceId: ${workspaceId}`);
|
|
3782
|
+
}
|
|
3708
3783
|
console.log(` Continue in your agent:`);
|
|
3709
3784
|
console.log(` Claude Code: /sellable:create-campaign`);
|
|
3710
3785
|
console.log(` Claude Code: /sellable:foundation`);
|
package/package.json
CHANGED
|
@@ -893,7 +893,11 @@ updates.
|
|
|
893
893
|
|
|
894
894
|
1. Call `mcp__sellable__get_auth_status({})`.
|
|
895
895
|
2. If auth is not OK with `error.type === "config"` or `error.type === "auth"`,
|
|
896
|
-
the user has not signed in yet. Run the FTUX
|
|
896
|
+
the user has not signed in yet. Run first-run login through the FTUX
|
|
897
|
+
magic-link handoff. If a browser page or tool guidance gives the user a
|
|
898
|
+
manual fallback, it must be
|
|
899
|
+
`sellable auth set <token> --workspace-id <workspace_id>`. Do not instruct
|
|
900
|
+
the user to hand-edit JSON auth config.
|
|
897
901
|
|
|
898
902
|
a. Say to the user verbatim:
|
|
899
903
|
|