@root-signals/scorable-cli 0.4.0 → 0.5.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/README.md CHANGED
@@ -24,6 +24,10 @@
24
24
  </a>
25
25
  </p>
26
26
 
27
+ <p align="center">
28
+ <video src="https://github.com/user-attachments/assets/3475573e-b20c-405b-acc6-ee48709998fa" width="800" autoplay loop muted></video>
29
+ </p>
30
+
27
31
  The `scorable` CLI is a command-line tool for interacting with the Scorable API. It lets you manage and execute Judges and Evaluators, view execution logs, and run prompt testing experiments directly from the terminal.
28
32
 
29
33
  Requires **Node.js 20 or higher**.
@@ -74,6 +78,18 @@ export SCORABLE_API_KEY="sk-your-api-key"
74
78
 
75
79
  The key lookup order is: `SCORABLE_API_KEY` env var → `api_key` in `~/.scorable/settings.json` → `temporary_api_key` in `~/.scorable/settings.json`.
76
80
 
81
+ ## Scorable Skills for AI Coding Agents
82
+
83
+ Install Scorable skills into your project so your AI coding agent (Claude Code, Cursor, etc.) can integrate evaluators automatically:
84
+
85
+ ```bash
86
+ scorable skills-add
87
+ ```
88
+
89
+ Once installed, open your coding agent in your AI powered project and use the prompt:
90
+
91
+ > "Integrate scorable evaluators"
92
+
77
93
  ## Judge Management
78
94
 
