@noir-ai/cli 1.9.3 → 1.9.4-beta.2
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 +1 -1
- package/dist/bin.js +107 -29
- package/dist/bin.js.map +1 -1
- package/dist/tui/index.js +107 -29
- package/dist/tui/index.js.map +1 -1
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ noir init # scaffolds .noir/ + host wiring + skills where suppo
|
|
|
30
30
|
# 2. Open the project in Claude Code (the v1 host) → it auto-spawns the Noir MCP server.
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
`noir init` defaults to Claude: it creates `.noir/` (project id, `config.yml`, `NOIR.md`, the SQLite store), root `.mcp.json`, a managed `CLAUDE.md` `@import` block, and the **
|
|
33
|
+
`noir init` defaults to Claude: it creates `.noir/` (project id, `config.yml`, `NOIR.md`, the SQLite store), root `.mcp.json`, a managed `CLAUDE.md` `@import` block, and the **27 native `noir-*` skills** (26 builtins + 1 integration) in `.claude/skills/`. Pass `--host` for agents-md, Gemini, Cursor, or OpenCode; only Claude and Cursor emit skills. There is no plugin and no marketplace — `noir init` / `noir sync` overwrite the managed `noir-*` namespace idempotently.
|
|
34
34
|
|
|
35
35
|
## Commands
|
|
36
36
|
|
package/dist/bin.js
CHANGED
|
@@ -777,13 +777,15 @@ async function status(opts) {
|
|
|
777
777
|
// src/commands/task.ts
|
|
778
778
|
import { PHASES } from "@noir-ai/workflow";
|
|
779
779
|
var PHASE_SKILL = {
|
|
780
|
-
|
|
781
|
-
|
|
780
|
+
// C3 curation (2026-08-10): intake+clarify merged into brainstorming;
|
|
781
|
+
// execute → executing-plans; verify → verifying; document → wrap.
|
|
782
|
+
intake: "noir-brainstorming",
|
|
783
|
+
clarify: "noir-brainstorming",
|
|
782
784
|
spec: "noir-spec",
|
|
783
|
-
plan: "noir-
|
|
784
|
-
execute: "noir-
|
|
785
|
-
verify: "noir-
|
|
786
|
-
document: "noir-
|
|
785
|
+
plan: "noir-planning",
|
|
786
|
+
execute: "noir-executing-plans",
|
|
787
|
+
verify: "noir-verifying",
|
|
788
|
+
document: "noir-wrap"
|
|
787
789
|
};
|
|
788
790
|
function skillFor(phase) {
|
|
789
791
|
if (typeof phase !== "string") return null;
|
|
@@ -1906,41 +1908,38 @@ async function memoryConsolidate(opts) {
|
|
|
1906
1908
|
import { claudeAdapter } from "@noir-ai/adapters";
|
|
1907
1909
|
import { loadProjectInfo as loadProjectInfo6 } from "@noir-ai/core";
|
|
1908
1910
|
import {
|
|
1911
|
+
buildRegistry,
|
|
1909
1912
|
discoverAll,
|
|
1910
|
-
emitSkillsToDir
|
|
1913
|
+
emitSkillsToDir,
|
|
1914
|
+
lintSkill
|
|
1911
1915
|
} from "@noir-ai/skills";
|
|
1912
1916
|
var CATEGORY = {
|
|
1913
|
-
"noir-
|
|
1914
|
-
"noir-
|
|
1915
|
-
"noir-
|
|
1916
|
-
"noir-
|
|
1917
|
+
"noir-brainstorming": "discovery",
|
|
1918
|
+
"noir-sync": "discovery",
|
|
1919
|
+
"noir-checkpoint": "discovery",
|
|
1920
|
+
"noir-exploring": "discovery",
|
|
1917
1921
|
"noir-spec": "spec",
|
|
1918
|
-
"noir-
|
|
1919
|
-
"noir-
|
|
1920
|
-
"noir-
|
|
1921
|
-
"noir-
|
|
1922
|
+
"noir-planning": "plan",
|
|
1923
|
+
"noir-prd": "plan",
|
|
1924
|
+
"noir-executing-plans": "execute",
|
|
1925
|
+
"noir-test-driven-development": "execute",
|
|
1926
|
+
"noir-systematic-debugging": "execute",
|
|
1922
1927
|
"noir-subagent": "execute",
|
|
1923
1928
|
"noir-parallel": "execute",
|
|
1924
|
-
"noir-
|
|
1925
|
-
"noir-review": "verify",
|
|
1929
|
+
"noir-verifying": "verify",
|
|
1926
1930
|
"noir-security": "verify",
|
|
1927
|
-
"noir-
|
|
1928
|
-
"noir-document": "document",
|
|
1931
|
+
"noir-wrap": "document",
|
|
1929
1932
|
"noir-readme": "document",
|
|
1930
|
-
"noir-
|
|
1931
|
-
"noir-branch": "git",
|
|
1932
|
-
"noir-pr": "git",
|
|
1933
|
+
"noir-shipping": "git",
|
|
1933
1934
|
"noir-worktree": "git",
|
|
1934
1935
|
"noir-recall": "memory",
|
|
1935
1936
|
"noir-remember": "memory",
|
|
1936
|
-
"noir-checkpoint": "memory",
|
|
1937
1937
|
"noir-context": "context",
|
|
1938
1938
|
"noir-frontend": "domain",
|
|
1939
1939
|
"noir-backend": "domain",
|
|
1940
1940
|
"noir-doctor": "meta",
|
|
1941
|
-
"noir-
|
|
1942
|
-
"noir-
|
|
1943
|
-
"noir-wrap": "meta"
|
|
1941
|
+
"noir-writing-skills": "meta",
|
|
1942
|
+
"noir-rules": "meta"
|
|
1944
1943
|
};
|
|
1945
1944
|
function categoryOf(name) {
|
|
1946
1945
|
const mapped = CATEGORY[name];
|
|
@@ -1949,7 +1948,9 @@ function categoryOf(name) {
|
|
|
1949
1948
|
}
|
|
1950
1949
|
function toRow(s, kind = "builtin") {
|
|
1951
1950
|
const description = typeof s.frontmatter.description === "string" ? s.frontmatter.description : "";
|
|
1952
|
-
|
|
1951
|
+
const status2 = s.skillMd.includes("> **Stub:**") ? "stub" : "full";
|
|
1952
|
+
const category = s.frontmatter.metadata?.category?.trim() || categoryOf(s.name);
|
|
1953
|
+
return { name: s.name, category, description, kind, status: status2 };
|
|
1953
1954
|
}
|
|
1954
1955
|
function truncate(text, max) {
|
|
1955
1956
|
if (text.length <= max) return text;
|
|
@@ -1990,9 +1991,10 @@ async function skillsList(opts) {
|
|
|
1990
1991
|
Skill: r.name,
|
|
1991
1992
|
Kind: r.kind,
|
|
1992
1993
|
Category: r.category,
|
|
1994
|
+
Status: r.status,
|
|
1993
1995
|
Description: truncate(r.description, 80)
|
|
1994
1996
|
})),
|
|
1995
|
-
["Skill", "Kind", "Category", "Description"],
|
|
1997
|
+
["Skill", "Kind", "Category", "Status", "Description"],
|
|
1996
1998
|
opts
|
|
1997
1999
|
);
|
|
1998
2000
|
}
|
|
@@ -2039,6 +2041,76 @@ async function skillsSync(opts) {
|
|
|
2039
2041
|
);
|
|
2040
2042
|
}
|
|
2041
2043
|
}
|
|
2044
|
+
async function skillsLint(opts) {
|
|
2045
|
+
let skills;
|
|
2046
|
+
try {
|
|
2047
|
+
const all = discoverAll();
|
|
2048
|
+
skills = [...all.builtins, ...all.integrations].map(lintSkill);
|
|
2049
|
+
} catch (err) {
|
|
2050
|
+
fail(
|
|
2051
|
+
EXIT.ERROR,
|
|
2052
|
+
`skills lint: could not lint skills (${err instanceof Error ? err.message : String(err)})`,
|
|
2053
|
+
opts
|
|
2054
|
+
);
|
|
2055
|
+
}
|
|
2056
|
+
const errored = skills.filter((s) => s.errors.length > 0);
|
|
2057
|
+
const warned = skills.filter((s) => s.warnings.length > 0 && s.errors.length === 0);
|
|
2058
|
+
const data = { count: skills.length, errored: errored.length, skills };
|
|
2059
|
+
if (opts.json === true) {
|
|
2060
|
+
process.stdout.write(`${JSON.stringify({ ok: errored.length === 0, data })}
|
|
2061
|
+
`);
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
if (errored.length === 0) {
|
|
2065
|
+
log(`noir skills lint \u2014 ${skills.length} skills, all validate clean.`, opts);
|
|
2066
|
+
} else {
|
|
2067
|
+
warn(
|
|
2068
|
+
`noir skills lint \u2014 ${errored.length} skill${errored.length === 1 ? "" : "s"} FAIL validation:`,
|
|
2069
|
+
opts
|
|
2070
|
+
);
|
|
2071
|
+
}
|
|
2072
|
+
for (const s of errored) {
|
|
2073
|
+
for (const e of s.errors) warn(` ${s.name}: ${e}`, opts);
|
|
2074
|
+
}
|
|
2075
|
+
if (warned.length > 0) {
|
|
2076
|
+
info(` ${warned.length} skill${warned.length === 1 ? "" : "s"} carry lint warnings:`, opts);
|
|
2077
|
+
for (const s of warned) {
|
|
2078
|
+
for (const w of s.warnings) info(` ${s.name}: ${w}`, opts);
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
async function skillsRegistry(opts) {
|
|
2083
|
+
let reg;
|
|
2084
|
+
try {
|
|
2085
|
+
reg = buildRegistry();
|
|
2086
|
+
} catch (err) {
|
|
2087
|
+
fail(
|
|
2088
|
+
EXIT.ERROR,
|
|
2089
|
+
`skills registry: could not build registry (${err instanceof Error ? err.message : String(err)})`,
|
|
2090
|
+
opts
|
|
2091
|
+
);
|
|
2092
|
+
}
|
|
2093
|
+
const data = { count: reg.length, skills: reg };
|
|
2094
|
+
if (opts.json === true) {
|
|
2095
|
+
process.stdout.write(`${JSON.stringify({ ok: true, data })}
|
|
2096
|
+
`);
|
|
2097
|
+
return;
|
|
2098
|
+
}
|
|
2099
|
+
log(`noir skills registry \u2014 ${reg.length} skills.`, opts);
|
|
2100
|
+
table(
|
|
2101
|
+
reg.map((r) => ({
|
|
2102
|
+
Skill: r.name,
|
|
2103
|
+
Kind: r.kind,
|
|
2104
|
+
Category: r.category,
|
|
2105
|
+
Version: r.version,
|
|
2106
|
+
Status: r.status,
|
|
2107
|
+
Refs: String(r.referenceCount),
|
|
2108
|
+
Lines: String(r.lines)
|
|
2109
|
+
})),
|
|
2110
|
+
["Skill", "Kind", "Category", "Version", "Status", "Refs", "Lines"],
|
|
2111
|
+
opts
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2042
2114
|
|
|
2043
2115
|
// src/bin.ts
|
|
2044
2116
|
function buildPaletteCommandsForTui() {
|
|
@@ -2385,8 +2457,14 @@ function createProgram() {
|
|
|
2385
2457
|
skillsGrp.command("sync").description("re-emit skills to the host skills dir").action(async (...args) => {
|
|
2386
2458
|
await skillsSync(toCliOptions(actionGlobals(args)));
|
|
2387
2459
|
});
|
|
2460
|
+
skillsGrp.command("lint").description("structural quality gate over the shipped pack (C3)").action(async (...args) => {
|
|
2461
|
+
await skillsLint(toCliOptions(actionGlobals(args)));
|
|
2462
|
+
});
|
|
2463
|
+
skillsGrp.command("registry").description("emit the runtime-derived skill registry (C3)").action(async (...args) => {
|
|
2464
|
+
await skillsRegistry(toCliOptions(actionGlobals(args)));
|
|
2465
|
+
});
|
|
2388
2466
|
skillsGrp.action(() => {
|
|
2389
|
-
throw new NoirCliError(EXIT.USAGE, "Usage: noir skills list|sync");
|
|
2467
|
+
throw new NoirCliError(EXIT.USAGE, "Usage: noir skills list|sync|lint|registry");
|
|
2390
2468
|
});
|
|
2391
2469
|
const taskGrp = program2.command("task").description("workflow task control");
|
|
2392
2470
|
taskGrp.command("new").description("start a new workflow task").requiredOption("--slug <slug>", "task slug").option("--mode <mode>", "full | quick").action(async (...args) => {
|