@buildinternet/uploads 0.9.0 → 0.10.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/README.md +23 -7
- package/dist/cli-args.d.ts +2 -0
- package/dist/cli-args.js +5 -0
- package/dist/cli-brand.d.ts +89 -0
- package/dist/cli-brand.js +166 -0
- package/dist/cli-catalog.d.ts +32 -0
- package/dist/cli-catalog.js +187 -0
- package/dist/cli-help.d.ts +26 -0
- package/dist/cli-help.js +176 -0
- package/dist/cli-style.d.ts +42 -0
- package/dist/cli-style.js +108 -0
- package/dist/cli.js +67 -73
- package/dist/client.d.ts +19 -0
- package/dist/client.js +31 -0
- package/dist/commands/admin-enrollment.js +2 -1
- package/dist/commands/completion.d.ts +3 -0
- package/dist/commands/completion.js +284 -0
- package/dist/commands/config.js +9 -7
- package/dist/commands/install.js +2 -1
- package/dist/commands/invite.js +15 -2
- package/dist/commands/login.d.ts +4 -0
- package/dist/commands/login.js +55 -10
- package/dist/commands/mcp.js +2 -1
- package/dist/commands/session.d.ts +31 -0
- package/dist/commands/session.js +140 -0
- package/dist/commands/setup.js +2 -1
- package/dist/commands.js +41 -20
- package/dist/config-file.d.ts +9 -0
- package/dist/config-file.js +39 -9
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/format-bytes.d.ts +5 -0
- package/dist/format-bytes.js +11 -0
- package/dist/update-check.d.ts +10 -0
- package/dist/update-check.js +28 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,10 +25,11 @@ uploads put ./capture-2026-…Z.png --pr 123 --name hero.png # clean leaf, sta
|
|
|
25
25
|
uploads put ./shot.png --pr 123 --name hero.png --dry-run --format url # preview URL, no upload
|
|
26
26
|
uploads gallery create --title "Release screenshots"
|
|
27
27
|
uploads put ./after.png --gallery gal_example
|
|
28
|
-
|
|
29
|
-
uploads
|
|
30
|
-
uploads meta
|
|
31
|
-
uploads
|
|
28
|
+
# custom metadata (queryable): page URL, in-app path, which surface
|
|
29
|
+
uploads put ./shot.png --meta url=https://app.example/settings --meta path=/settings --meta app=web
|
|
30
|
+
uploads meta get screenshots/myapp/42/shot.webp
|
|
31
|
+
uploads meta set screenshots/myapp/42/shot.webp path=/onboarding --delete url
|
|
32
|
+
uploads find app=web path=/settings # or: list --meta app=web
|
|
32
33
|
uploads doctor
|
|
33
34
|
```
|
|
34
35
|
|
|
@@ -37,10 +38,19 @@ up local source; product docs and PR “how to try it” examples should use the
|
|
|
37
38
|
global `uploads` form above.
|
|
38
39
|
|
|
39
40
|
Commands: `attach`, `put`, `gallery`, `comment`, `list`, `find`, `meta`, `delete`, `usage`,
|
|
40
|
-
`reconcile`, `purge-expired`, `setup`, `install`, `
|
|
41
|
+
`reconcile`, `purge-expired`, `setup`, `install`, `login`, `whoami` (alias `status`),
|
|
42
|
+
`logout`, `invite`, `admin`, `config`, `doctor`, `health`, `mcp`, `completion`.
|
|
43
|
+
|
|
44
|
+
**Help:** bare `uploads` / `uploads help` / `--help` shows essentials; use
|
|
45
|
+
`uploads help --all` (or `--help --all`) for the full command list. Per-command:
|
|
46
|
+
`uploads <cmd> --help`.
|
|
47
|
+
|
|
48
|
+
**Shell completion:** `uploads completion bash|zsh|fish` prints a script to
|
|
49
|
+
stdout. Example (zsh): `uploads completion zsh > ~/.zsh/completions/_uploads`.
|
|
41
50
|
|
|
42
51
|
**Globals (before the command):** `--api-url`, `--token`, `--workspace` / `-w`,
|
|
43
|
-
`--env-file`, `--json`, `--quiet`, `--version` / `-V`, `-h` / `--help
|
|
52
|
+
`--env-file`, `--json`, `--quiet`, `--version` / `-V`, `-h` / `--help`, `--all`
|
|
53
|
+
(with root help).
|
|
44
54
|
|
|
45
55
|
**Update hints:** after a successful run the CLI may print one stderr line when a
|
|
46
56
|
newer npm release is available (at most once/day, `~/.cache/uploads/`). Silence
|
|
@@ -65,7 +75,13 @@ use `gh/…`. Workspaces may restrict put/sign to those roots via
|
|
|
65
75
|
**Image optimization:** by default, still images are re-encoded to WebP (long edge
|
|
66
76
|
capped, high quality) before upload so GitHub embeds stay small, and **EXIF is
|
|
67
77
|
stripped**. Pass `--keep-exif` / `UPLOADS_KEEP_EXIF=1` to preserve image metadata, or
|
|
68
|
-
`--no-optimize` / `UPLOADS_NO_OPTIMIZE=1` to upload originals unchanged.
|
|
78
|
+
`--no-optimize` / `UPLOADS_NO_OPTIMIZE=1` to upload originals unchanged. Optimize
|
|
79
|
+
notes print human sizes (e.g. `411.5 KB → 94.2 KB`).
|
|
80
|
+
|
|
81
|
+
**Re-upload / hot-swap:** the same key overwrites in place with no prompt (stable
|
|
82
|
+
`--pr` / `attach` paths). Human mode notes `>> replaced existing object (same URL)`;
|
|
83
|
+
JSON includes `replaced`. Preview with `--dry-run` (reports _would replace_ when
|
|
84
|
+
the key already exists).
|
|
69
85
|
|
|
70
86
|
**Frames (opt-in):** `--frame phone|browser|iphone-16-pro` composites chrome
|
|
71
87
|
**before** optimize. `phone`/`browser` are procedural; `iphone-16-pro` fetches
|
package/dist/cli-args.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface GlobalFlags {
|
|
|
7
7
|
quiet?: boolean;
|
|
8
8
|
/** `--version` / `-V` — print package version and exit. */
|
|
9
9
|
version?: boolean;
|
|
10
|
+
/** `--all` — with root help, show the full command list. */
|
|
11
|
+
all?: boolean;
|
|
10
12
|
}
|
|
11
13
|
export interface ParsedArgv {
|
|
12
14
|
globals: GlobalFlags;
|
package/dist/cli-args.js
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* uploads.sh brand tokens + terminal chevron mark for root help.
|
|
3
|
+
* Colors mirror packages/ui/src/tokens.css; geometry from Brand.tsx / favicon.
|
|
4
|
+
*/
|
|
5
|
+
export interface Rgb {
|
|
6
|
+
r: number;
|
|
7
|
+
g: number;
|
|
8
|
+
b: number;
|
|
9
|
+
}
|
|
10
|
+
/** Design tokens from packages/ui (dark scheme). */
|
|
11
|
+
export declare const BRAND: {
|
|
12
|
+
readonly bg: {
|
|
13
|
+
readonly r: 10;
|
|
14
|
+
readonly g: 10;
|
|
15
|
+
readonly b: 11;
|
|
16
|
+
};
|
|
17
|
+
readonly panel: {
|
|
18
|
+
readonly r: 18;
|
|
19
|
+
readonly g: 18;
|
|
20
|
+
readonly b: 20;
|
|
21
|
+
};
|
|
22
|
+
readonly line: {
|
|
23
|
+
readonly r: 35;
|
|
24
|
+
readonly g: 35;
|
|
25
|
+
readonly b: 39;
|
|
26
|
+
};
|
|
27
|
+
readonly fg: {
|
|
28
|
+
readonly r: 236;
|
|
29
|
+
readonly g: 236;
|
|
30
|
+
readonly b: 234;
|
|
31
|
+
};
|
|
32
|
+
readonly body: {
|
|
33
|
+
readonly r: 179;
|
|
34
|
+
readonly g: 179;
|
|
35
|
+
readonly b: 173;
|
|
36
|
+
};
|
|
37
|
+
readonly muted: {
|
|
38
|
+
readonly r: 138;
|
|
39
|
+
readonly g: 138;
|
|
40
|
+
readonly b: 131;
|
|
41
|
+
};
|
|
42
|
+
readonly accent: {
|
|
43
|
+
readonly r: 194;
|
|
44
|
+
readonly g: 126;
|
|
45
|
+
readonly b: 255;
|
|
46
|
+
};
|
|
47
|
+
readonly green: {
|
|
48
|
+
readonly r: 143;
|
|
49
|
+
readonly g: 174;
|
|
50
|
+
readonly b: 98;
|
|
51
|
+
};
|
|
52
|
+
readonly red: {
|
|
53
|
+
readonly r: 217;
|
|
54
|
+
readonly g: 138;
|
|
55
|
+
readonly b: 156;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
export declare function mixRgb(a: Rgb, b: Rgb, t: number): Rgb;
|
|
59
|
+
export declare function accentAt(opacity: number, over?: Rgb): Rgb;
|
|
60
|
+
/** Deep-copy the thin chevron opacity grid. */
|
|
61
|
+
export declare function rasterizeMark(): (number | null)[][];
|
|
62
|
+
/**
|
|
63
|
+
* Half-block render of the mark (▀/▄/█). Two pixel rows → one terminal row.
|
|
64
|
+
*/
|
|
65
|
+
export declare function renderBrandMarkLines(options?: {
|
|
66
|
+
color?: boolean;
|
|
67
|
+
}): string[];
|
|
68
|
+
/** Default CLI tagline. */
|
|
69
|
+
export declare const DEFAULT_TAGLINE = "GitHub screenshot + recording uploads for agents";
|
|
70
|
+
/**
|
|
71
|
+
* Brand lockup:
|
|
72
|
+
* [mark] uploads.sh
|
|
73
|
+
* [mark] GitHub screenshot + recording uploads for agents
|
|
74
|
+
* [mark] v0.9.0
|
|
75
|
+
*/
|
|
76
|
+
export declare function formatBrandHeader(options?: {
|
|
77
|
+
color?: boolean;
|
|
78
|
+
label?: string;
|
|
79
|
+
tagline?: string;
|
|
80
|
+
version?: string;
|
|
81
|
+
}): string;
|
|
82
|
+
export declare function formatUpdateBanner(options: {
|
|
83
|
+
current: string;
|
|
84
|
+
latest: string;
|
|
85
|
+
color?: boolean;
|
|
86
|
+
}): string;
|
|
87
|
+
export declare function formatAuthBanner(options?: {
|
|
88
|
+
color?: boolean;
|
|
89
|
+
}): string;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* uploads.sh brand tokens + terminal chevron mark for root help.
|
|
3
|
+
* Colors mirror packages/ui/src/tokens.css; geometry from Brand.tsx / favicon.
|
|
4
|
+
*/
|
|
5
|
+
/** Design tokens from packages/ui (dark scheme). */
|
|
6
|
+
export const BRAND = {
|
|
7
|
+
bg: { r: 0x0a, g: 0x0a, b: 0x0b },
|
|
8
|
+
panel: { r: 0x12, g: 0x12, b: 0x14 },
|
|
9
|
+
line: { r: 0x23, g: 0x23, b: 0x27 },
|
|
10
|
+
fg: { r: 0xec, g: 0xec, b: 0xea },
|
|
11
|
+
body: { r: 0xb3, g: 0xb3, b: 0xad },
|
|
12
|
+
muted: { r: 0x8a, g: 0x8a, b: 0x83 },
|
|
13
|
+
accent: { r: 0xc2, g: 0x7e, b: 0xff },
|
|
14
|
+
green: { r: 0x8f, g: 0xae, b: 0x62 },
|
|
15
|
+
red: { r: 0xd9, g: 0x8a, b: 0x9c },
|
|
16
|
+
};
|
|
17
|
+
export function mixRgb(a, b, t) {
|
|
18
|
+
const u = Math.min(1, Math.max(0, t));
|
|
19
|
+
return {
|
|
20
|
+
r: Math.round(a.r * u + b.r * (1 - u)),
|
|
21
|
+
g: Math.round(a.g * u + b.g * (1 - u)),
|
|
22
|
+
b: Math.round(a.b * u + b.b * (1 - u)),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function accentAt(opacity, over = BRAND.panel) {
|
|
26
|
+
return mixRgb(BRAND.accent, over, opacity);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Thin stacked chevrons (1-cell stroke, 5×9) with brand opacities 1 / 0.55 / 0.28.
|
|
30
|
+
* Mirrors the three fading Λ shapes from the favicon without fat 4×4 fills.
|
|
31
|
+
*/
|
|
32
|
+
const THIN_CHEVRON = (() => {
|
|
33
|
+
const rows = [" # ", " # # ", "# #", " # ", " # # ", "# #", " # ", " # # ", "# #"];
|
|
34
|
+
const opacities = [1, 1, 1, 0.55, 0.55, 0.55, 0.28, 0.28, 0.28];
|
|
35
|
+
return rows.map((row, y) => [...row].map((ch) => (ch === "#" ? opacities[y] : null)));
|
|
36
|
+
})();
|
|
37
|
+
/** Deep-copy the thin chevron opacity grid. */
|
|
38
|
+
export function rasterizeMark() {
|
|
39
|
+
return THIN_CHEVRON.map((row) => row.slice());
|
|
40
|
+
}
|
|
41
|
+
function cellColor(v) {
|
|
42
|
+
if (v === null || v <= 0)
|
|
43
|
+
return null;
|
|
44
|
+
return accentAt(v);
|
|
45
|
+
}
|
|
46
|
+
function ansiFg(c) {
|
|
47
|
+
return `\u001b[38;2;${c.r};${c.g};${c.b}m`;
|
|
48
|
+
}
|
|
49
|
+
function ansiBg(c) {
|
|
50
|
+
return `\u001b[48;2;${c.r};${c.g};${c.b}m`;
|
|
51
|
+
}
|
|
52
|
+
const ANSI_RESET = "\u001b[0m";
|
|
53
|
+
/**
|
|
54
|
+
* Half-block render of the mark (▀/▄/█). Two pixel rows → one terminal row.
|
|
55
|
+
*/
|
|
56
|
+
export function renderBrandMarkLines(options = {}) {
|
|
57
|
+
const grid = rasterizeMark();
|
|
58
|
+
const color = options.color ?? false;
|
|
59
|
+
const height = grid.length;
|
|
60
|
+
const width = grid[0]?.length ?? 0;
|
|
61
|
+
const lines = [];
|
|
62
|
+
for (let y = 0; y < height; y += 2) {
|
|
63
|
+
let line = "";
|
|
64
|
+
for (let x = 0; x < width; x++) {
|
|
65
|
+
const top = grid[y]?.[x] ?? null;
|
|
66
|
+
const bot = grid[y + 1]?.[x] ?? null;
|
|
67
|
+
const tc = cellColor(top);
|
|
68
|
+
const bc = cellColor(bot);
|
|
69
|
+
if (!color) {
|
|
70
|
+
const strength = Math.max(top ?? 0, bot ?? 0);
|
|
71
|
+
if (strength <= 0)
|
|
72
|
+
line += " ";
|
|
73
|
+
else if (top && bot)
|
|
74
|
+
line += strength >= 0.8 ? "█" : strength >= 0.4 ? "▓" : "░";
|
|
75
|
+
else if (top)
|
|
76
|
+
line += "▀";
|
|
77
|
+
else
|
|
78
|
+
line += "▄";
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (tc && bc) {
|
|
82
|
+
if (top === bot)
|
|
83
|
+
line += ansiFg(tc) + "█" + ANSI_RESET;
|
|
84
|
+
else
|
|
85
|
+
line += ansiFg(tc) + ansiBg(bc) + "▀" + ANSI_RESET;
|
|
86
|
+
}
|
|
87
|
+
else if (tc)
|
|
88
|
+
line += ansiFg(tc) + "▀" + ANSI_RESET;
|
|
89
|
+
else if (bc)
|
|
90
|
+
line += ansiFg(bc) + "▄" + ANSI_RESET;
|
|
91
|
+
else
|
|
92
|
+
line += " ";
|
|
93
|
+
}
|
|
94
|
+
lines.push(line.replace(/\s+$/, ""));
|
|
95
|
+
}
|
|
96
|
+
return lines;
|
|
97
|
+
}
|
|
98
|
+
/** Default CLI tagline. */
|
|
99
|
+
export const DEFAULT_TAGLINE = "GitHub screenshot + recording uploads for agents";
|
|
100
|
+
/**
|
|
101
|
+
* Brand lockup:
|
|
102
|
+
* [mark] uploads.sh
|
|
103
|
+
* [mark] GitHub screenshot + recording uploads for agents
|
|
104
|
+
* [mark] v0.9.0
|
|
105
|
+
*/
|
|
106
|
+
export function formatBrandHeader(options = {}) {
|
|
107
|
+
const color = options.color ?? false;
|
|
108
|
+
const label = options.label ?? "uploads.sh";
|
|
109
|
+
const tagline = options.tagline ?? DEFAULT_TAGLINE;
|
|
110
|
+
const markLines = renderBrandMarkLines({ color });
|
|
111
|
+
const markWidth = Math.max(...markLines.map((l) => visibleWidth(l)), 1);
|
|
112
|
+
const gap = " ";
|
|
113
|
+
const paint = (text, rgb, bold = false) => color
|
|
114
|
+
? `${bold ? "\u001b[1m" : ""}\u001b[38;2;${rgb.r};${rgb.g};${rgb.b}m${text}\u001b[0m`
|
|
115
|
+
: text;
|
|
116
|
+
const extras = [
|
|
117
|
+
paint(label, BRAND.fg, true),
|
|
118
|
+
paint(tagline, BRAND.muted),
|
|
119
|
+
options.version ? paint(`v${options.version}`, BRAND.muted) : "",
|
|
120
|
+
];
|
|
121
|
+
const out = [];
|
|
122
|
+
const rows = Math.max(markLines.length, extras.filter(Boolean).length);
|
|
123
|
+
for (let i = 0; i < rows; i++) {
|
|
124
|
+
const mark = (markLines[i] ?? "").padEnd(markWidth, " ");
|
|
125
|
+
const extra = extras[i] ? gap + extras[i] : "";
|
|
126
|
+
out.push(mark + extra);
|
|
127
|
+
}
|
|
128
|
+
return out.join("\n") + "\n";
|
|
129
|
+
}
|
|
130
|
+
/** Strip CSI sequences for display-width (ESC is matched as \x1b for the linter). */
|
|
131
|
+
function visibleWidth(s) {
|
|
132
|
+
// eslint-disable-next-line no-control-regex -- intentional: strip ANSI CSI
|
|
133
|
+
return s.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
134
|
+
}
|
|
135
|
+
function boxLines(lines, options = {}) {
|
|
136
|
+
const color = options.color ?? false;
|
|
137
|
+
const tone = options.tone ?? BRAND.accent;
|
|
138
|
+
const width = Math.max(...lines.map((l) => l.length), 1) + 4;
|
|
139
|
+
const bar = "─".repeat(width);
|
|
140
|
+
const pad = (s) => s.padEnd(width - 2);
|
|
141
|
+
if (!color) {
|
|
142
|
+
return [`┌${bar}┐`, ...lines.map((l) => `│ ${pad(l)}│`), `└${bar}┘`, ""].join("\n");
|
|
143
|
+
}
|
|
144
|
+
const edge = (s) => `\u001b[38;2;${tone.r};${tone.g};${tone.b}m${s}\u001b[0m`;
|
|
145
|
+
const title = (s) => `\u001b[1m\u001b[38;2;${tone.r};${tone.g};${tone.b}m${s}\u001b[0m`;
|
|
146
|
+
const cmd = (s) => `\u001b[1m\u001b[38;2;${BRAND.fg.r};${BRAND.fg.g};${BRAND.fg.b}m${s}\u001b[0m`;
|
|
147
|
+
const muted = (s) => `\u001b[38;2;${BRAND.muted.r};${BRAND.muted.g};${BRAND.muted.b}m${s}\u001b[0m`;
|
|
148
|
+
return [
|
|
149
|
+
edge(`┌${bar}┐`),
|
|
150
|
+
...lines.map((l, i) => {
|
|
151
|
+
const body = i === 0 ? title(pad(l)) : i === 1 ? cmd(pad(l)) : muted(pad(l));
|
|
152
|
+
return `${edge("│ ")}${body}${edge("│")}`;
|
|
153
|
+
}),
|
|
154
|
+
edge(`└${bar}┘`),
|
|
155
|
+
"",
|
|
156
|
+
].join("\n");
|
|
157
|
+
}
|
|
158
|
+
export function formatUpdateBanner(options) {
|
|
159
|
+
return boxLines([`Update available ${options.current} → ${options.latest}`, `npm i -g @buildinternet/uploads`], { color: options.color, tone: BRAND.accent });
|
|
160
|
+
}
|
|
161
|
+
export function formatAuthBanner(options = {}) {
|
|
162
|
+
return boxLines(["Sign in via browser", "uploads login"], {
|
|
163
|
+
color: options.color,
|
|
164
|
+
tone: BRAND.red,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI surface for help text and shell completions.
|
|
3
|
+
* Keep in sync when adding root commands or nested subcommands.
|
|
4
|
+
*/
|
|
5
|
+
export interface CatalogCommand {
|
|
6
|
+
/** Root command name (no args). */
|
|
7
|
+
name: string;
|
|
8
|
+
summary: string;
|
|
9
|
+
/** Shown in help left column when set (e.g. `put <file>`). */
|
|
10
|
+
usage?: string;
|
|
11
|
+
/** Included in the short essentials help. */
|
|
12
|
+
essential?: boolean;
|
|
13
|
+
subcommands?: readonly {
|
|
14
|
+
name: string;
|
|
15
|
+
summary: string;
|
|
16
|
+
}[];
|
|
17
|
+
}
|
|
18
|
+
/** Global flags accepted before the subcommand. */
|
|
19
|
+
export declare const GLOBAL_FLAGS: readonly {
|
|
20
|
+
flag: string;
|
|
21
|
+
summary: string;
|
|
22
|
+
}[];
|
|
23
|
+
/** Common flags for put/attach (file-oriented commands). */
|
|
24
|
+
export declare const PUT_LIKE_FLAGS: readonly string[];
|
|
25
|
+
export declare const LIST_LIKE_FLAGS: readonly string[];
|
|
26
|
+
export declare const ROOT_COMMANDS: readonly CatalogCommand[];
|
|
27
|
+
export declare const COMPLETION_SHELLS: readonly ["bash", "zsh", "fish"];
|
|
28
|
+
export type CompletionShell = (typeof COMPLETION_SHELLS)[number];
|
|
29
|
+
export declare function isCompletionShell(value: string): value is CompletionShell;
|
|
30
|
+
export declare function rootCommandNames(): string[];
|
|
31
|
+
/** Also accept plural alias for the completion command. */
|
|
32
|
+
export declare const COMPLETION_ALIASES: readonly ["completion", "completions"];
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI surface for help text and shell completions.
|
|
3
|
+
* Keep in sync when adding root commands or nested subcommands.
|
|
4
|
+
*/
|
|
5
|
+
/** Global flags accepted before the subcommand. */
|
|
6
|
+
export const GLOBAL_FLAGS = [
|
|
7
|
+
{ flag: "--api-url", summary: "API base URL" },
|
|
8
|
+
{ flag: "--token", summary: "Bearer token" },
|
|
9
|
+
{ flag: "--workspace", summary: "Workspace name" },
|
|
10
|
+
{ flag: "-w", summary: "Workspace name (short)" },
|
|
11
|
+
{ flag: "--env-file", summary: "Load env from file" },
|
|
12
|
+
{ flag: "--json", summary: "JSON on stdout" },
|
|
13
|
+
{ flag: "--quiet", summary: "Suppress stderr progress" },
|
|
14
|
+
{ flag: "--version", summary: "Print package version" },
|
|
15
|
+
{ flag: "-V", summary: "Print package version (short)" },
|
|
16
|
+
{ flag: "--help", summary: "Show help" },
|
|
17
|
+
{ flag: "-h", summary: "Show help (short)" },
|
|
18
|
+
{ flag: "--all", summary: "Full root help listing" },
|
|
19
|
+
];
|
|
20
|
+
/** Common flags for put/attach (file-oriented commands). */
|
|
21
|
+
export const PUT_LIKE_FLAGS = [
|
|
22
|
+
"--destination",
|
|
23
|
+
"--prefix",
|
|
24
|
+
"--repo",
|
|
25
|
+
"--ref",
|
|
26
|
+
"--pr",
|
|
27
|
+
"--issue",
|
|
28
|
+
"--comment",
|
|
29
|
+
"--no-comment",
|
|
30
|
+
"--format",
|
|
31
|
+
"--dry-run",
|
|
32
|
+
"--name",
|
|
33
|
+
"--no-optimize",
|
|
34
|
+
"--frame",
|
|
35
|
+
"--frame-url",
|
|
36
|
+
"--gallery",
|
|
37
|
+
"--meta",
|
|
38
|
+
"--workspace",
|
|
39
|
+
"-w",
|
|
40
|
+
"--help",
|
|
41
|
+
"-h",
|
|
42
|
+
];
|
|
43
|
+
export const LIST_LIKE_FLAGS = [
|
|
44
|
+
"--prefix",
|
|
45
|
+
"--limit",
|
|
46
|
+
"--cursor",
|
|
47
|
+
"--meta",
|
|
48
|
+
"--workspace",
|
|
49
|
+
"-w",
|
|
50
|
+
"--help",
|
|
51
|
+
"-h",
|
|
52
|
+
];
|
|
53
|
+
export const ROOT_COMMANDS = [
|
|
54
|
+
{
|
|
55
|
+
name: "attach",
|
|
56
|
+
usage: "attach <file...>",
|
|
57
|
+
summary: "Attach media to the current PR (stable URLs + managed comment)",
|
|
58
|
+
essential: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "put",
|
|
62
|
+
usage: "put <file>",
|
|
63
|
+
summary: "Upload (+ URL + markdown for GitHub)",
|
|
64
|
+
essential: true,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "gallery",
|
|
68
|
+
summary: "Create and organize public media galleries",
|
|
69
|
+
subcommands: [
|
|
70
|
+
{ name: "create", summary: "Create a gallery" },
|
|
71
|
+
{ name: "show", summary: "Show a gallery" },
|
|
72
|
+
{ name: "list", summary: "List galleries" },
|
|
73
|
+
{ name: "delete", summary: "Delete a gallery record" },
|
|
74
|
+
{ name: "add", summary: "Add objects to a gallery" },
|
|
75
|
+
{ name: "link", summary: "Link a gallery to a GitHub issue/PR" },
|
|
76
|
+
{ name: "unlink", summary: "Unlink a gallery from GitHub" },
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "comment",
|
|
81
|
+
summary: "Create/update a PR/issue attachments comment (via gh)",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "list",
|
|
85
|
+
summary: "List objects (--meta k=v filters by queryable metadata)",
|
|
86
|
+
essential: true,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "find",
|
|
90
|
+
usage: "find k=v...",
|
|
91
|
+
summary: "List objects matching metadata (alias for list --meta)",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "meta",
|
|
95
|
+
summary: "Get/set an object's queryable metadata",
|
|
96
|
+
subcommands: [
|
|
97
|
+
{ name: "get", summary: "Show metadata for an object" },
|
|
98
|
+
{ name: "set", summary: "Merge-set and/or delete metadata pairs" },
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "delete",
|
|
103
|
+
usage: "delete <key>",
|
|
104
|
+
summary: "Delete object",
|
|
105
|
+
essential: true,
|
|
106
|
+
},
|
|
107
|
+
{ name: "usage", summary: "Workspace storage / upload counters" },
|
|
108
|
+
{ name: "reconcile", summary: "Rebuild usage ledger from storage" },
|
|
109
|
+
{ name: "purge-expired", summary: "Delete objects past retentionDays" },
|
|
110
|
+
{ name: "setup", summary: "Inspect/configure advanced CLI settings" },
|
|
111
|
+
{
|
|
112
|
+
name: "install",
|
|
113
|
+
summary: "Install the agent skill + register the remote MCP server",
|
|
114
|
+
essential: true,
|
|
115
|
+
subcommands: [
|
|
116
|
+
{ name: "skill", summary: "Install the agent skill only" },
|
|
117
|
+
{ name: "mcp", summary: "Register the remote MCP server only" },
|
|
118
|
+
{ name: "all", summary: "Install skill and MCP (default)" },
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "login",
|
|
123
|
+
summary: "Sign in via browser (or an enrollment code) and save credentials",
|
|
124
|
+
essential: true,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "whoami",
|
|
128
|
+
summary: "Show active workspace and token (alias: status)",
|
|
129
|
+
essential: true,
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "logout",
|
|
133
|
+
summary: "Remove the saved UPLOADS_TOKEN from the config file",
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "invite",
|
|
137
|
+
summary: "Invite a teammate to a workspace (workspace admin; device login)",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "admin",
|
|
141
|
+
summary: "Site-operator invitation management (ADMIN_TOKEN)",
|
|
142
|
+
subcommands: [
|
|
143
|
+
{ name: "invite", summary: "Create a workspace invitation" },
|
|
144
|
+
{ name: "enrollment", summary: "Legacy alias for invite" },
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "config",
|
|
149
|
+
summary: "Show path, init, or set shared config",
|
|
150
|
+
subcommands: [
|
|
151
|
+
{ name: "path", summary: "Print config file path" },
|
|
152
|
+
{ name: "show", summary: "Show effective settings" },
|
|
153
|
+
{ name: "init", summary: "Create or update UPLOADS_* keys" },
|
|
154
|
+
{ name: "set", summary: "Set one UPLOADS_* key" },
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "doctor",
|
|
159
|
+
summary: "Health + auth + workspace checks",
|
|
160
|
+
essential: true,
|
|
161
|
+
},
|
|
162
|
+
{ name: "health", summary: "API liveness (no auth)" },
|
|
163
|
+
{ name: "mcp", summary: "Serve MCP over stdio (tools mirror the CLI)" },
|
|
164
|
+
{
|
|
165
|
+
name: "help",
|
|
166
|
+
summary: "Show this help (essentials; use --all for the full list)",
|
|
167
|
+
subcommands: [{ name: "--all", summary: "Full command list and config" }],
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: "completion",
|
|
171
|
+
summary: "Print shell completion script (bash, zsh, or fish)",
|
|
172
|
+
subcommands: [
|
|
173
|
+
{ name: "bash", summary: "Bash completion script" },
|
|
174
|
+
{ name: "zsh", summary: "Zsh completion script" },
|
|
175
|
+
{ name: "fish", summary: "Fish completion script" },
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
export const COMPLETION_SHELLS = ["bash", "zsh", "fish"];
|
|
180
|
+
export function isCompletionShell(value) {
|
|
181
|
+
return COMPLETION_SHELLS.includes(value);
|
|
182
|
+
}
|
|
183
|
+
export function rootCommandNames() {
|
|
184
|
+
return ROOT_COMMANDS.map((c) => c.name);
|
|
185
|
+
}
|
|
186
|
+
/** Also accept plural alias for the completion command. */
|
|
187
|
+
export const COMPLETION_ALIASES = ["completion", "completions"];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type CliStyle } from "./cli-style.js";
|
|
2
|
+
export interface RootHelpOptions {
|
|
3
|
+
/** Full command list + config layers. Default: curated essentials. */
|
|
4
|
+
full?: boolean;
|
|
5
|
+
/** Force color on/off; default is TTY + env detection on stderr. */
|
|
6
|
+
color?: boolean;
|
|
7
|
+
style?: CliStyle;
|
|
8
|
+
/** Include pixel brand mark in the header (default true). */
|
|
9
|
+
brandMark?: boolean;
|
|
10
|
+
/** Override package version shown in the header. */
|
|
11
|
+
version?: string;
|
|
12
|
+
/** When set, show a noticeable update banner under the header. */
|
|
13
|
+
latestVersion?: string;
|
|
14
|
+
/**
|
|
15
|
+
* When true, show a loud "not signed in" banner at the very top with
|
|
16
|
+
* `uploads login`. Callers should set this when no token is configured.
|
|
17
|
+
*/
|
|
18
|
+
needsAuth?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Root help text. Default is a short essentials view; pass `full: true` for
|
|
22
|
+
* the complete command + config dump (`uploads help --all`).
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatRootHelp(options?: RootHelpOptions): string;
|
|
25
|
+
/** True when argv for the `help` command requests the full listing. */
|
|
26
|
+
export declare function wantsFullHelp(args: string[]): boolean;
|