@shipd-ai/cli 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/commands/auth.d.ts +5 -4
- package/dist/commands/auth.js +29 -11
- package/dist/quests.d.ts +3 -1
- package/dist/quests.js +15 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,15 +16,16 @@ Admin docs, the supported checks, and a copy-paste setup prompt for coding agent
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
npm install -g @shipd-ai/cli
|
|
19
|
-
shipd login # opens
|
|
19
|
+
shipd login # opens https://shipd.ai/cli-auth (one token for every quest); or: shipd login --token <jwt>
|
|
20
20
|
shipd whoami
|
|
21
21
|
shipd quests # which quests this CLI can talk to
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
`login` opens the token page in your browser; paste the token back into the
|
|
25
|
-
terminal.
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
terminal. `--no-browser` prints the page URL instead of opening it. The token is
|
|
26
|
+
stored at `~/.shipd/credentials.json` (mode 0600). It is personal: never commit
|
|
27
|
+
or share it. Typing `--token` by hand leaves it in your shell history, so prefer
|
|
28
|
+
the prompt there. `shipd logout` deletes it.
|
|
28
29
|
|
|
29
30
|
## Three input modes
|
|
30
31
|
|
|
@@ -110,6 +111,7 @@ check with `status`, `verdict`, `output`, `error`, `durationMs`, and `steps`
|
|
|
110
111
|
|
|
111
112
|
| Variable | Effect |
|
|
112
113
|
| --- | --- |
|
|
114
|
+
| `SHIPD_AUTH_URL` | Override the platform login page `shipd login` opens (default `https://shipd.ai/cli-auth`). |
|
|
113
115
|
| `SHIPD_<QUEST>_URL` | Override the quest's base URL (for example `SHIPD_OLYMPUS_URL`). |
|
|
114
116
|
| `SHIPD_<QUEST>_CONVEX_URL` | Skip `/api/cli/config` and talk to this Convex deployment. |
|
|
115
117
|
| `SHIPD_HOME` | Credentials and caches directory (default `~/.shipd`). |
|
package/dist/commands/auth.d.ts
CHANGED
|
@@ -3,14 +3,15 @@ export declare const login: import("citty").CommandDef<{
|
|
|
3
3
|
readonly type: "string";
|
|
4
4
|
readonly description: "Paste the token directly instead of prompting";
|
|
5
5
|
};
|
|
6
|
-
readonly
|
|
6
|
+
readonly browser: {
|
|
7
7
|
readonly type: "boolean";
|
|
8
|
-
readonly
|
|
8
|
+
readonly default: true;
|
|
9
|
+
readonly description: "Open the login page in a browser";
|
|
10
|
+
readonly negativeDescription: "Print the login URL instead of opening a browser";
|
|
9
11
|
};
|
|
10
12
|
readonly quest: {
|
|
11
13
|
readonly type: "string";
|
|
12
|
-
readonly description: "
|
|
13
|
-
readonly default: "olympus";
|
|
14
|
+
readonly description: "Open this quest's own login page instead of the platform page (the token works for every quest either way)";
|
|
14
15
|
};
|
|
15
16
|
}>;
|
|
16
17
|
export declare const logout: import("citty").CommandDef<import("citty").ArgsDef>;
|
package/dist/commands/auth.js
CHANGED
|
@@ -4,7 +4,7 @@ import { defineCommand } from "citty";
|
|
|
4
4
|
import { clearCredentials, loadCredentials, saveCredentials } from "../auth.js";
|
|
5
5
|
import { UsageError } from "../errors.js";
|
|
6
6
|
import { printJson } from "../format.js";
|
|
7
|
-
import {
|
|
7
|
+
import { platformAuthUrl, questAuthUrl } from "../quests.js";
|
|
8
8
|
function openBrowser(url) {
|
|
9
9
|
if (process.platform === "win32") {
|
|
10
10
|
// `start` is a cmd.exe built-in, not a standalone executable.
|
|
@@ -18,7 +18,18 @@ function openBrowser(url) {
|
|
|
18
18
|
function prompt(question) {
|
|
19
19
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
20
20
|
return new Promise((resolve) => {
|
|
21
|
+
let answered = false;
|
|
22
|
+
// stdin can end before an answer (a non-interactive shell with nothing
|
|
23
|
+
// piped in). Resolve empty so login fails with a usage error; otherwise
|
|
24
|
+
// the process drains and exits 0 with nothing saved.
|
|
25
|
+
rl.on("close", () => {
|
|
26
|
+
if (answered)
|
|
27
|
+
return;
|
|
28
|
+
process.stdout.write("\n");
|
|
29
|
+
resolve("");
|
|
30
|
+
});
|
|
21
31
|
rl.question(question, (answer) => {
|
|
32
|
+
answered = true;
|
|
22
33
|
rl.close();
|
|
23
34
|
resolve(answer.trim());
|
|
24
35
|
});
|
|
@@ -27,8 +38,7 @@ function prompt(question) {
|
|
|
27
38
|
const questArg = {
|
|
28
39
|
quest: {
|
|
29
40
|
type: "string",
|
|
30
|
-
description:
|
|
31
|
-
default: DEFAULT_QUEST,
|
|
41
|
+
description: "Open this quest's own login page instead of the platform page (the token works for every quest either way)",
|
|
32
42
|
},
|
|
33
43
|
};
|
|
34
44
|
export const login = defineCommand({
|
|
@@ -36,23 +46,31 @@ export const login = defineCommand({
|
|
|
36
46
|
args: {
|
|
37
47
|
...questArg,
|
|
38
48
|
token: { type: "string", description: "Paste the token directly instead of prompting" },
|
|
39
|
-
|
|
49
|
+
// Named `browser` with a true default because citty parses `--no-browser`
|
|
50
|
+
// as browser=false; an arg literally named "no-browser" is never set.
|
|
51
|
+
browser: {
|
|
52
|
+
type: "boolean",
|
|
53
|
+
default: true,
|
|
54
|
+
description: "Open the login page in a browser",
|
|
55
|
+
negativeDescription: "Print the login URL instead of opening a browser",
|
|
56
|
+
},
|
|
40
57
|
},
|
|
41
58
|
run: async ({ args }) => {
|
|
42
|
-
const authUrl = questAuthUrl(args.quest);
|
|
59
|
+
const authUrl = args.quest ? questAuthUrl(args.quest) : platformAuthUrl();
|
|
43
60
|
let token = args.token?.trim();
|
|
44
61
|
if (!token) {
|
|
45
|
-
if (args
|
|
46
|
-
console.log(`\n Open this page and copy the token:\n ${authUrl}\n`);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
62
|
+
if (args.browser) {
|
|
49
63
|
console.log(`\n Opening browser...\n ${authUrl}\n`);
|
|
50
64
|
openBrowser(authUrl);
|
|
51
65
|
}
|
|
66
|
+
else {
|
|
67
|
+
console.log(`\n Open this page and copy the token:\n ${authUrl}\n`);
|
|
68
|
+
}
|
|
52
69
|
token = await prompt(" Paste your token: ");
|
|
53
70
|
}
|
|
54
|
-
if (!token)
|
|
55
|
-
throw new UsageError("No token provided.");
|
|
71
|
+
if (!token) {
|
|
72
|
+
throw new UsageError("No token provided. Pass it with --token, or paste it at the prompt in an interactive terminal.");
|
|
73
|
+
}
|
|
56
74
|
const identity = saveCredentials(token);
|
|
57
75
|
const expiresAt = new Date(identity.exp * 1000).toLocaleDateString();
|
|
58
76
|
console.log(`\n Logged in as ${identity.name || identity.email || identity.sub}`);
|
package/dist/quests.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ export declare const DEFAULT_QUEST = "olympus";
|
|
|
4
4
|
export declare function knownQuests(): string[];
|
|
5
5
|
/** `SHIPD_<QUEST>_URL` override, or NODE_ENV=development → localhost. */
|
|
6
6
|
export declare function questBaseUrl(quest: string): string;
|
|
7
|
-
/**
|
|
7
|
+
/** `SHIPD_AUTH_URL` override, or NODE_ENV=development → localhost. */
|
|
8
|
+
export declare function platformAuthUrl(): string;
|
|
9
|
+
/** A quest's own copy of the token page (the platform page is the default). */
|
|
8
10
|
export declare function questAuthUrl(quest: string): string;
|
|
9
11
|
export interface QuestConfig {
|
|
10
12
|
convexUrl: string;
|
package/dist/quests.js
CHANGED
|
@@ -32,7 +32,21 @@ export function questBaseUrl(quest) {
|
|
|
32
32
|
}
|
|
33
33
|
return process.env.NODE_ENV === "development" ? entry.dev : entry.prod;
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
// The platform-level token page. The shipd-cli token works for every quest,
|
|
36
|
+
// so the browser login lands here; `questAuthUrl` stays for a quest's own
|
|
37
|
+
// copy of the page (`shipd login --quest <quest>`).
|
|
38
|
+
const PLATFORM_AUTH_URL = {
|
|
39
|
+
prod: "https://shipd.ai/cli-auth",
|
|
40
|
+
dev: "http://localhost:3010/cli-auth",
|
|
41
|
+
};
|
|
42
|
+
/** `SHIPD_AUTH_URL` override, or NODE_ENV=development → localhost. */
|
|
43
|
+
export function platformAuthUrl() {
|
|
44
|
+
const override = process.env.SHIPD_AUTH_URL;
|
|
45
|
+
if (override)
|
|
46
|
+
return override;
|
|
47
|
+
return process.env.NODE_ENV === "development" ? PLATFORM_AUTH_URL.dev : PLATFORM_AUTH_URL.prod;
|
|
48
|
+
}
|
|
49
|
+
/** A quest's own copy of the token page (the platform page is the default). */
|
|
36
50
|
export function questAuthUrl(quest) {
|
|
37
51
|
return `${questBaseUrl(quest)}/cli-auth`;
|
|
38
52
|
}
|