facult 2.6.0 → 2.7.1
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 +145 -337
- package/package.json +1 -1
- package/src/adapters/codex.ts +1 -1
- package/src/audit/agent.ts +26 -24
- package/src/audit/fix.ts +875 -0
- package/src/audit/index.ts +51 -2
- package/src/audit/safe.ts +596 -0
- package/src/audit/static.ts +151 -34
- package/src/audit/status.ts +21 -0
- package/src/audit/suppressions.ts +266 -0
- package/src/audit/tui.ts +784 -174
- package/src/audit/update-index.ts +4 -17
- package/src/builtin.ts +7 -1
- package/src/cli-ui.ts +375 -0
- package/src/consolidate.ts +151 -55
- package/src/doctor.ts +327 -0
- package/src/global-docs.ts +43 -2
- package/src/index.ts +571 -292
- package/src/manage.ts +931 -88
- package/src/mcp-config.ts +132 -0
- package/src/project-sync.ts +288 -0
- package/src/remote.ts +387 -117
- package/src/trust.ts +119 -11
- package/src/util/git.ts +95 -0
package/src/remote.ts
CHANGED
|
@@ -11,6 +11,14 @@ import {
|
|
|
11
11
|
} from "node:path";
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
13
|
import { isCancel, multiselect, select, text } from "@clack/prompts";
|
|
14
|
+
import {
|
|
15
|
+
renderBullets,
|
|
16
|
+
renderCatalog,
|
|
17
|
+
renderCode,
|
|
18
|
+
renderKeyValue,
|
|
19
|
+
renderPage,
|
|
20
|
+
renderTable,
|
|
21
|
+
} from "./cli-ui";
|
|
14
22
|
import { buildIndex } from "./index-builder";
|
|
15
23
|
import { facultRootDir, readFacultConfig } from "./paths";
|
|
16
24
|
import {
|
|
@@ -49,6 +57,8 @@ const REMOTE_STATE_VERSION = 1;
|
|
|
49
57
|
const VERSION_TOKEN_RE = /[A-Za-z]+|[0-9]+/g;
|
|
50
58
|
const QUERY_SPLIT_RE = /\s+/;
|
|
51
59
|
const MD_EXT_RE = /\.md$/i;
|
|
60
|
+
const FILE_EXT_RE = /\.[A-Za-z0-9]+$/;
|
|
61
|
+
const TRAILING_SLASH_RE = /\/+$/;
|
|
52
62
|
const PROMPT_PATH_SPLIT_RE = /[,\n]/;
|
|
53
63
|
const GIT_WORKTREE_LINE_RE = /\r?\n/;
|
|
54
64
|
|
|
@@ -231,6 +241,38 @@ Use this skill when the task repeatedly follows a known workflow and you want co
|
|
|
231
241
|
},
|
|
232
242
|
},
|
|
233
243
|
},
|
|
244
|
+
{
|
|
245
|
+
id: "agent-template",
|
|
246
|
+
type: "agent",
|
|
247
|
+
title: "Canonical Agent Template",
|
|
248
|
+
description:
|
|
249
|
+
"Starter canonical subagent scaffold for focused, reviewable specialist behavior.",
|
|
250
|
+
version: "1.0.0",
|
|
251
|
+
tags: ["template", "dx", "agent"],
|
|
252
|
+
agent: {
|
|
253
|
+
fileName: "agent.toml",
|
|
254
|
+
content: `name = "{{name}}"
|
|
255
|
+
description = "Describe the focused responsibility for {{name}}."
|
|
256
|
+
|
|
257
|
+
developer_instructions = """
|
|
258
|
+
You are {{name}}.
|
|
259
|
+
|
|
260
|
+
Operate with a tight scope.
|
|
261
|
+
|
|
262
|
+
Prioritize:
|
|
263
|
+
- one clear responsibility
|
|
264
|
+
- concrete evidence over vague summaries
|
|
265
|
+
- explicit assumptions and blockers
|
|
266
|
+
- outputs that are easy for the calling agent to apply
|
|
267
|
+
|
|
268
|
+
Return:
|
|
269
|
+
- what you changed or found
|
|
270
|
+
- what you verified
|
|
271
|
+
- what still needs a decision
|
|
272
|
+
"""
|
|
273
|
+
`,
|
|
274
|
+
},
|
|
275
|
+
},
|
|
234
276
|
{
|
|
235
277
|
id: "agents-md-template",
|
|
236
278
|
type: "agent",
|
|
@@ -589,7 +631,11 @@ function normalizeCwdList(raw: string | null | undefined): string[] {
|
|
|
589
631
|
|
|
590
632
|
function isInteractiveOutputRequested(args: string[]): boolean {
|
|
591
633
|
return (
|
|
592
|
-
!
|
|
634
|
+
!(
|
|
635
|
+
args.includes("--json") ||
|
|
636
|
+
args.includes("--yes") ||
|
|
637
|
+
args.includes("--non-interactive")
|
|
638
|
+
) &&
|
|
593
639
|
process.stdin.isTTY === true &&
|
|
594
640
|
process.stdout.isTTY === true
|
|
595
641
|
);
|
|
@@ -1895,6 +1941,18 @@ async function installMcpItem(args: {
|
|
|
1895
1941
|
};
|
|
1896
1942
|
}
|
|
1897
1943
|
|
|
1944
|
+
function deriveAgentTemplateName(fileName: string): string {
|
|
1945
|
+
const normalized = fileName.replaceAll("\\", "/");
|
|
1946
|
+
const base = basename(normalized);
|
|
1947
|
+
if (base.toLowerCase() === "agent.toml") {
|
|
1948
|
+
const parent = basename(dirname(normalized));
|
|
1949
|
+
if (parent && parent !== ".") {
|
|
1950
|
+
return parent;
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
return base.replace(FILE_EXT_RE, "");
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1898
1956
|
async function installAgentItem(args: {
|
|
1899
1957
|
item: RemoteAgentItem;
|
|
1900
1958
|
installAs?: string;
|
|
@@ -1918,12 +1976,14 @@ async function installAgentItem(args: {
|
|
|
1918
1976
|
);
|
|
1919
1977
|
}
|
|
1920
1978
|
|
|
1979
|
+
const agentName = deriveAgentTemplateName(fileName);
|
|
1980
|
+
|
|
1921
1981
|
if (!args.dryRun) {
|
|
1922
1982
|
await mkdir(dirname(filePath), { recursive: true });
|
|
1923
1983
|
await Bun.write(
|
|
1924
1984
|
filePath,
|
|
1925
1985
|
renderTemplate(args.item.agent.content, {
|
|
1926
|
-
name:
|
|
1986
|
+
name: agentName,
|
|
1927
1987
|
})
|
|
1928
1988
|
);
|
|
1929
1989
|
}
|
|
@@ -2488,84 +2548,159 @@ async function verifySource(args: {
|
|
|
2488
2548
|
}
|
|
2489
2549
|
|
|
2490
2550
|
function printSearchHelp() {
|
|
2491
|
-
console.log(
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2551
|
+
console.log(
|
|
2552
|
+
renderPage({
|
|
2553
|
+
title: "fclt search",
|
|
2554
|
+
subtitle: "Search configured remote indices.",
|
|
2555
|
+
sections: [
|
|
2556
|
+
{
|
|
2557
|
+
title: "Usage",
|
|
2558
|
+
lines: renderBullets([
|
|
2559
|
+
renderCode(
|
|
2560
|
+
"fclt search <query> [--index <name>] [--limit <n>] [--json]"
|
|
2561
|
+
),
|
|
2562
|
+
]),
|
|
2563
|
+
},
|
|
2564
|
+
{
|
|
2565
|
+
title: "Notes",
|
|
2566
|
+
lines: renderBullets([
|
|
2567
|
+
`Builtin index ${renderCode(BUILTIN_INDEX_NAME)} is always available.`,
|
|
2568
|
+
`Builtin provider aliases: ${SMITHERY_INDEX_NAME}, ${GLAMA_INDEX_NAME}, ${SKILLS_SH_INDEX_NAME}, ${CLAWHUB_INDEX_NAME}.`,
|
|
2569
|
+
"Optional custom indices can be configured in ~/.ai/.facult/indices.json.",
|
|
2570
|
+
]),
|
|
2571
|
+
},
|
|
2572
|
+
],
|
|
2573
|
+
})
|
|
2574
|
+
);
|
|
2501
2575
|
}
|
|
2502
2576
|
|
|
2503
2577
|
function printInstallHelp() {
|
|
2504
|
-
console.log(
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2578
|
+
console.log(
|
|
2579
|
+
renderPage({
|
|
2580
|
+
title: "fclt install",
|
|
2581
|
+
subtitle: "Install an item from a remote index into canonical state.",
|
|
2582
|
+
sections: [
|
|
2583
|
+
{
|
|
2584
|
+
title: "Usage",
|
|
2585
|
+
lines: renderBullets([
|
|
2586
|
+
renderCode(
|
|
2587
|
+
"fclt install <index:item> [--as <name>] [--dry-run] [--force] [--strict-source-trust] [--json]"
|
|
2588
|
+
),
|
|
2589
|
+
]),
|
|
2590
|
+
},
|
|
2591
|
+
{
|
|
2592
|
+
title: "Examples",
|
|
2593
|
+
lines: renderBullets([
|
|
2594
|
+
renderCode("fclt install facult:skill-template --as my-skill"),
|
|
2595
|
+
renderCode(
|
|
2596
|
+
"fclt install facult:agent-template --as reviewer/agent.toml"
|
|
2597
|
+
),
|
|
2598
|
+
renderCode("fclt install facult:mcp-stdio-template --as github"),
|
|
2599
|
+
renderCode("fclt install smithery:github"),
|
|
2600
|
+
]),
|
|
2601
|
+
},
|
|
2602
|
+
],
|
|
2603
|
+
})
|
|
2604
|
+
);
|
|
2517
2605
|
}
|
|
2518
2606
|
|
|
2519
2607
|
function printUpdateHelp() {
|
|
2520
|
-
console.log(
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2608
|
+
console.log(
|
|
2609
|
+
renderPage({
|
|
2610
|
+
title: "fclt update",
|
|
2611
|
+
subtitle: "Check for updates to remotely installed items.",
|
|
2612
|
+
sections: [
|
|
2613
|
+
{
|
|
2614
|
+
title: "Usage",
|
|
2615
|
+
lines: renderBullets([
|
|
2616
|
+
renderCode(
|
|
2617
|
+
"fclt update [--apply] [--strict-source-trust] [--json]"
|
|
2618
|
+
),
|
|
2619
|
+
]),
|
|
2620
|
+
},
|
|
2621
|
+
{
|
|
2622
|
+
title: "Options",
|
|
2623
|
+
lines: renderTable({
|
|
2624
|
+
headers: ["Option", "Meaning"],
|
|
2625
|
+
rows: [
|
|
2626
|
+
["--apply", "Install available updates"],
|
|
2627
|
+
[
|
|
2628
|
+
"--strict-source-trust",
|
|
2629
|
+
"Block review-level sources unless explicitly trusted",
|
|
2630
|
+
],
|
|
2631
|
+
],
|
|
2632
|
+
}),
|
|
2633
|
+
},
|
|
2634
|
+
],
|
|
2635
|
+
})
|
|
2636
|
+
);
|
|
2529
2637
|
}
|
|
2530
2638
|
|
|
2531
2639
|
function printTemplatesHelp() {
|
|
2532
|
-
console.log(
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2640
|
+
console.log(
|
|
2641
|
+
renderPage({
|
|
2642
|
+
title: "fclt templates",
|
|
2643
|
+
subtitle:
|
|
2644
|
+
"Scaffold canonical skills, MCP, agents, snippets, docs, and automation.",
|
|
2645
|
+
sections: [
|
|
2646
|
+
{
|
|
2647
|
+
title: "Usage",
|
|
2648
|
+
lines: renderBullets([
|
|
2649
|
+
renderCode("fclt templates list [--json]"),
|
|
2650
|
+
renderCode(
|
|
2651
|
+
"fclt templates init skill <name> [--force] [--dry-run]"
|
|
2652
|
+
),
|
|
2653
|
+
renderCode("fclt templates init mcp <name> [--force] [--dry-run]"),
|
|
2654
|
+
renderCode(
|
|
2655
|
+
"fclt templates init agent <name> [--force] [--dry-run]"
|
|
2656
|
+
),
|
|
2657
|
+
renderCode(
|
|
2658
|
+
"fclt templates init snippet <marker> [--force] [--dry-run]"
|
|
2659
|
+
),
|
|
2660
|
+
renderCode("fclt templates init agents [--force] [--dry-run]"),
|
|
2661
|
+
renderCode("fclt templates init project-ai [--force] [--dry-run]"),
|
|
2662
|
+
renderCode(
|
|
2663
|
+
"fclt templates init automation <template-id> [--scope global|project|wide] [--name <name>] [--project-root <path>] [--cwds <path1,path2>] [--rrule <RRULE>] [--status PAUSED|ACTIVE] [--yes] [--dry-run]"
|
|
2664
|
+
),
|
|
2665
|
+
]),
|
|
2666
|
+
},
|
|
2667
|
+
{
|
|
2668
|
+
title: "Notes",
|
|
2669
|
+
lines: renderBullets([
|
|
2670
|
+
`Templates are powered by the builtin ${renderCode(BUILTIN_INDEX_NAME)} index.`,
|
|
2671
|
+
"Automation templates scaffold Codex automation files under ~/.codex/automations/.",
|
|
2672
|
+
`${renderCode("--yes")} and ${renderCode("--non-interactive")} skip scope prompts and use inferred defaults when possible.`,
|
|
2673
|
+
"Use project scope for one repo root, wide/global scope for many explicit roots.",
|
|
2674
|
+
]),
|
|
2675
|
+
},
|
|
2676
|
+
],
|
|
2677
|
+
})
|
|
2678
|
+
);
|
|
2556
2679
|
}
|
|
2557
2680
|
|
|
2558
2681
|
function printVerifySourceHelp() {
|
|
2559
|
-
console.log(
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2682
|
+
console.log(
|
|
2683
|
+
renderPage({
|
|
2684
|
+
title: "fclt verify-source",
|
|
2685
|
+
subtitle: "Verify source trust, integrity, and signature status.",
|
|
2686
|
+
sections: [
|
|
2687
|
+
{
|
|
2688
|
+
title: "Usage",
|
|
2689
|
+
lines: renderBullets([
|
|
2690
|
+
renderCode("fclt verify-source <name> [--json]"),
|
|
2691
|
+
]),
|
|
2692
|
+
},
|
|
2693
|
+
{
|
|
2694
|
+
title: "Examples",
|
|
2695
|
+
lines: renderBullets([
|
|
2696
|
+
renderCode("fclt verify-source facult"),
|
|
2697
|
+
renderCode("fclt verify-source smithery"),
|
|
2698
|
+
renderCode("fclt verify-source local-index --json"),
|
|
2699
|
+
]),
|
|
2700
|
+
},
|
|
2701
|
+
],
|
|
2702
|
+
})
|
|
2703
|
+
);
|
|
2569
2704
|
}
|
|
2570
2705
|
|
|
2571
2706
|
function parseLongFlag(argv: string[], flag: string): string | null {
|
|
@@ -2644,16 +2779,34 @@ export async function searchCommand(
|
|
|
2644
2779
|
return;
|
|
2645
2780
|
}
|
|
2646
2781
|
if (!results.length) {
|
|
2647
|
-
console.log("(no results)");
|
|
2648
|
-
return;
|
|
2649
|
-
}
|
|
2650
|
-
for (const row of results) {
|
|
2651
|
-
const version = row.item.version ?? "-";
|
|
2652
|
-
const title = row.item.title ?? row.item.description ?? "";
|
|
2653
2782
|
console.log(
|
|
2654
|
-
|
|
2783
|
+
renderPage({
|
|
2784
|
+
title: "fclt search",
|
|
2785
|
+
subtitle: `No remote results for "${query}".`,
|
|
2786
|
+
sections: [],
|
|
2787
|
+
})
|
|
2655
2788
|
);
|
|
2789
|
+
return;
|
|
2656
2790
|
}
|
|
2791
|
+
console.log(
|
|
2792
|
+
renderPage({
|
|
2793
|
+
title: "fclt search",
|
|
2794
|
+
subtitle: `${results.length} remote match${results.length === 1 ? "" : "es"} for "${query}"`,
|
|
2795
|
+
sections: [
|
|
2796
|
+
{
|
|
2797
|
+
title: "Results",
|
|
2798
|
+
lines: renderCatalog(
|
|
2799
|
+
results.map((row) => ({
|
|
2800
|
+
title: `${row.index}:${row.item.id}`,
|
|
2801
|
+
meta: `${row.item.type} • v${row.item.version ?? "-"}`,
|
|
2802
|
+
description:
|
|
2803
|
+
row.item.title ?? row.item.description ?? "No title.",
|
|
2804
|
+
}))
|
|
2805
|
+
),
|
|
2806
|
+
},
|
|
2807
|
+
],
|
|
2808
|
+
})
|
|
2809
|
+
);
|
|
2657
2810
|
} catch (err) {
|
|
2658
2811
|
console.error(err instanceof Error ? err.message : String(err));
|
|
2659
2812
|
process.exitCode = 1;
|
|
@@ -2704,15 +2857,37 @@ export async function installCommand(
|
|
|
2704
2857
|
return;
|
|
2705
2858
|
}
|
|
2706
2859
|
const action = dryRun ? "Would install" : "Installed";
|
|
2707
|
-
console.log(
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2860
|
+
console.log(
|
|
2861
|
+
renderPage({
|
|
2862
|
+
title: "fclt install",
|
|
2863
|
+
subtitle: `${action} ${result.ref} as ${result.installedAs}`,
|
|
2864
|
+
sections: [
|
|
2865
|
+
{
|
|
2866
|
+
title: "Result",
|
|
2867
|
+
lines: renderKeyValue([
|
|
2868
|
+
["type", result.type],
|
|
2869
|
+
[
|
|
2870
|
+
"source trust",
|
|
2871
|
+
result.sourceTrustLevel === "trusted"
|
|
2872
|
+
? "trusted"
|
|
2873
|
+
: result.sourceTrustLevel,
|
|
2874
|
+
],
|
|
2875
|
+
["path", result.path],
|
|
2876
|
+
]),
|
|
2877
|
+
},
|
|
2878
|
+
{
|
|
2879
|
+
title: "Changed Paths",
|
|
2880
|
+
lines: renderBullets(result.changedPaths),
|
|
2881
|
+
},
|
|
2882
|
+
],
|
|
2883
|
+
footer:
|
|
2884
|
+
result.sourceTrustLevel === "review" && !strictSourceTrust
|
|
2885
|
+
? [
|
|
2886
|
+
"Source policy is review. Use --strict-source-trust to require explicit trust.",
|
|
2887
|
+
]
|
|
2888
|
+
: undefined,
|
|
2889
|
+
})
|
|
2890
|
+
);
|
|
2716
2891
|
} catch (err) {
|
|
2717
2892
|
console.error(err instanceof Error ? err.message : String(err));
|
|
2718
2893
|
process.exitCode = 1;
|
|
@@ -2747,19 +2922,39 @@ export async function updateCommand(
|
|
|
2747
2922
|
return;
|
|
2748
2923
|
}
|
|
2749
2924
|
if (!report.checks.length) {
|
|
2750
|
-
console.log("No remotely installed items found.");
|
|
2751
|
-
return;
|
|
2752
|
-
}
|
|
2753
|
-
for (const check of report.checks) {
|
|
2754
|
-
const current = check.currentVersion ?? "-";
|
|
2755
|
-
const latest = check.latestVersion ?? "-";
|
|
2756
2925
|
console.log(
|
|
2757
|
-
|
|
2926
|
+
renderPage({
|
|
2927
|
+
title: "fclt update",
|
|
2928
|
+
subtitle: "No remotely installed items found.",
|
|
2929
|
+
sections: [],
|
|
2930
|
+
})
|
|
2758
2931
|
);
|
|
2932
|
+
return;
|
|
2759
2933
|
}
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2934
|
+
console.log(
|
|
2935
|
+
renderPage({
|
|
2936
|
+
title: "fclt update",
|
|
2937
|
+
subtitle: `${report.checks.length} installed item${report.checks.length === 1 ? "" : "s"} checked`,
|
|
2938
|
+
sections: [
|
|
2939
|
+
{
|
|
2940
|
+
title: "Checks",
|
|
2941
|
+
lines: renderCatalog(
|
|
2942
|
+
report.checks.map((check) => ({
|
|
2943
|
+
title: check.installed.ref,
|
|
2944
|
+
meta: check.status,
|
|
2945
|
+
description: check.installed.installedAs,
|
|
2946
|
+
details: [
|
|
2947
|
+
`Version ${check.currentVersion ?? "-"} -> ${check.latestVersion ?? "-"}`,
|
|
2948
|
+
],
|
|
2949
|
+
}))
|
|
2950
|
+
),
|
|
2951
|
+
},
|
|
2952
|
+
],
|
|
2953
|
+
footer: apply
|
|
2954
|
+
? [`Applied ${report.applied.length} update(s).`]
|
|
2955
|
+
: undefined,
|
|
2956
|
+
})
|
|
2957
|
+
);
|
|
2763
2958
|
} catch (err) {
|
|
2764
2959
|
console.error(err instanceof Error ? err.message : String(err));
|
|
2765
2960
|
process.exitCode = 1;
|
|
@@ -2802,14 +2997,31 @@ export async function verifySourceCommand(
|
|
|
2802
2997
|
} else {
|
|
2803
2998
|
const trustOrigin = report.trust.explicit ? "explicit" : "default";
|
|
2804
2999
|
console.log(
|
|
2805
|
-
|
|
3000
|
+
renderPage({
|
|
3001
|
+
title: `fclt verify-source ${report.source.name}`,
|
|
3002
|
+
subtitle: report.source.url,
|
|
3003
|
+
sections: [
|
|
3004
|
+
{
|
|
3005
|
+
title: "Source",
|
|
3006
|
+
lines: renderKeyValue([
|
|
3007
|
+
["kind", report.source.kind],
|
|
3008
|
+
["trust", `${report.trust.level} (${trustOrigin})`],
|
|
3009
|
+
["items", String(report.checks.items)],
|
|
3010
|
+
]),
|
|
3011
|
+
},
|
|
3012
|
+
{
|
|
3013
|
+
title: "Checks",
|
|
3014
|
+
lines: renderKeyValue([
|
|
3015
|
+
["fetch", report.checks.fetch],
|
|
3016
|
+
["parse", report.checks.parse],
|
|
3017
|
+
["integrity", report.checks.integrity],
|
|
3018
|
+
["signature", report.checks.signature],
|
|
3019
|
+
]),
|
|
3020
|
+
},
|
|
3021
|
+
],
|
|
3022
|
+
footer: report.error ? [`error: ${report.error}`] : undefined,
|
|
3023
|
+
})
|
|
2806
3024
|
);
|
|
2807
|
-
console.log(
|
|
2808
|
-
`trust=${report.trust.level} (${trustOrigin})\tfetch=${report.checks.fetch}\tparse=${report.checks.parse}\tintegrity=${report.checks.integrity}\tsignature=${report.checks.signature}\titems=${report.checks.items}`
|
|
2809
|
-
);
|
|
2810
|
-
if (report.error) {
|
|
2811
|
-
console.log(`error: ${report.error}`);
|
|
2812
|
-
}
|
|
2813
3025
|
}
|
|
2814
3026
|
|
|
2815
3027
|
if (report.error) {
|
|
@@ -2860,9 +3072,24 @@ export async function templatesCommand(
|
|
|
2860
3072
|
console.log(JSON.stringify(rows, null, 2));
|
|
2861
3073
|
return;
|
|
2862
3074
|
}
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
3075
|
+
console.log(
|
|
3076
|
+
renderPage({
|
|
3077
|
+
title: "fclt templates list",
|
|
3078
|
+
subtitle: `${rows.length} available scaffold${rows.length === 1 ? "" : "s"}`,
|
|
3079
|
+
sections: [
|
|
3080
|
+
{
|
|
3081
|
+
title: "Templates",
|
|
3082
|
+
lines: renderCatalog(
|
|
3083
|
+
rows.map((row) => ({
|
|
3084
|
+
title: row.id,
|
|
3085
|
+
meta: `${row.type} • ${row.version}`,
|
|
3086
|
+
description: row.description || row.title,
|
|
3087
|
+
}))
|
|
3088
|
+
),
|
|
3089
|
+
},
|
|
3090
|
+
],
|
|
3091
|
+
})
|
|
3092
|
+
);
|
|
2866
3093
|
return;
|
|
2867
3094
|
}
|
|
2868
3095
|
if (sub !== "init") {
|
|
@@ -2874,7 +3101,7 @@ export async function templatesCommand(
|
|
|
2874
3101
|
const [kind, ...args] = rest;
|
|
2875
3102
|
if (!kind) {
|
|
2876
3103
|
console.error(
|
|
2877
|
-
"templates init requires a kind (skill|mcp|snippet|agents|claude|project-ai|automation)"
|
|
3104
|
+
"templates init requires a kind (skill|mcp|agent|snippet|agents|claude|project-ai|automation)"
|
|
2878
3105
|
);
|
|
2879
3106
|
process.exitCode = 2;
|
|
2880
3107
|
return;
|
|
@@ -2897,10 +3124,18 @@ export async function templatesCommand(
|
|
|
2897
3124
|
return;
|
|
2898
3125
|
}
|
|
2899
3126
|
const action = dryRun ? "Would scaffold" : "Scaffolded";
|
|
2900
|
-
console.log(
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
3127
|
+
console.log(
|
|
3128
|
+
renderPage({
|
|
3129
|
+
title: `fclt templates init ${kind}`,
|
|
3130
|
+
subtitle: `${action} ${result.installedAs}`,
|
|
3131
|
+
sections: [
|
|
3132
|
+
{
|
|
3133
|
+
title: "Changed Paths",
|
|
3134
|
+
lines: renderBullets(result.changedPaths),
|
|
3135
|
+
},
|
|
3136
|
+
],
|
|
3137
|
+
})
|
|
3138
|
+
);
|
|
2904
3139
|
return;
|
|
2905
3140
|
} catch (err) {
|
|
2906
3141
|
console.error(err instanceof Error ? err.message : String(err));
|
|
@@ -2927,6 +3162,20 @@ export async function templatesCommand(
|
|
|
2927
3162
|
process.exitCode = 2;
|
|
2928
3163
|
return;
|
|
2929
3164
|
}
|
|
3165
|
+
} else if (kind === "agent") {
|
|
3166
|
+
ref = `${BUILTIN_INDEX_NAME}:agent-template`;
|
|
3167
|
+
const rawName = positional[0];
|
|
3168
|
+
if (!rawName) {
|
|
3169
|
+
console.error("templates init agent requires a <name>");
|
|
3170
|
+
process.exitCode = 2;
|
|
3171
|
+
return;
|
|
3172
|
+
}
|
|
3173
|
+
const normalizedName = rawName
|
|
3174
|
+
.replaceAll("\\", "/")
|
|
3175
|
+
.replace(TRAILING_SLASH_RE, "");
|
|
3176
|
+
as = normalizedName.endsWith(".toml")
|
|
3177
|
+
? normalizedName
|
|
3178
|
+
: `${normalizedName}/agent.toml`;
|
|
2930
3179
|
} else if (kind === "snippet") {
|
|
2931
3180
|
ref = `${BUILTIN_INDEX_NAME}:snippet-template`;
|
|
2932
3181
|
as = positional[0];
|
|
@@ -2999,11 +3248,24 @@ export async function templatesCommand(
|
|
|
2999
3248
|
}
|
|
3000
3249
|
const action = dryRun ? "Would scaffold" : "Scaffolded";
|
|
3001
3250
|
console.log(
|
|
3002
|
-
|
|
3251
|
+
renderPage({
|
|
3252
|
+
title: "fclt templates init automation",
|
|
3253
|
+
subtitle: `${action} ${result.installedAs}`,
|
|
3254
|
+
sections: [
|
|
3255
|
+
{
|
|
3256
|
+
title: "Automation",
|
|
3257
|
+
lines: renderKeyValue([
|
|
3258
|
+
["name", result.installedAs],
|
|
3259
|
+
["path", result.path],
|
|
3260
|
+
]),
|
|
3261
|
+
},
|
|
3262
|
+
{
|
|
3263
|
+
title: "Changed Paths",
|
|
3264
|
+
lines: renderBullets(result.changedPaths),
|
|
3265
|
+
},
|
|
3266
|
+
],
|
|
3267
|
+
})
|
|
3003
3268
|
);
|
|
3004
|
-
for (const path of result.changedPaths) {
|
|
3005
|
-
console.log(` - ${path}`);
|
|
3006
|
-
}
|
|
3007
3269
|
return;
|
|
3008
3270
|
} catch (err) {
|
|
3009
3271
|
console.error(err instanceof Error ? err.message : String(err));
|
|
@@ -3034,10 +3296,18 @@ export async function templatesCommand(
|
|
|
3034
3296
|
return;
|
|
3035
3297
|
}
|
|
3036
3298
|
const action = dryRun ? "Would scaffold" : "Scaffolded";
|
|
3037
|
-
console.log(
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3299
|
+
console.log(
|
|
3300
|
+
renderPage({
|
|
3301
|
+
title: `fclt templates init ${kind}`,
|
|
3302
|
+
subtitle: `${action} ${result.installedAs}`,
|
|
3303
|
+
sections: [
|
|
3304
|
+
{
|
|
3305
|
+
title: "Changed Paths",
|
|
3306
|
+
lines: renderBullets(result.changedPaths),
|
|
3307
|
+
},
|
|
3308
|
+
],
|
|
3309
|
+
})
|
|
3310
|
+
);
|
|
3041
3311
|
} catch (err) {
|
|
3042
3312
|
console.error(err instanceof Error ? err.message : String(err));
|
|
3043
3313
|
process.exitCode = 1;
|