@impulselab/directory 2.7.4 → 2.7.5
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 +13 -13
- package/dist/index.js +31 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,16 +38,16 @@ If the remote version changed first, `push` keeps your file and asks you to sync
|
|
|
38
38
|
|
|
39
39
|
| Command | Description |
|
|
40
40
|
| --- | --- |
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
41
|
+
| `npx @impulselab/directory login [--key <key>] [--url <baseUrl>]` | Browser device-flow login; `--key` is the headless/CI fallback |
|
|
42
|
+
| `npx @impulselab/directory logout` | Remove the saved API key |
|
|
43
|
+
| `npx @impulselab/directory whoami` | Show the authenticated user |
|
|
44
|
+
| `npx @impulselab/directory sync [--project] [--prune] [--force] [--dry-run] [--json]` | Install or update synced artifacts |
|
|
45
|
+
| `npx @impulselab/directory status [--project] [--json]` | Show synced, modified, outdated and missing files |
|
|
46
|
+
| `npx @impulselab/directory push <path> [-m <changelog>]` | Publish a local edit as a new artifact version |
|
|
47
|
+
| `npx @impulselab/directory add <owner/slug> [--target <target>]` | Public install without lock tracking; interactive picker in a TTY |
|
|
48
|
+
| `npx @impulselab/directory add stack <id> [--target <target>]` | One-shot public stack install |
|
|
49
|
+
| `npx @impulselab/directory agents` | List enabled agents |
|
|
50
|
+
| `npx @impulselab/directory agents enable\|disable <claude\|codex\|cursor>` | Update agent targets |
|
|
51
51
|
|
|
52
52
|
## Installing an artifact
|
|
53
53
|
|
|
@@ -71,9 +71,9 @@ npx @impulselab/directory <owner>/<slug> --target claude-slash
|
|
|
71
71
|
The picker is skipped automatically when stdin/stdout is not a TTY, when `--target`
|
|
72
72
|
is set, or when `CI` is set. Legacy
|
|
73
73
|
`npx @impulselab/directory user/slug --target claude-slash` still works and is
|
|
74
|
-
treated as `
|
|
74
|
+
treated as `npx @impulselab/directory add user/slug`.
|
|
75
75
|
|
|
76
|
-
> Note: `
|
|
76
|
+
> Note: `npx @impulselab/directory add stack <id>` installs are non-interactive and use each
|
|
77
77
|
> artifact's per-target default for now.
|
|
78
78
|
|
|
79
79
|
## Target Mapping
|
|
@@ -85,4 +85,4 @@ treated as `impulse add user/slug`.
|
|
|
85
85
|
| `agent` | `~/.claude/agents/<slug>.md` | `.claude/agents/<slug>.md` | - | - |
|
|
86
86
|
| `rule` | - | - | - | `.cursor/rules/<slug>.mdc` |
|
|
87
87
|
|
|
88
|
-
Global sync covers Claude Code and Claude Cowork because both read `~/.claude`. Codex slash commands sync to `~/.codex/prompts`. Cursor artifacts are project-scoped, so run `
|
|
88
|
+
Global sync covers Claude Code and Claude Cowork because both read `~/.claude`. Codex slash commands sync to `~/.codex/prompts`. Cursor artifacts are project-scoped, so run `npx @impulselab/directory sync --project` from inside the project.
|
package/dist/index.js
CHANGED
|
@@ -151,6 +151,12 @@ function resolveInstallPaths(kind, slug, agents2, scope) {
|
|
|
151
151
|
// src/commands/add.ts
|
|
152
152
|
import pc from "picocolors";
|
|
153
153
|
|
|
154
|
+
// src/lib/cli-invocation.ts
|
|
155
|
+
var cliInvocation = "npx @impulselab/directory";
|
|
156
|
+
function cliCommand(args) {
|
|
157
|
+
return `${cliInvocation} ${args}`;
|
|
158
|
+
}
|
|
159
|
+
|
|
154
160
|
// src/lib/config.ts
|
|
155
161
|
import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
156
162
|
import { homedir } from "os";
|
|
@@ -326,13 +332,13 @@ async function readPayload(response) {
|
|
|
326
332
|
}
|
|
327
333
|
function errorMessage(status, payload) {
|
|
328
334
|
if (status === 401) {
|
|
329
|
-
return
|
|
335
|
+
return `Invalid or missing API key - run \`${cliCommand("login")}\``;
|
|
330
336
|
}
|
|
331
337
|
if (status === 403) {
|
|
332
338
|
return "You do not have permission to perform this action";
|
|
333
339
|
}
|
|
334
340
|
if (status === 409 && isObject(payload) && payload.error === "version_conflict") {
|
|
335
|
-
return `Remote is at v${payload.currentVersion}, run
|
|
341
|
+
return `Remote is at v${payload.currentVersion}, run \`${cliCommand("sync")}\` first (your file is kept)`;
|
|
336
342
|
}
|
|
337
343
|
if (status === 422) {
|
|
338
344
|
return "The server rejected the request as invalid";
|
|
@@ -431,7 +437,11 @@ async function addCommand(identifier, options) {
|
|
|
431
437
|
}
|
|
432
438
|
return;
|
|
433
439
|
}
|
|
434
|
-
throw new Error(
|
|
440
|
+
throw new Error(
|
|
441
|
+
`Use \`${cliCommand("add <owner/slug>")}\` or \`${cliCommand(
|
|
442
|
+
"add stack <id>"
|
|
443
|
+
)}\``
|
|
444
|
+
);
|
|
435
445
|
}
|
|
436
446
|
function shouldRunInteractive(options) {
|
|
437
447
|
return Boolean(
|
|
@@ -755,19 +765,21 @@ async function pollForToken(baseUrl, device) {
|
|
|
755
765
|
}
|
|
756
766
|
if (errorCode === "access_denied") {
|
|
757
767
|
throw new Error(
|
|
758
|
-
|
|
768
|
+
`Authorization was denied. Run \`${cliCommand("login")}\` to retry.`
|
|
759
769
|
);
|
|
760
770
|
}
|
|
761
771
|
if (errorCode === "expired_token") {
|
|
762
772
|
throw new Error(
|
|
763
|
-
|
|
773
|
+
`The code expired. Run \`${cliCommand("login")}\` to get a new one.`
|
|
764
774
|
);
|
|
765
775
|
}
|
|
766
776
|
throw new Error(
|
|
767
777
|
errorDescription(payload) ?? `Device login failed (${errorCode})`
|
|
768
778
|
);
|
|
769
779
|
}
|
|
770
|
-
throw new Error(
|
|
780
|
+
throw new Error(
|
|
781
|
+
`The code expired. Run \`${cliCommand("login")}\` to get a new one.`
|
|
782
|
+
);
|
|
771
783
|
}
|
|
772
784
|
async function createApiKey(baseUrl, accessToken) {
|
|
773
785
|
const { status, payload } = await authRequest(baseUrl, "/api-key/create", {
|
|
@@ -926,7 +938,9 @@ function isNotFound2(error) {
|
|
|
926
938
|
async function pushCommand(filePath, options) {
|
|
927
939
|
const config = await loadConfig();
|
|
928
940
|
if (!config.apiKey) {
|
|
929
|
-
throw new Error(
|
|
941
|
+
throw new Error(
|
|
942
|
+
`Invalid or missing API key - run \`${cliCommand("login")}\``
|
|
943
|
+
);
|
|
930
944
|
}
|
|
931
945
|
const absPath = path5.resolve(filePath);
|
|
932
946
|
const match = await findLockedFile(absPath);
|
|
@@ -1329,7 +1343,9 @@ function prefixForAction(type) {
|
|
|
1329
1343
|
async function statusCommand(options) {
|
|
1330
1344
|
const config = await loadConfig();
|
|
1331
1345
|
if (!config.apiKey) {
|
|
1332
|
-
throw new Error(
|
|
1346
|
+
throw new Error(
|
|
1347
|
+
`Invalid or missing API key - run \`${cliCommand("login")}\``
|
|
1348
|
+
);
|
|
1333
1349
|
}
|
|
1334
1350
|
const scope = options.project ? "project" : "global";
|
|
1335
1351
|
const scopeRoot = options.project ? await resolveProjectRoot() : homedir6();
|
|
@@ -1396,7 +1412,9 @@ import pc7 from "picocolors";
|
|
|
1396
1412
|
async function syncCommand(options) {
|
|
1397
1413
|
const config = await loadConfig();
|
|
1398
1414
|
if (!config.apiKey) {
|
|
1399
|
-
throw new Error(
|
|
1415
|
+
throw new Error(
|
|
1416
|
+
`Invalid or missing API key - run \`${cliCommand("login")}\``
|
|
1417
|
+
);
|
|
1400
1418
|
}
|
|
1401
1419
|
const scope = options.project ? "project" : "global";
|
|
1402
1420
|
const scopeRoot = options.project ? await resolveProjectRoot() : homedir7();
|
|
@@ -1450,7 +1468,9 @@ async function syncCommand(options) {
|
|
|
1450
1468
|
}
|
|
1451
1469
|
if (skipped.length > 0) {
|
|
1452
1470
|
console.info(
|
|
1453
|
-
|
|
1471
|
+
`Run \`${cliCommand("push <path>")}\` to publish, or \`${cliCommand(
|
|
1472
|
+
"sync --force"
|
|
1473
|
+
)}\`.`
|
|
1454
1474
|
);
|
|
1455
1475
|
}
|
|
1456
1476
|
const conflicts = actions.filter((action) => action.type === "skip-conflict");
|
|
@@ -1513,7 +1533,7 @@ import pc8 from "picocolors";
|
|
|
1513
1533
|
async function whoamiCommand() {
|
|
1514
1534
|
const config = await loadConfig();
|
|
1515
1535
|
if (!config.apiKey) {
|
|
1516
|
-
throw new Error(
|
|
1536
|
+
throw new Error(`Not logged in - run \`${cliCommand("login")}\``);
|
|
1517
1537
|
}
|
|
1518
1538
|
const me = await createApiClient(config.baseUrl, config.apiKey).me();
|
|
1519
1539
|
console.info(`${pc8.green("\u2713")} ${me.user.slug} <${me.user.email}>`);
|