@corelayer-ai/cli 0.1.0 → 0.2.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/install-skill.js +45 -0
- package/dist/index.js +9 -0
- package/dist/lib/auth.js +7 -1
- package/dist/lib/cli-auth.js +31 -0
- package/dist/lib/config.js +1 -0
- package/package.json +3 -2
- package/skill/SKILL.md +150 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, copyFileSync, unlinkSync, rmdirSync, } from "node:fs";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { fail } from "../lib/output.js";
|
|
6
|
+
const SKILL_NAME = "corelayer";
|
|
7
|
+
function getSkillTargetDir() {
|
|
8
|
+
return join(homedir(), ".claude", "skills", SKILL_NAME);
|
|
9
|
+
}
|
|
10
|
+
function getSkillSourcePath() {
|
|
11
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
12
|
+
const distDir = dirname(dirname(thisFile));
|
|
13
|
+
const packageDir = dirname(distDir);
|
|
14
|
+
return join(packageDir, "skill", "SKILL.md");
|
|
15
|
+
}
|
|
16
|
+
export async function runInstallSkill(_args, ctx) {
|
|
17
|
+
const source = getSkillSourcePath();
|
|
18
|
+
if (!existsSync(source)) {
|
|
19
|
+
fail("Skill file not found. The CLI package may be incomplete.");
|
|
20
|
+
}
|
|
21
|
+
const targetDir = getSkillTargetDir();
|
|
22
|
+
const targetFile = join(targetDir, "SKILL.md");
|
|
23
|
+
mkdirSync(targetDir, { recursive: true });
|
|
24
|
+
copyFileSync(source, targetFile);
|
|
25
|
+
if (!ctx.quiet) {
|
|
26
|
+
process.stdout.write(`Corelayer skill installed to ${targetFile}\nClaude Code will now automatically use the Corelayer CLI for production tasks.\n`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export async function runUninstallSkill(_args, ctx) {
|
|
30
|
+
const targetDir = getSkillTargetDir();
|
|
31
|
+
const targetFile = join(targetDir, "SKILL.md");
|
|
32
|
+
if (!existsSync(targetFile)) {
|
|
33
|
+
fail("Corelayer skill is not installed.");
|
|
34
|
+
}
|
|
35
|
+
unlinkSync(targetFile);
|
|
36
|
+
try {
|
|
37
|
+
rmdirSync(targetDir);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// directory not empty or already removed
|
|
41
|
+
}
|
|
42
|
+
if (!ctx.quiet) {
|
|
43
|
+
process.stdout.write("Corelayer skill uninstalled.\n");
|
|
44
|
+
}
|
|
45
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { runConfig } from "./commands/config.js";
|
|
|
4
4
|
import { runGroups } from "./commands/groups.js";
|
|
5
5
|
import { runIntegrations } from "./commands/integrations.js";
|
|
6
6
|
import { runIssues } from "./commands/issues.js";
|
|
7
|
+
import { runInstallSkill, runUninstallSkill, } from "./commands/install-skill.js";
|
|
7
8
|
import { runLogin } from "./commands/login.js";
|
|
8
9
|
import { runLogout } from "./commands/logout.js";
|
|
9
10
|
const require = createRequire(import.meta.url);
|
|
@@ -19,6 +20,8 @@ Usage:
|
|
|
19
20
|
corelayer groups list
|
|
20
21
|
corelayer integrations list [--group <groupId>]
|
|
21
22
|
corelayer config <get|set> ...
|
|
23
|
+
corelayer install-skill (install Claude Code skill)
|
|
24
|
+
corelayer uninstall-skill (remove Claude Code skill)
|
|
22
25
|
|
|
23
26
|
Global flags:
|
|
24
27
|
--json
|
|
@@ -102,6 +105,12 @@ async function main() {
|
|
|
102
105
|
case "config":
|
|
103
106
|
await runConfig(rest, ctx);
|
|
104
107
|
return;
|
|
108
|
+
case "install-skill":
|
|
109
|
+
await runInstallSkill(rest, ctx);
|
|
110
|
+
return;
|
|
111
|
+
case "uninstall-skill":
|
|
112
|
+
await runUninstallSkill(rest, ctx);
|
|
113
|
+
return;
|
|
105
114
|
default:
|
|
106
115
|
process.stderr.write(`Unknown command: ${command}\n`);
|
|
107
116
|
printHelp();
|
package/dist/lib/auth.js
CHANGED
|
@@ -151,7 +151,13 @@ export async function loginWithBrowser() {
|
|
|
151
151
|
return result;
|
|
152
152
|
}
|
|
153
153
|
function validateServerUrl(url) {
|
|
154
|
-
|
|
154
|
+
let parsed;
|
|
155
|
+
try {
|
|
156
|
+
parsed = new URL(url);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
throw new Error("Invalid server URL. Use a full URL such as https://app.corelayer.com or http://localhost:3000.");
|
|
160
|
+
}
|
|
155
161
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
156
162
|
throw new Error(`Unsupported protocol "${parsed.protocol}" — only http: and https: are allowed.`);
|
|
157
163
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
const MAX_CALLBACK_BODY_BYTES = 8 * 1024;
|
|
3
|
+
export function parseTrustedOrigin(authBaseUrl) {
|
|
4
|
+
const parsed = new URL(authBaseUrl);
|
|
5
|
+
return parsed.origin;
|
|
6
|
+
}
|
|
7
|
+
export function hashCliAuthCode(code) {
|
|
8
|
+
return crypto.createHash("sha256").update(code).digest("hex");
|
|
9
|
+
}
|
|
10
|
+
export async function readJsonBody(req) {
|
|
11
|
+
const chunks = [];
|
|
12
|
+
let total = 0;
|
|
13
|
+
for await (const chunk of req) {
|
|
14
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
15
|
+
total += buffer.length;
|
|
16
|
+
if (total > MAX_CALLBACK_BODY_BYTES) {
|
|
17
|
+
throw new Error("Callback body is too large");
|
|
18
|
+
}
|
|
19
|
+
chunks.push(buffer);
|
|
20
|
+
}
|
|
21
|
+
const raw = Buffer.concat(chunks).toString("utf8").trim();
|
|
22
|
+
if (!raw) {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(raw);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
throw new Error("Callback body is not valid JSON");
|
|
30
|
+
}
|
|
31
|
+
}
|
package/dist/lib/config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@corelayer-ai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Corelayer CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"corelayer": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"skill"
|
|
11
12
|
],
|
|
12
13
|
"engines": {
|
|
13
14
|
"node": ">=18.0.0"
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: corelayer
|
|
3
|
+
description: >
|
|
4
|
+
Use when the user mentions production issues, errors, monitoring, incidents,
|
|
5
|
+
error analysis, root cause analysis, issue triage, Corelayer, or wants to
|
|
6
|
+
check/manage/close/reopen production issues. Also use when the user says
|
|
7
|
+
"check prod", "what's broken", "any errors", "issue summary", or references
|
|
8
|
+
the corelayer CLI.
|
|
9
|
+
user-invocable: true
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Corelayer CLI
|
|
13
|
+
|
|
14
|
+
Corelayer is an AI-powered error analysis and monitoring platform. The `corelayer` CLI lets you manage production issues, view root cause analyses, and triage errors directly from the terminal.
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
The CLI must be installed and authenticated. Config lives at `~/.corelayer/config.json`.
|
|
19
|
+
|
|
20
|
+
If not logged in, run:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
corelayer login
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick reference
|
|
27
|
+
|
|
28
|
+
### Check production health
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
corelayer issues summary --group <groupId>
|
|
32
|
+
corelayer issues list --group <groupId>
|
|
33
|
+
corelayer issues list --severity critical
|
|
34
|
+
corelayer issues list --status open
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Inspect a specific issue
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
corelayer issues get <issueId>
|
|
41
|
+
corelayer issues get <issueId> --json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Returns: title, status, severity, event count, what happened, root cause, and next steps.
|
|
45
|
+
|
|
46
|
+
### Triage issues
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
corelayer issues close <issueId> --feedback "Fixed in PR #123"
|
|
50
|
+
corelayer issues reopen <issueId>
|
|
51
|
+
corelayer issues delete <issueId> --yes
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### List groups and integrations
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
corelayer groups list
|
|
58
|
+
corelayer integrations list --group <groupId>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Configuration
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
corelayer config set default-group <groupId>
|
|
65
|
+
corelayer config get
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Setting a default group avoids repeating `--group` on every command.
|
|
69
|
+
|
|
70
|
+
## Global flags
|
|
71
|
+
|
|
72
|
+
| Flag | Purpose |
|
|
73
|
+
| ----------------- | -------------------------------------------------- |
|
|
74
|
+
| `--json` | Output as JSON (useful for piping/parsing) |
|
|
75
|
+
| `--quiet` / `-q` | Suppress non-error output |
|
|
76
|
+
| `--no-color` | Disable colored output |
|
|
77
|
+
| `--api-url <url>` | Override the configured API server for one command |
|
|
78
|
+
|
|
79
|
+
## Command reference
|
|
80
|
+
|
|
81
|
+
### `corelayer issues list [--group <id>] [--status <s>] [--severity <s>] [--limit <n>] [--page <n>]`
|
|
82
|
+
|
|
83
|
+
List issues for a group. Requires `--group` or a configured default group.
|
|
84
|
+
Filterable by status (`open`, `closed`) and severity (`critical`, `high`, `medium`, `low`).
|
|
85
|
+
|
|
86
|
+
### `corelayer issues get <issueId>`
|
|
87
|
+
|
|
88
|
+
Get full details for an issue including AI-generated analysis: what happened, root cause, and next steps.
|
|
89
|
+
|
|
90
|
+
### `corelayer issues summary [--group <id>]`
|
|
91
|
+
|
|
92
|
+
Returns a JSON severity breakdown for the group.
|
|
93
|
+
|
|
94
|
+
### `corelayer issues close <issueId> [--feedback "..."]`
|
|
95
|
+
|
|
96
|
+
Close an issue. Optionally provide feedback (e.g., link to the fix).
|
|
97
|
+
|
|
98
|
+
### `corelayer issues reopen <issueId>`
|
|
99
|
+
|
|
100
|
+
Reopen a previously closed issue.
|
|
101
|
+
|
|
102
|
+
### `corelayer issues delete <issueId> [--yes]`
|
|
103
|
+
|
|
104
|
+
Soft-delete an issue. Prompts for confirmation unless `--yes` is passed.
|
|
105
|
+
|
|
106
|
+
### `corelayer groups list`
|
|
107
|
+
|
|
108
|
+
List all groups in the organization.
|
|
109
|
+
|
|
110
|
+
### `corelayer integrations list [--group <id>]`
|
|
111
|
+
|
|
112
|
+
List connected integration accounts and their resource counts.
|
|
113
|
+
|
|
114
|
+
### `corelayer config get [key]`
|
|
115
|
+
|
|
116
|
+
Get config values. Keys: `api-url`, `default-group`. No key returns the full config.
|
|
117
|
+
|
|
118
|
+
### `corelayer config set <key> <value>`
|
|
119
|
+
|
|
120
|
+
Set config values. Keys: `api-url`, `default-group`.
|
|
121
|
+
|
|
122
|
+
### `corelayer login`
|
|
123
|
+
|
|
124
|
+
Authenticate via browser. Or use `corelayer login --code <CODE> --api-url <url>` for manual auth.
|
|
125
|
+
|
|
126
|
+
### `corelayer logout`
|
|
127
|
+
|
|
128
|
+
Clear stored credentials.
|
|
129
|
+
|
|
130
|
+
## Workflows
|
|
131
|
+
|
|
132
|
+
### "What's happening in production?"
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
corelayer issues summary
|
|
136
|
+
corelayer issues list --severity critical
|
|
137
|
+
corelayer issues get <id> --json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Scripting and automation
|
|
141
|
+
|
|
142
|
+
Use `--json` and `--quiet` flags for machine-readable output:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
corelayer issues list --json --group <id> | jq '.issues[] | select(.severity == "critical")'
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Background agent usage
|
|
149
|
+
|
|
150
|
+
When running as a background agent, always use `--json` for structured output and `--quiet` to suppress interactive messages. Set `default-group` in config so group IDs don't need to be passed every time.
|