79
95
  ### List judges
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerExportYamlCommand(evaluator: Command): void;
3
+ //# sourceMappingURL=export-yaml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-yaml.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/export-yaml.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAwBlE"}
@@ -0,0 +1,31 @@
1
+ import { writeFileSync } from "node:fs";
2
+ import ora from "ora";
3
+ import { requireApiKey, getSdkClient } from "../../auth.js";
4
+ import { printSuccess, handleSdkError } from "../../output.js";
5
+ export function registerExportYamlCommand(evaluator) {
6
+ evaluator
7
+ .command("export-yaml")
8
+ .description("Export an evaluator as a YAML file")
9
+ .argument("<id>", "Evaluator ID")
10
+ .option("--output <file>", "Write YAML to this file instead of stdout")
11
+ .action(async (id, opts) => {
12
+ const spinner = ora("Exporting…").start();
13
+ try {
14
+ const apiKey = await requireApiKey();
15
+ const client = getSdkClient(apiKey);
16
+ const yaml = await client.evaluators.exportYaml(id);
17
+ spinner.stop();
18
+ if (opts.output) {
19
+ writeFileSync(opts.output, yaml, "utf8");
20
+ printSuccess(`Evaluator exported to ${opts.output}`);
21
+ }
22
+ else {
23
+ process.stdout.write(yaml);
24
+ }
25
+ }
26
+ catch (e) {
27
+ spinner.stop();
28
+ handleSdkError(e);
29
+ }
30
+ });
31
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerImportYamlCommand(evaluator: Command): void;
3
+ //# sourceMappingURL=import-yaml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-yaml.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/import-yaml.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CA2ClE"}
@@ -0,0 +1,49 @@
1
+ import { readFileSync } from "node:fs";
2
+ import ora from "ora";
3
+ import { requireApiKey, getBaseUrl } from "../../auth.js";
4
+ import { printSuccess, printError, printJson, handleSdkError } from "../../output.js";
5
+ export function registerImportYamlCommand(evaluator) {
6
+ evaluator
7
+ .command("import-yaml")
8
+ .description("Import an evaluator from a YAML file")
9
+ .requiredOption("--file <path>", "Path to the YAML file to import")
10
+ .option("--overwrite", "Overwrite if an evaluator with the same name already exists")
11
+ .action(async (opts) => {
12
+ let yamlContent;
13
+ try {
14
+ yamlContent = readFileSync(opts.file, "utf8");
15
+ }
16
+ catch {
17
+ printError(`Could not read file: ${opts.file}`);
18
+ return;
19
+ }
20
+ const spinner = ora("Importing…").start();
21
+ try {
22
+ const apiKey = await requireApiKey();
23
+ const baseUrl = getBaseUrl();
24
+ const response = await fetch(`${baseUrl}/v1/evaluators/import-yaml/`, {
25
+ method: "POST",
26
+ headers: {
27
+ Authorization: `Api-Key ${apiKey}`,
28
+ "Content-Type": "application/json",
29
+ },
30
+ body: JSON.stringify({ yaml: yamlContent, overwrite: opts.overwrite ?? false }),
31
+ });
32
+ if (!response.ok) {
33
+ spinner.stop();
34
+ const text = await response.text();
35
+ printError(`Import failed (${response.status}): ${text}`);
36
+ return;
37
+ }
38
+ const result = (await response.json());
39
+ spinner.stop();
40
+ const name = typeof result["name"] === "string" ? result["name"] : "evaluator";
41
+ printSuccess(`Evaluator "${name}" imported successfully!`);
42
+ printJson(result);
43
+ }
44
+ catch (e) {
45
+ spinner.stop();
46
+ handleSdkError(e);
47
+ }
48
+ });
49
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAahE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAehE"}
@@ -7,6 +7,8 @@ import { registerDeleteCommand } from "./delete.js";
7
7
  import { registerExecuteCommand } from "./execute.js";
8
8
  import { registerExecuteByNameCommand } from "./execute-by-name.js";
9
9
  import { registerDuplicateCommand } from "./duplicate.js";
10
+ import { registerExportYamlCommand } from "./export-yaml.js";
11
+ import { registerImportYamlCommand } from "./import-yaml.js";
10
12
  export function registerEvaluatorCommands(program) {
11
13
  const evaluator = new Command("evaluator").description("Evaluator management commands");
12
14
  registerListCommand(evaluator);
@@ -17,5 +19,7 @@ export function registerEvaluatorCommands(program) {
17
19
  registerExecuteCommand(evaluator);
18
20
  registerExecuteByNameCommand(evaluator);
19
21
  registerDuplicateCommand(evaluator);
22
+ registerExportYamlCommand(evaluator);
23
+ registerImportYamlCommand(evaluator);
20
24
  program.addCommand(evaluator);
21
25
  }
@@ -8,6 +8,6 @@ function buildPtGroup(name) {
8
8
  return pt;
9
9
  }
10
10
  export function registerPromptTestCommands(program) {
11
- program.addCommand(buildPtGroup("pt"));
11
+ program.addCommand(buildPtGroup("pt"), { hidden: true });
12
12
  program.addCommand(buildPtGroup("prompt-test"));
13
13
  }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerSkillsAddCommand(program: Command): void;
3
+ //# sourceMappingURL=skills-add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills-add.d.ts","sourceRoot":"","sources":["../../src/commands/skills-add.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0B/D"}
@@ -0,0 +1,29 @@
1
+ import { spawn } from "node:child_process";
2
+ import { CliError } from "../types.js";
3
+ import { printSuccess, printInfo } from "../output.js";
4
+ export function registerSkillsAddCommand(program) {
5
+ program
6
+ .command("skills-add")
7
+ .description("Install Scorable Skills for coding agents")
8
+ .action(async () => {
9
+ await new Promise((resolve, reject) => {
10
+ const child = spawn("npx", ["skills", "add", "root-signals/scorable-skills"], {
11
+ stdio: "inherit",
12
+ });
13
+ child.on("close", (code) => {
14
+ if (code !== 0) {
15
+ reject(new CliError(code ?? 1, `skills add exited with code ${code}`));
16
+ }
17
+ else {
18
+ resolve();
19
+ }
20
+ });
21
+ child.on("error", (err) => {
22
+ reject(new CliError(1, `Failed to run npx skills: ${err.message}`));
23
+ });
24
+ });
25
+ console.log();
26
+ printSuccess("Scorable skills installed.");
27
+ printInfo('Open your coding agent in your AI powered project and use the prompt: "Integrate scorable evaluators"');
28
+ });
29
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6CpC,wBAAgB,SAAS,IAAI,OAAO,CAmBnC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgDpC,wBAAgB,SAAS,IAAI,OAAO,CAoBnC"}
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import { registerPromptTestCommands } from "./commands/prompt-test/index.js";
9
9
  import { registerEvaluatorCommands } from "./commands/evaluator/index.js";
10
10
  import { registerExecutionLogCommands } from "./commands/execution-log/index.js";
11
11
  import { registerAuthCommands } from "./commands/auth/index.js";
12
+ import { registerSkillsAddCommand } from "./commands/skills-add.js";
12
13
  const { version } = createRequire(import.meta.url)("../package.json");
13
14
  function buildBanner(ver) {
14
15
  const logo = chalk.hex("#4D9FFF");
@@ -35,7 +36,9 @@ function buildGettingStarted() {
35
36
  ` ${num("1")} Authenticate ${chalk.dim("(pick one)")}:`,
36
37
  ` ${cmd("$ scorable auth demo-key")} ${chalk.dim("# for quick testing")}`,
37
38
  ` ${cmd("$ scorable auth set-key <api-key>")} ${chalk.dim("# permanent key")}`,
38
- ` ${num("2")} Explore resources:`,
39
+ ` ${num("2")} Install skills for your AI coding agent:`,
40
+ ` ${cmd("$ scorable skills-add")}`,
41
+ ` ${num("3")} Explore resources:`,
39
42
  ` ${cmd("$ scorable judge list")}`,
40
43
  ` ${cmd("$ scorable evaluator list")}`,
41
44
  "",
@@ -57,6 +60,7 @@ export function createCli() {
57
60
  registerEvaluatorCommands(program);
58
61
  registerExecutionLogCommands(program);
59
62
  registerAuthCommands(program);
63
+ registerSkillsAddCommand(program);
60
64
  return program;
61
65
  }
62
66
  if (realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@root-signals/scorable-cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "CLI for Scorable",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Scorable",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@inquirer/prompts": "^8.3.2",
34
- "@root-signals/scorable": "^0.3.1",
34
+ "@root-signals/scorable": "^0.4.0",
35
35
  "chalk": "^5.6.2",
36
36
  "cli-table3": "^0.6.5",
37
37
  "commander": "^14.0.3",