@asteroidai/cli 1.8.204 → 1.9.4
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/dist/asteroid.js +36 -15
- package/dist/core.js +30 -12
- package/package.json +1 -1
- package/src/output.test.ts +45 -0
- package/src/output.ts +35 -12
- package/src/reference.ts +1 -0
- package/src/run.test.ts +20 -0
- package/src/run.ts +9 -2
package/dist/asteroid.js
CHANGED
|
@@ -48,16 +48,17 @@ function indent(text2) {
|
|
|
48
48
|
function text(value2) {
|
|
49
49
|
return clean(isScalar(value2) ? String(value2) : JSON.stringify(value2));
|
|
50
50
|
}
|
|
51
|
-
function cell(value2) {
|
|
51
|
+
function cell(value2, options = {}) {
|
|
52
52
|
if (value2 === null || value2 === void 0) return "";
|
|
53
53
|
const line = text(value2).replace(/\s+/g, " ");
|
|
54
|
-
|
|
54
|
+
if (options.full || line.length <= MAX_CELL) return line;
|
|
55
|
+
return `${line.slice(0, MAX_CELL - 1)}\u2026`;
|
|
55
56
|
}
|
|
56
|
-
function columns(rows) {
|
|
57
|
+
function columns(rows, options) {
|
|
57
58
|
const scalarKeys = [];
|
|
58
59
|
for (const row of rows) {
|
|
59
60
|
for (const [key, value2] of Object.entries(row)) {
|
|
60
|
-
if (isScalar(value2) && !HIDDEN.test(key) && !scalarKeys.includes(key))
|
|
61
|
+
if (isScalar(value2) && !HIDDEN.test(key.split(".").at(-1) ?? key) && !scalarKeys.includes(key))
|
|
61
62
|
scalarKeys.push(key);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
@@ -65,16 +66,29 @@ function columns(rows) {
|
|
|
65
66
|
...PREFERRED.filter((key) => scalarKeys.includes(key)),
|
|
66
67
|
...scalarKeys.filter((key) => !PREFERRED.includes(key))
|
|
67
68
|
];
|
|
68
|
-
return ordered.slice(0, MAX_COLUMNS);
|
|
69
|
+
return options.full ? ordered : ordered.slice(0, MAX_COLUMNS);
|
|
69
70
|
}
|
|
70
71
|
function style(format, value2, options) {
|
|
71
72
|
return options.styled ? styleText(format, value2, { validateStream: false }) : value2;
|
|
72
73
|
}
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
const
|
|
74
|
+
function flatten(row) {
|
|
75
|
+
const flat = {};
|
|
76
|
+
for (const [key, value2] of Object.entries(row)) {
|
|
77
|
+
if (!isObject(value2)) {
|
|
78
|
+
flat[key] = value2;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
for (const [inner, v] of Object.entries(value2))
|
|
82
|
+
flat[`${key}.${inner}`] = v;
|
|
83
|
+
}
|
|
84
|
+
return flat;
|
|
85
|
+
}
|
|
86
|
+
function table(input, options = {}) {
|
|
87
|
+
if (input.length === 0) return "No results.";
|
|
88
|
+
const rows = input.map(flatten);
|
|
89
|
+
const keys = columns(rows, options);
|
|
76
90
|
if (keys.length === 0) return rows.map((row) => text(row)).join("\n");
|
|
77
|
-
const cells = rows.map((row) => keys.map((key) => cell(row[key])));
|
|
91
|
+
const cells = rows.map((row) => keys.map((key) => cell(row[key], options)));
|
|
78
92
|
if (options.styled) {
|
|
79
93
|
const grid = new Table({
|
|
80
94
|
head: keys.map((key) => style("bold", key, options)),
|
|
@@ -91,10 +105,10 @@ function table(rows, options = {}) {
|
|
|
91
105
|
"\n"
|
|
92
106
|
);
|
|
93
107
|
}
|
|
94
|
-
function summary(value2) {
|
|
108
|
+
function summary(value2, options) {
|
|
95
109
|
if (Array.isArray(value2))
|
|
96
110
|
return `[${value2.length} item${value2.length === 1 ? "" : "s"}]`;
|
|
97
|
-
if (value2 && typeof value2 === "object") return cell(value2);
|
|
111
|
+
if (value2 && typeof value2 === "object") return cell(value2, options);
|
|
98
112
|
return text(value2);
|
|
99
113
|
}
|
|
100
114
|
function record(value2, options) {
|
|
@@ -109,7 +123,11 @@ ${indent(table(v, options))}`;
|
|
|
109
123
|
return `${label(key)} ${v.map(text).join(`
|
|
110
124
|
${" ".repeat(width + 2)}`)}`;
|
|
111
125
|
}
|
|
112
|
-
|
|
126
|
+
if (isObject(v) && Object.keys(v).length > 0) {
|
|
127
|
+
return `${style("bold", key, options)}:
|
|
128
|
+
${indent(record(v, options))}`;
|
|
129
|
+
}
|
|
130
|
+
return `${label(key)} ${isScalar(v) ? text(v) : summary(v, options)}`;
|
|
113
131
|
}).join("\n");
|
|
114
132
|
}
|
|
115
133
|
function render(value2, options = {}) {
|
|
@@ -5312,7 +5330,7 @@ var ApiError = class extends Error {
|
|
|
5312
5330
|
status;
|
|
5313
5331
|
body;
|
|
5314
5332
|
};
|
|
5315
|
-
var VERSION = "1.
|
|
5333
|
+
var VERSION = "1.9.4";
|
|
5316
5334
|
function problem(status, body, fallback) {
|
|
5317
5335
|
if (body && typeof body === "object") {
|
|
5318
5336
|
const record2 = body;
|
|
@@ -5861,7 +5879,10 @@ async function runCommand(command, parsed, deps) {
|
|
|
5861
5879
|
}
|
|
5862
5880
|
if (response.json !== void 0) {
|
|
5863
5881
|
deps.stdout(
|
|
5864
|
-
`${parsed.json ? JSON.stringify(response.json, null, 2) : render(response.json, {
|
|
5882
|
+
`${parsed.json ? JSON.stringify(response.json, null, 2) : render(response.json, {
|
|
5883
|
+
styled: deps.styled,
|
|
5884
|
+
full: !deps.stdoutIsTTY
|
|
5885
|
+
})}
|
|
5865
5886
|
`
|
|
5866
5887
|
);
|
|
5867
5888
|
return 0;
|
|
@@ -5870,7 +5891,7 @@ async function runCommand(command, parsed, deps) {
|
|
|
5870
5891
|
`);
|
|
5871
5892
|
return 0;
|
|
5872
5893
|
}
|
|
5873
|
-
var DESCRIPTION = "The Asteroid CLI. Sign in with `asteroid login`, or set ASTEROID_API_KEY.";
|
|
5894
|
+
var DESCRIPTION = "The Asteroid CLI. Sign in with `asteroid login`, or set ASTEROID_API_KEY.\nAt a terminal, tables show up to 6 columns and cut long cells to fit; when output is piped, they show every column in full. Use `--json` for every field.";
|
|
5874
5895
|
async function run(argv2, deps) {
|
|
5875
5896
|
try {
|
|
5876
5897
|
const invocation = await parseInvocation(argv2, {
|
package/dist/core.js
CHANGED
|
@@ -4560,16 +4560,17 @@ function indent(text2) {
|
|
|
4560
4560
|
function text(value2) {
|
|
4561
4561
|
return clean(isScalar(value2) ? String(value2) : JSON.stringify(value2));
|
|
4562
4562
|
}
|
|
4563
|
-
function cell(value2) {
|
|
4563
|
+
function cell(value2, options = {}) {
|
|
4564
4564
|
if (value2 === null || value2 === void 0) return "";
|
|
4565
4565
|
const line = text(value2).replace(/\s+/g, " ");
|
|
4566
|
-
|
|
4566
|
+
if (options.full || line.length <= MAX_CELL) return line;
|
|
4567
|
+
return `${line.slice(0, MAX_CELL - 1)}\u2026`;
|
|
4567
4568
|
}
|
|
4568
|
-
function columns(rows) {
|
|
4569
|
+
function columns(rows, options) {
|
|
4569
4570
|
const scalarKeys = [];
|
|
4570
4571
|
for (const row of rows) {
|
|
4571
4572
|
for (const [key, value2] of Object.entries(row)) {
|
|
4572
|
-
if (isScalar(value2) && !HIDDEN.test(key) && !scalarKeys.includes(key))
|
|
4573
|
+
if (isScalar(value2) && !HIDDEN.test(key.split(".").at(-1) ?? key) && !scalarKeys.includes(key))
|
|
4573
4574
|
scalarKeys.push(key);
|
|
4574
4575
|
}
|
|
4575
4576
|
}
|
|
@@ -4577,16 +4578,29 @@ function columns(rows) {
|
|
|
4577
4578
|
...PREFERRED.filter((key) => scalarKeys.includes(key)),
|
|
4578
4579
|
...scalarKeys.filter((key) => !PREFERRED.includes(key))
|
|
4579
4580
|
];
|
|
4580
|
-
return ordered.slice(0, MAX_COLUMNS);
|
|
4581
|
+
return options.full ? ordered : ordered.slice(0, MAX_COLUMNS);
|
|
4581
4582
|
}
|
|
4582
4583
|
function style(format, value2, options) {
|
|
4583
4584
|
return options.styled ? styleText(format, value2, { validateStream: false }) : value2;
|
|
4584
4585
|
}
|
|
4585
|
-
function
|
|
4586
|
-
|
|
4587
|
-
const
|
|
4586
|
+
function flatten(row) {
|
|
4587
|
+
const flat = {};
|
|
4588
|
+
for (const [key, value2] of Object.entries(row)) {
|
|
4589
|
+
if (!isObject(value2)) {
|
|
4590
|
+
flat[key] = value2;
|
|
4591
|
+
continue;
|
|
4592
|
+
}
|
|
4593
|
+
for (const [inner, v] of Object.entries(value2))
|
|
4594
|
+
flat[`${key}.${inner}`] = v;
|
|
4595
|
+
}
|
|
4596
|
+
return flat;
|
|
4597
|
+
}
|
|
4598
|
+
function table(input, options = {}) {
|
|
4599
|
+
if (input.length === 0) return "No results.";
|
|
4600
|
+
const rows = input.map(flatten);
|
|
4601
|
+
const keys = columns(rows, options);
|
|
4588
4602
|
if (keys.length === 0) return rows.map((row) => text(row)).join("\n");
|
|
4589
|
-
const cells = rows.map((row) => keys.map((key) => cell(row[key])));
|
|
4603
|
+
const cells = rows.map((row) => keys.map((key) => cell(row[key], options)));
|
|
4590
4604
|
if (options.styled) {
|
|
4591
4605
|
const grid = new Table({
|
|
4592
4606
|
head: keys.map((key) => style("bold", key, options)),
|
|
@@ -4603,10 +4617,10 @@ function table(rows, options = {}) {
|
|
|
4603
4617
|
"\n"
|
|
4604
4618
|
);
|
|
4605
4619
|
}
|
|
4606
|
-
function summary(value2) {
|
|
4620
|
+
function summary(value2, options) {
|
|
4607
4621
|
if (Array.isArray(value2))
|
|
4608
4622
|
return `[${value2.length} item${value2.length === 1 ? "" : "s"}]`;
|
|
4609
|
-
if (value2 && typeof value2 === "object") return cell(value2);
|
|
4623
|
+
if (value2 && typeof value2 === "object") return cell(value2, options);
|
|
4610
4624
|
return text(value2);
|
|
4611
4625
|
}
|
|
4612
4626
|
function record(value2, options) {
|
|
@@ -4621,7 +4635,11 @@ ${indent(table(v, options))}`;
|
|
|
4621
4635
|
return `${label(key)} ${v.map(text).join(`
|
|
4622
4636
|
${" ".repeat(width + 2)}`)}`;
|
|
4623
4637
|
}
|
|
4624
|
-
|
|
4638
|
+
if (isObject(v) && Object.keys(v).length > 0) {
|
|
4639
|
+
return `${style("bold", key, options)}:
|
|
4640
|
+
${indent(record(v, options))}`;
|
|
4641
|
+
}
|
|
4642
|
+
return `${label(key)} ${isScalar(v) ? text(v) : summary(v, options)}`;
|
|
4625
4643
|
}).join("\n");
|
|
4626
4644
|
}
|
|
4627
4645
|
function render(value2, options = {}) {
|
package/package.json
CHANGED
package/src/output.test.ts
CHANGED
|
@@ -23,4 +23,49 @@ describe("render", () => {
|
|
|
23
23
|
expect(render(rows)).not.toContain("┌");
|
|
24
24
|
expect(render(rows, { styled: true })).toContain("┌");
|
|
25
25
|
});
|
|
26
|
+
|
|
27
|
+
it("prints nested objects in full, not as cut JSON", () => {
|
|
28
|
+
const out = render({
|
|
29
|
+
workflow: { id: "3cfc3c1d-e38d-4132-a5ee-8847136d491d", name: "Nebula" },
|
|
30
|
+
version: { version: 3, isPublished: true },
|
|
31
|
+
});
|
|
32
|
+
expect(out).toContain("3cfc3c1d-e38d-4132-a5ee-8847136d491d");
|
|
33
|
+
expect(out).toMatch(/workflow:\n {2}id +3cfc3c1d/);
|
|
34
|
+
expect(out).not.toContain("…");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("flattens one level of nested fields into table columns", () => {
|
|
38
|
+
const out = render([
|
|
39
|
+
{ date: "2026-10-09", outcomes: { success: 3, failure: 1 } },
|
|
40
|
+
]);
|
|
41
|
+
expect(out).toContain("OUTCOMES.SUCCESS");
|
|
42
|
+
expect(out).toMatch(/2026-10-09 +3 +1/);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("hides nested fields that are hidden at the top level", () => {
|
|
46
|
+
const out = render([
|
|
47
|
+
{ id: "1", execution: { agentId: "a-1", status: "failed" } },
|
|
48
|
+
]);
|
|
49
|
+
expect(out).toContain("EXECUTION.STATUS");
|
|
50
|
+
expect(out).not.toContain("AGENTID");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("keeps long cells whole when asked", () => {
|
|
54
|
+
const secrets = `ECW(51d1db07-a6e1-4b1d-8303-a472b78923e8)[PASSWORD=##ECW_PASSWORD##]`;
|
|
55
|
+
const rows = [{ id: "p-1", secrets }];
|
|
56
|
+
expect(render(rows)).toContain("…");
|
|
57
|
+
expect(render(rows, { full: true })).toContain(secrets);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("shows every column when asked, six otherwise", () => {
|
|
61
|
+
const row = Object.fromEntries(
|
|
62
|
+
["id", "a", "b", "c", "d", "e", "f", "g"].map((key) => [
|
|
63
|
+
key,
|
|
64
|
+
key.toUpperCase(),
|
|
65
|
+
]),
|
|
66
|
+
);
|
|
67
|
+
const header = (out: string) => out.split("\n")[0].trim().split(/\s+/);
|
|
68
|
+
expect(header(render([row]))).toHaveLength(6);
|
|
69
|
+
expect(header(render([row], { full: true }))).toHaveLength(8);
|
|
70
|
+
});
|
|
26
71
|
});
|
package/src/output.ts
CHANGED
|
@@ -22,6 +22,7 @@ type Row = Record<string, unknown>;
|
|
|
22
22
|
|
|
23
23
|
export interface RenderOptions {
|
|
24
24
|
styled?: boolean;
|
|
25
|
+
full?: boolean;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export function clean(text: string): string {
|
|
@@ -49,17 +50,22 @@ function text(value: unknown): string {
|
|
|
49
50
|
return clean(isScalar(value) ? String(value) : JSON.stringify(value));
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
function cell(value: unknown): string {
|
|
53
|
+
function cell(value: unknown, options: RenderOptions = {}): string {
|
|
53
54
|
if (value === null || value === undefined) return "";
|
|
54
55
|
const line = text(value).replace(/\s+/g, " ");
|
|
55
|
-
|
|
56
|
+
if (options.full || line.length <= MAX_CELL) return line;
|
|
57
|
+
return `${line.slice(0, MAX_CELL - 1)}…`;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
function columns(rows: Row[]): string[] {
|
|
60
|
+
function columns(rows: Row[], options: RenderOptions): string[] {
|
|
59
61
|
const scalarKeys: string[] = [];
|
|
60
62
|
for (const row of rows) {
|
|
61
63
|
for (const [key, value] of Object.entries(row)) {
|
|
62
|
-
if (
|
|
64
|
+
if (
|
|
65
|
+
isScalar(value) &&
|
|
66
|
+
!HIDDEN.test(key.split(".").at(-1) ?? key) &&
|
|
67
|
+
!scalarKeys.includes(key)
|
|
68
|
+
)
|
|
63
69
|
scalarKeys.push(key);
|
|
64
70
|
}
|
|
65
71
|
}
|
|
@@ -67,7 +73,7 @@ function columns(rows: Row[]): string[] {
|
|
|
67
73
|
...PREFERRED.filter((key) => scalarKeys.includes(key)),
|
|
68
74
|
...scalarKeys.filter((key) => !PREFERRED.includes(key)),
|
|
69
75
|
];
|
|
70
|
-
return ordered.slice(0, MAX_COLUMNS);
|
|
76
|
+
return options.full ? ordered : ordered.slice(0, MAX_COLUMNS);
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
function style(
|
|
@@ -80,11 +86,25 @@ function style(
|
|
|
80
86
|
: value;
|
|
81
87
|
}
|
|
82
88
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
89
|
+
function flatten(row: Row): Row {
|
|
90
|
+
const flat: Row = {};
|
|
91
|
+
for (const [key, value] of Object.entries(row)) {
|
|
92
|
+
if (!isObject(value)) {
|
|
93
|
+
flat[key] = value;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
for (const [inner, v] of Object.entries(value as Row))
|
|
97
|
+
flat[`${key}.${inner}`] = v;
|
|
98
|
+
}
|
|
99
|
+
return flat;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function table(input: Row[], options: RenderOptions = {}): string {
|
|
103
|
+
if (input.length === 0) return "No results.";
|
|
104
|
+
const rows = input.map(flatten);
|
|
105
|
+
const keys = columns(rows, options);
|
|
86
106
|
if (keys.length === 0) return rows.map((row) => text(row)).join("\n");
|
|
87
|
-
const cells = rows.map((row) => keys.map((key) => cell(row[key])));
|
|
107
|
+
const cells = rows.map((row) => keys.map((key) => cell(row[key], options)));
|
|
88
108
|
if (options.styled) {
|
|
89
109
|
const grid = new Table({
|
|
90
110
|
head: keys.map((key) => style("bold", key, options)),
|
|
@@ -106,10 +126,10 @@ export function table(rows: Row[], options: RenderOptions = {}): string {
|
|
|
106
126
|
);
|
|
107
127
|
}
|
|
108
128
|
|
|
109
|
-
function summary(value: unknown): string {
|
|
129
|
+
function summary(value: unknown, options: RenderOptions): string {
|
|
110
130
|
if (Array.isArray(value))
|
|
111
131
|
return `[${value.length} item${value.length === 1 ? "" : "s"}]`;
|
|
112
|
-
if (value && typeof value === "object") return cell(value);
|
|
132
|
+
if (value && typeof value === "object") return cell(value, options);
|
|
113
133
|
return text(value);
|
|
114
134
|
}
|
|
115
135
|
|
|
@@ -124,7 +144,10 @@ function record(value: Row, options: RenderOptions): string {
|
|
|
124
144
|
if (Array.isArray(v) && v.length > 0 && v.every(isScalar)) {
|
|
125
145
|
return `${label(key)} ${v.map(text).join(`\n${" ".repeat(width + 2)}`)}`;
|
|
126
146
|
}
|
|
127
|
-
|
|
147
|
+
if (isObject(v) && Object.keys(v as Row).length > 0) {
|
|
148
|
+
return `${style("bold", key, options)}:\n${indent(record(v as Row, options))}`;
|
|
149
|
+
}
|
|
150
|
+
return `${label(key)} ${isScalar(v) ? text(v) : summary(v, options)}`;
|
|
128
151
|
})
|
|
129
152
|
.join("\n");
|
|
130
153
|
}
|
package/src/reference.ts
CHANGED
|
@@ -138,6 +138,7 @@ export function renderReference(commands: CliCommand[]): string {
|
|
|
138
138
|
"Sign in with `asteroid login`, or set `ASTEROID_API_KEY` for CI and agents.",
|
|
139
139
|
"Commands that return data print compact text. Add `--json` to get the response as JSON.",
|
|
140
140
|
"The text output may change between releases. Scripts should read `--json`.",
|
|
141
|
+
"At a terminal, tables show up to 6 columns and cut long cells to fit; when output is piped, they show every column in full. Use `--json` for every field.",
|
|
141
142
|
"Downloads write raw bytes. `login`, `logout` and `use` only report status on stderr.",
|
|
142
143
|
"Exit codes: 0 ok, 1 API error, 2 usage error.",
|
|
143
144
|
"",
|
package/src/run.test.ts
CHANGED
|
@@ -269,6 +269,26 @@ describe("guards", () => {
|
|
|
269
269
|
});
|
|
270
270
|
});
|
|
271
271
|
|
|
272
|
+
describe("cell width", () => {
|
|
273
|
+
const long = "x".repeat(80);
|
|
274
|
+
const reply = () => json({ items: [{ id: "w-1", name: long }] });
|
|
275
|
+
|
|
276
|
+
it("keeps cells whole when stdout is not a terminal", async () => {
|
|
277
|
+
const h = harness({ ASTEROID_API_KEY: "sk_test" }, reply);
|
|
278
|
+
await run(["workflow", "list"], h.deps);
|
|
279
|
+
expect(h.out.join("")).toContain(long);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("cuts long cells at a terminal", async () => {
|
|
283
|
+
const h = harness({ ASTEROID_API_KEY: "sk_test" }, reply);
|
|
284
|
+
h.deps.stdoutIsTTY = true;
|
|
285
|
+
await run(["workflow", "list"], h.deps);
|
|
286
|
+
const out = h.out.join("");
|
|
287
|
+
expect(out).toContain(`${"x".repeat(59)}…`);
|
|
288
|
+
expect(out).not.toContain(long);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
272
292
|
describe("terminal safety", () => {
|
|
273
293
|
it("refuses to print a download to a terminal", async () => {
|
|
274
294
|
const h = harness(
|
package/src/run.ts
CHANGED
|
@@ -138,7 +138,14 @@ async function runCommand(
|
|
|
138
138
|
}
|
|
139
139
|
if (response.json !== undefined) {
|
|
140
140
|
deps.stdout(
|
|
141
|
-
`${
|
|
141
|
+
`${
|
|
142
|
+
parsed.json
|
|
143
|
+
? JSON.stringify(response.json, null, 2)
|
|
144
|
+
: render(response.json, {
|
|
145
|
+
styled: deps.styled,
|
|
146
|
+
full: !deps.stdoutIsTTY,
|
|
147
|
+
})
|
|
148
|
+
}\n`,
|
|
142
149
|
);
|
|
143
150
|
return 0;
|
|
144
151
|
}
|
|
@@ -147,7 +154,7 @@ async function runCommand(
|
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
const DESCRIPTION =
|
|
150
|
-
"The Asteroid CLI. Sign in with `asteroid login`, or set ASTEROID_API_KEY.";
|
|
157
|
+
"The Asteroid CLI. Sign in with `asteroid login`, or set ASTEROID_API_KEY.\nAt a terminal, tables show up to 6 columns and cut long cells to fit; when output is piped, they show every column in full. Use `--json` for every field.";
|
|
151
158
|
|
|
152
159
|
export async function run(argv: string[], deps: Deps): Promise<number> {
|
|
153
160
|
try {
|