@corelayer-ai/cli 0.3.0 → 0.4.0
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/commands/config.js +28 -0
- package/dist/commands/groups.js +22 -0
- package/dist/commands/install-skill.js +36 -2
- package/dist/commands/integrations.js +23 -0
- package/dist/commands/issues.js +79 -2
- package/dist/commands/login.js +24 -0
- package/dist/commands/logout.js +15 -1
- package/dist/index.js +25 -27
- package/dist/lib/api-client.js +23 -2
- package/package.json +1 -1
- package/skill/SKILL.md +5 -0
package/dist/commands/config.js
CHANGED
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
import { readConfig, updateConfig } from "../lib/config.js";
|
|
2
2
|
import { fail, printJson } from "../lib/output.js";
|
|
3
|
+
function printHelp() {
|
|
4
|
+
process.stdout.write(`corelayer config - Read and write local CLI config
|
|
5
|
+
|
|
6
|
+
USAGE:
|
|
7
|
+
corelayer config <subcommand> [key] [value]
|
|
8
|
+
|
|
9
|
+
SUBCOMMANDS:
|
|
10
|
+
get [key] Print the full config, or one value
|
|
11
|
+
set <key> <value> Set a config value
|
|
12
|
+
|
|
13
|
+
KEYS:
|
|
14
|
+
api-url API server URL
|
|
15
|
+
default-group Default group ID for issues and integrations commands
|
|
16
|
+
|
|
17
|
+
OPTIONS:
|
|
18
|
+
--json Output as JSON (get only)
|
|
19
|
+
-h, --help Print help
|
|
20
|
+
|
|
21
|
+
EXAMPLES:
|
|
22
|
+
corelayer config get
|
|
23
|
+
corelayer config get api-url
|
|
24
|
+
corelayer config set default-group g_123
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
3
27
|
export async function runConfig(args, ctx) {
|
|
28
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
29
|
+
printHelp();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
4
32
|
const sub = args[0];
|
|
5
33
|
if (sub === "get") {
|
|
6
34
|
const key = args[1];
|
package/dist/commands/groups.js
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
import { CorelayerClient } from "../lib/api-client.js";
|
|
2
2
|
import { resolveToken, resolveApiUrl } from "../lib/config.js";
|
|
3
3
|
import { fail, formatDate, printJson, printTable } from "../lib/output.js";
|
|
4
|
+
function printHelp() {
|
|
5
|
+
process.stdout.write(`corelayer groups - List and inspect groups
|
|
6
|
+
|
|
7
|
+
USAGE:
|
|
8
|
+
corelayer groups <subcommand> [options]
|
|
9
|
+
|
|
10
|
+
SUBCOMMANDS:
|
|
11
|
+
list List all groups you have access to
|
|
12
|
+
|
|
13
|
+
OPTIONS:
|
|
14
|
+
--json Output as JSON
|
|
15
|
+
-h, --help Print help
|
|
16
|
+
|
|
17
|
+
EXAMPLES:
|
|
18
|
+
corelayer groups list
|
|
19
|
+
corelayer groups list --json
|
|
20
|
+
`);
|
|
21
|
+
}
|
|
4
22
|
export async function runGroups(args, ctx) {
|
|
23
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
24
|
+
printHelp();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
5
27
|
const sub = args[0];
|
|
6
28
|
if (sub !== "list") {
|
|
7
29
|
fail("Usage: corelayer groups list");
|
|
@@ -13,7 +13,37 @@ function getSkillSourcePath() {
|
|
|
13
13
|
const packageDir = dirname(distDir);
|
|
14
14
|
return join(packageDir, "skill", "SKILL.md");
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
function printInstallHelp() {
|
|
17
|
+
process.stdout
|
|
18
|
+
.write(`corelayer install-skill - Install the Corelayer agent skill
|
|
19
|
+
|
|
20
|
+
USAGE:
|
|
21
|
+
corelayer install-skill
|
|
22
|
+
|
|
23
|
+
DESCRIPTION:
|
|
24
|
+
Copies the Corelayer skill into ~/.claude/skills/corelayer so coding agents
|
|
25
|
+
can use it. Run 'corelayer uninstall-skill' to remove it.
|
|
26
|
+
|
|
27
|
+
OPTIONS:
|
|
28
|
+
-h, --help Print help
|
|
29
|
+
`);
|
|
30
|
+
}
|
|
31
|
+
function printUninstallHelp() {
|
|
32
|
+
process.stdout
|
|
33
|
+
.write(`corelayer uninstall-skill - Remove the Corelayer agent skill
|
|
34
|
+
|
|
35
|
+
USAGE:
|
|
36
|
+
corelayer uninstall-skill
|
|
37
|
+
|
|
38
|
+
OPTIONS:
|
|
39
|
+
-h, --help Print help
|
|
40
|
+
`);
|
|
41
|
+
}
|
|
42
|
+
export async function runInstallSkill(args, ctx) {
|
|
43
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
44
|
+
printInstallHelp();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
17
47
|
const source = getSkillSourcePath();
|
|
18
48
|
if (!existsSync(source)) {
|
|
19
49
|
fail("Skill file not found. The CLI package may be incomplete.");
|
|
@@ -26,7 +56,11 @@ export async function runInstallSkill(_args, ctx) {
|
|
|
26
56
|
process.stdout.write(`Corelayer skill installed to ${targetFile}\n`);
|
|
27
57
|
}
|
|
28
58
|
}
|
|
29
|
-
export async function runUninstallSkill(
|
|
59
|
+
export async function runUninstallSkill(args, ctx) {
|
|
60
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
61
|
+
printUninstallHelp();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
30
64
|
const targetDir = getSkillTargetDir();
|
|
31
65
|
const targetFile = join(targetDir, "SKILL.md");
|
|
32
66
|
if (!existsSync(targetFile)) {
|
|
@@ -7,7 +7,30 @@ function readFlag(args, flag) {
|
|
|
7
7
|
return undefined;
|
|
8
8
|
return args[index + 1];
|
|
9
9
|
}
|
|
10
|
+
function printHelp() {
|
|
11
|
+
process.stdout.write(`corelayer integrations - List integrations for a group
|
|
12
|
+
|
|
13
|
+
USAGE:
|
|
14
|
+
corelayer integrations <subcommand> [options]
|
|
15
|
+
|
|
16
|
+
SUBCOMMANDS:
|
|
17
|
+
list List integrations for a group
|
|
18
|
+
|
|
19
|
+
OPTIONS:
|
|
20
|
+
--group <id> Group ID (or set default-group via 'corelayer config set')
|
|
21
|
+
--json Output as JSON
|
|
22
|
+
-h, --help Print help
|
|
23
|
+
|
|
24
|
+
EXAMPLES:
|
|
25
|
+
corelayer integrations list --group g_123
|
|
26
|
+
corelayer integrations list --json
|
|
27
|
+
`);
|
|
28
|
+
}
|
|
10
29
|
export async function runIntegrations(args, ctx) {
|
|
30
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
31
|
+
printHelp();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
11
34
|
const sub = args[0];
|
|
12
35
|
if (sub !== "list") {
|
|
13
36
|
fail("Usage: corelayer integrations list [--group <groupId>]");
|
package/dist/commands/issues.js
CHANGED
|
@@ -25,7 +25,9 @@ function removeFlags(args) {
|
|
|
25
25
|
arg === "--severity" ||
|
|
26
26
|
arg === "--limit" ||
|
|
27
27
|
arg === "--page" ||
|
|
28
|
-
arg === "--feedback"
|
|
28
|
+
arg === "--feedback" ||
|
|
29
|
+
arg === "--last-seen-before" ||
|
|
30
|
+
arg === "--last-seen-before-or-on") {
|
|
29
31
|
skipNext = true;
|
|
30
32
|
continue;
|
|
31
33
|
}
|
|
@@ -45,7 +47,49 @@ async function confirmDelete() {
|
|
|
45
47
|
rl.close();
|
|
46
48
|
return answer.trim().toLowerCase() === "y";
|
|
47
49
|
}
|
|
50
|
+
function printHelp() {
|
|
51
|
+
process.stdout.write(`corelayer issues - List, inspect, and manage issues
|
|
52
|
+
|
|
53
|
+
USAGE:
|
|
54
|
+
corelayer issues <subcommand> [options]
|
|
55
|
+
|
|
56
|
+
SUBCOMMANDS:
|
|
57
|
+
list List issues in a group
|
|
58
|
+
get <id> Show details for one issue
|
|
59
|
+
summary Summarize issue health for a group
|
|
60
|
+
close <id> Close an issue (write operation)
|
|
61
|
+
bulk-close Close many issues in one request (write operation)
|
|
62
|
+
reopen <id> Reopen a closed issue (write operation)
|
|
63
|
+
delete <id> Delete an issue (write operation)
|
|
64
|
+
|
|
65
|
+
OPTIONS:
|
|
66
|
+
--group <id> Group ID (or set default-group via 'corelayer config set')
|
|
67
|
+
--status <status> Filter by status (list)
|
|
68
|
+
--severity <sev> Filter by severity (list)
|
|
69
|
+
--limit <n> Limit results (list)
|
|
70
|
+
--page <n> Page number (list)
|
|
71
|
+
--feedback <text> Feedback message (close)
|
|
72
|
+
--last-seen-before <date|preset>
|
|
73
|
+
Filter bulk-close to issues seen before a cutoff
|
|
74
|
+
--last-seen-before-or-on <date|preset>
|
|
75
|
+
Filter bulk-close to issues seen on or before a cutoff
|
|
76
|
+
--yes Skip confirmation prompt (delete)
|
|
77
|
+
--json Output as JSON
|
|
78
|
+
-h, --help Print help
|
|
79
|
+
|
|
80
|
+
EXAMPLES:
|
|
81
|
+
corelayer issues list --group g_123 --status Open
|
|
82
|
+
corelayer issues get i_456 --json
|
|
83
|
+
corelayer issues close i_456 --feedback "fixed in deploy 2026-04-07"
|
|
84
|
+
corelayer issues bulk-close --group g_123 --last-seen-before-or-on 14days --feedback "Not seen in two weeks"
|
|
85
|
+
corelayer issues delete i_456 --yes
|
|
86
|
+
`);
|
|
87
|
+
}
|
|
48
88
|
export async function runIssues(args, ctx) {
|
|
89
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
90
|
+
printHelp();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
49
93
|
const sub = args[0];
|
|
50
94
|
const config = readConfig();
|
|
51
95
|
const token = resolveToken();
|
|
@@ -123,6 +167,39 @@ export async function runIssues(args, ctx) {
|
|
|
123
167
|
}
|
|
124
168
|
return;
|
|
125
169
|
}
|
|
170
|
+
if (sub === "bulk-close") {
|
|
171
|
+
const groupId = readFlag(args, "--group") || config.defaults?.group;
|
|
172
|
+
if (!groupId) {
|
|
173
|
+
fail("groupId is required. Use --group <groupId> or set default-group via corelayer config set default-group <groupId>");
|
|
174
|
+
}
|
|
175
|
+
const lastSeenBefore = readFlag(args, "--last-seen-before");
|
|
176
|
+
const lastSeenBeforeOrOn = readFlag(args, "--last-seen-before-or-on");
|
|
177
|
+
if (!lastSeenBefore && !lastSeenBeforeOrOn) {
|
|
178
|
+
fail('Usage: corelayer issues bulk-close --group <groupId> (--last-seen-before <date|preset> | --last-seen-before-or-on <date|preset>) [--feedback "..."]');
|
|
179
|
+
}
|
|
180
|
+
const feedback = readFlag(args, "--feedback");
|
|
181
|
+
const result = await client.bulkIssueAction({
|
|
182
|
+
action: "close",
|
|
183
|
+
groupId,
|
|
184
|
+
feedback,
|
|
185
|
+
filters: {
|
|
186
|
+
status: readFlag(args, "--status") || "Open",
|
|
187
|
+
severity: readFlag(args, "--severity"),
|
|
188
|
+
lastSeenBefore,
|
|
189
|
+
lastSeenBeforeOrOn,
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
if (ctx.json) {
|
|
193
|
+
printJson(result);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
process.stdout.write(`Bulk close complete. Closed ${result.affected} issues`);
|
|
197
|
+
if (result.skipped > 0) {
|
|
198
|
+
process.stdout.write(`, skipped ${result.skipped}`);
|
|
199
|
+
}
|
|
200
|
+
process.stdout.write(".\n");
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
126
203
|
if (sub === "reopen") {
|
|
127
204
|
const issueId = commandArgs[0];
|
|
128
205
|
if (!issueId) {
|
|
@@ -162,5 +239,5 @@ export async function runIssues(args, ctx) {
|
|
|
162
239
|
printJson(summary);
|
|
163
240
|
return;
|
|
164
241
|
}
|
|
165
|
-
fail("Usage: corelayer issues <list|get|close|reopen|delete|summary> [options]");
|
|
242
|
+
fail("Usage: corelayer issues <list|get|close|bulk-close|reopen|delete|summary> [options]");
|
|
166
243
|
}
|
package/dist/commands/login.js
CHANGED
|
@@ -10,6 +10,26 @@ function readFlag(args, flag) {
|
|
|
10
10
|
function hasFlag(args, flag) {
|
|
11
11
|
return args.includes(flag);
|
|
12
12
|
}
|
|
13
|
+
function printHelp() {
|
|
14
|
+
process.stdout.write(`corelayer login - Authenticate with Corelayer
|
|
15
|
+
|
|
16
|
+
USAGE:
|
|
17
|
+
corelayer login Open browser to authenticate
|
|
18
|
+
corelayer login --code <code> --api-url <url> Complete login with an auth code
|
|
19
|
+
corelayer login --with-token --api-url <url> Save a token piped on stdin
|
|
20
|
+
|
|
21
|
+
OPTIONS:
|
|
22
|
+
--code <code> Auth code from the browser flow (manual login)
|
|
23
|
+
--with-token Read an API key from stdin and save it to config
|
|
24
|
+
--api-url <url> API server URL (required for --code and --with-token)
|
|
25
|
+
-h, --help Print help
|
|
26
|
+
|
|
27
|
+
EXAMPLES:
|
|
28
|
+
corelayer login
|
|
29
|
+
corelayer login --code abc123 --api-url https://api.corelayer.com
|
|
30
|
+
echo $CORELAYER_API_KEY | corelayer login --with-token --api-url https://api.corelayer.com
|
|
31
|
+
`);
|
|
32
|
+
}
|
|
13
33
|
async function readStdin() {
|
|
14
34
|
if (process.stdin.isTTY) {
|
|
15
35
|
fail("No token provided on stdin. Usage: echo $CORELAYER_API_KEY | corelayer login --with-token");
|
|
@@ -21,6 +41,10 @@ async function readStdin() {
|
|
|
21
41
|
return Buffer.concat(chunks).toString("utf8").trim();
|
|
22
42
|
}
|
|
23
43
|
export async function runLogin(args, ctx) {
|
|
44
|
+
if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
|
|
45
|
+
printHelp();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
24
48
|
const code = readFlag(args, "--code");
|
|
25
49
|
const withToken = hasFlag(args, "--with-token");
|
|
26
50
|
if (withToken) {
|
package/dist/commands/logout.js
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { clearToken } from "../lib/config.js";
|
|
2
|
-
|
|
2
|
+
function printHelp() {
|
|
3
|
+
process.stdout.write(`corelayer logout - Sign out and clear local credentials
|
|
4
|
+
|
|
5
|
+
USAGE:
|
|
6
|
+
corelayer logout
|
|
7
|
+
|
|
8
|
+
OPTIONS:
|
|
9
|
+
-h, --help Print help
|
|
10
|
+
`);
|
|
11
|
+
}
|
|
12
|
+
export async function runLogout(args, ctx) {
|
|
13
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
14
|
+
printHelp();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
3
17
|
clearToken();
|
|
4
18
|
if (!ctx.quiet) {
|
|
5
19
|
process.stdout.write("Logged out.\n");
|
package/dist/index.js
CHANGED
|
@@ -10,38 +10,36 @@ import { runLogout } from "./commands/logout.js";
|
|
|
10
10
|
const require = createRequire(import.meta.url);
|
|
11
11
|
const { version } = require("../package.json");
|
|
12
12
|
function printHelp() {
|
|
13
|
-
process.stdout
|
|
13
|
+
process.stdout
|
|
14
|
+
.write(`Corelayer CLI - Manage groups, issues, and integrations from your terminal
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
corelayer
|
|
17
|
-
corelayer login --code <CODE> --api-url <url> (manual)
|
|
18
|
-
corelayer login --with-token --api-url <url> (pipe token from stdin)
|
|
19
|
-
corelayer logout
|
|
20
|
-
corelayer issues <list|get|close|reopen|delete|summary> ...
|
|
21
|
-
corelayer groups list
|
|
22
|
-
corelayer integrations list [--group <groupId>]
|
|
23
|
-
corelayer config <get|set> ...
|
|
24
|
-
corelayer install-skill (install Corelayer skill)
|
|
25
|
-
corelayer uninstall-skill (remove Corelayer skill)
|
|
16
|
+
USAGE:
|
|
17
|
+
corelayer [global options] <command> [command options]
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
COMMANDS:
|
|
20
|
+
login Authenticate with Corelayer (opens browser)
|
|
21
|
+
logout Sign out and clear local credentials
|
|
22
|
+
groups List and inspect groups
|
|
23
|
+
issues List, inspect, and manage issues
|
|
24
|
+
integrations List integrations for a group
|
|
25
|
+
config Read and write local CLI config
|
|
26
|
+
install-skill Install the Corelayer agent skill
|
|
27
|
+
uninstall-skill Remove the Corelayer agent skill
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
GLOBAL OPTIONS:
|
|
30
|
+
--json Output as JSON for scripting
|
|
31
|
+
-q, --quiet Suppress non-essential output
|
|
32
|
+
--api-url <url> Override the configured API server
|
|
33
|
+
--no-color Disable colored output
|
|
34
|
+
-h, --help Print help
|
|
35
|
+
-v, --version Print version
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
ENVIRONMENT VARIABLES:
|
|
38
|
+
CORELAYER_API_KEY API key for non-interactive auth (skips login)
|
|
39
|
+
CORELAYER_API_URL Server URL (default: https://api.corelayer.com)
|
|
40
|
+
CORELAYER_AUTH_URL Auth server URL (default: https://app.corelayer.com)
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
echo $CORELAYER_API_KEY | corelayer login --with-token --api-url <url>
|
|
42
|
+
Run 'corelayer <command> --help' for more information on a command.
|
|
45
43
|
`);
|
|
46
44
|
}
|
|
47
45
|
function parseGlobalFlags(argv) {
|
package/dist/lib/api-client.js
CHANGED
|
@@ -6,9 +6,14 @@ async function parseError(res) {
|
|
|
6
6
|
catch {
|
|
7
7
|
body = null;
|
|
8
8
|
}
|
|
9
|
-
|
|
9
|
+
const message = body?.error ||
|
|
10
10
|
body?.message ||
|
|
11
|
-
`${res.status} ${res.statusText || "Request failed"}
|
|
11
|
+
`${res.status} ${res.statusText || "Request failed"}`;
|
|
12
|
+
const retryAfter = res.headers.get("retry-after");
|
|
13
|
+
if (res.status === 429 && retryAfter) {
|
|
14
|
+
return `${message}. Retry after ${retryAfter}s.`;
|
|
15
|
+
}
|
|
16
|
+
return message;
|
|
12
17
|
}
|
|
13
18
|
export class CorelayerClient {
|
|
14
19
|
baseUrl;
|
|
@@ -65,6 +70,22 @@ export class CorelayerClient {
|
|
|
65
70
|
feedback,
|
|
66
71
|
});
|
|
67
72
|
}
|
|
73
|
+
async bulkIssueAction(params) {
|
|
74
|
+
const filters = new URLSearchParams();
|
|
75
|
+
for (const [key, value] of Object.entries(params.filters || {})) {
|
|
76
|
+
if (value !== undefined && value !== null && value !== "") {
|
|
77
|
+
filters.set(key, String(value));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return this.request("POST", "/api/v1/issues/bulk", {
|
|
81
|
+
action: params.action,
|
|
82
|
+
groupId: params.groupId,
|
|
83
|
+
issueIds: params.issueIds,
|
|
84
|
+
selectAll: !params.issueIds || params.issueIds.length === 0,
|
|
85
|
+
filters: filters.toString() || undefined,
|
|
86
|
+
feedback: params.feedback,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
68
89
|
async reopenIssue(issueId) {
|
|
69
90
|
await this.request("PATCH", `/api/v1/issues/${issueId}`, {
|
|
70
91
|
status: "Open",
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -47,6 +47,7 @@ Returns: title, status, severity, event count, what happened, root cause, and ne
|
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
49
|
corelayer issues close <issueId> --feedback "Fixed in PR #123"
|
|
50
|
+
corelayer issues bulk-close --group <groupId> --last-seen-before-or-on 14days --feedback "Not seen in two weeks"
|
|
50
51
|
corelayer issues reopen <issueId>
|
|
51
52
|
corelayer issues delete <issueId> --yes
|
|
52
53
|
```
|
|
@@ -95,6 +96,10 @@ Returns a JSON severity breakdown for the group.
|
|
|
95
96
|
|
|
96
97
|
Close an issue. Optionally provide feedback (e.g., link to the fix).
|
|
97
98
|
|
|
99
|
+
### `corelayer issues bulk-close --group <id> (--last-seen-before <date|preset> | --last-seen-before-or-on <date|preset>) [--feedback "..."]`
|
|
100
|
+
|
|
101
|
+
Close many stale issues in one request. Presets such as `14days` are supported.
|
|
102
|
+
|
|
98
103
|
### `corelayer issues reopen <issueId>`
|
|
99
104
|
|
|
100
105
|
Reopen a previously closed issue.
|