create-academic-research 0.1.3 → 0.1.5
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 +10 -7
- package/dist/src/agents.d.ts +9 -0
- package/dist/src/agents.js +126 -0
- package/dist/src/capabilities.d.ts +2 -2
- package/dist/src/capabilities.js +11 -15
- package/dist/src/cli.d.ts +1 -0
- package/dist/src/cli.js +71 -7
- package/dist/src/project.js +4 -3
- package/package.json +1 -1
- package/template/README.md +1 -0
- package/template/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,9 +35,10 @@ adjacent interdisciplinary CS.
|
|
|
35
35
|
|
|
36
36
|
The generated repository is agent-neutral. By default the wizard records
|
|
37
37
|
`agent: universal`, installs one shared project-local `.agents/skills` copy,
|
|
38
|
-
and writes generic MCP snippets. Use `--agent <
|
|
39
|
-
|
|
40
|
-
`
|
|
38
|
+
and writes generic MCP snippets. Use `--agent <id>` only when you want to force
|
|
39
|
+
a specific target recognized by the `skills` CLI. Run
|
|
40
|
+
`npx academic-research agents list` inside a generated project to see every
|
|
41
|
+
supported target and alias.
|
|
41
42
|
|
|
42
43
|
## Default Experience
|
|
43
44
|
|
|
@@ -76,6 +77,7 @@ Inside a generated project:
|
|
|
76
77
|
```bash
|
|
77
78
|
npx academic-research doctor
|
|
78
79
|
npx academic-research rename --title "New Title" --slug new-title --package new_title
|
|
80
|
+
npx academic-research agents list
|
|
79
81
|
npx academic-research skills presets
|
|
80
82
|
npx academic-research skills install --preset default
|
|
81
83
|
npx academic-research skills install --preset enhanced
|
|
@@ -134,8 +136,9 @@ The create wizard can install that project-local package automatically.
|
|
|
134
136
|
Those skills are portable `SKILL.md` instructions, but they require an
|
|
135
137
|
agent/runtime that can load skills or include the relevant instructions in
|
|
136
138
|
context. They are not automatic capabilities of every raw model API.
|
|
137
|
-
Use `--agent <
|
|
138
|
-
`--agent claude
|
|
139
|
+
Use `--agent <id>` for explicit setup with any id from
|
|
140
|
+
`academic-research agents list`. The shorthand `--agent claude` is normalized
|
|
141
|
+
to the supported `claude-code` target.
|
|
139
142
|
Avoid `--agent auto` for unattended setup: the upstream `skills` CLI may expand
|
|
140
143
|
it to every agent it detects on the machine.
|
|
141
144
|
|
|
@@ -166,8 +169,8 @@ Releases are tag-driven. Update `package.json` and `package-lock.json`, commit
|
|
|
166
169
|
the change, create `vX.Y.Z`, and push the tag:
|
|
167
170
|
|
|
168
171
|
```bash
|
|
169
|
-
git tag -a v0.1.
|
|
170
|
-
git push origin main v0.1.
|
|
172
|
+
git tag -a v0.1.5 -m "v0.1.5"
|
|
173
|
+
git push origin main v0.1.5
|
|
171
174
|
```
|
|
172
175
|
|
|
173
176
|
Once the GitHub repository is public, the release workflow validates the tag
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const DEFAULT_AGENT = "universal";
|
|
2
|
+
export declare const AUTO_AGENT = "auto";
|
|
3
|
+
export declare const SUPPORTED_SKILL_AGENT_TARGETS: readonly ["adal", "aider-desk", "amp", "antigravity", "augment", "bob", "claude-code", "cline", "codearts-agent", "codebuddy", "codemaker", "codestudio", "codex", "command-code", "continue", "cortex", "crush", "cursor", "deepagents", "devin", "dexto", "droid", "firebender", "forgecode", "gemini-cli", "github-copilot", "goose", "hermes-agent", "iflow-cli", "junie", "kilo", "kimi-cli", "kiro-cli", "kode", "mcpjam", "mistral-vibe", "mux", "neovate", "openclaw", "opencode", "openhands", "pi", "pochi", "qoder", "qwen-code", "replit", "roo", "rovodev", "tabnine-cli", "trae", "trae-cn", "universal", "warp", "windsurf", "zencoder"];
|
|
4
|
+
export declare const AGENT_TARGET_ALIASES: Record<string, string>;
|
|
5
|
+
export declare function normalizeAgentTarget(agent: string | undefined): string;
|
|
6
|
+
export declare function assertKnownAgentTarget(agent: string | undefined): string;
|
|
7
|
+
export declare function formatAgentTargetList(): string;
|
|
8
|
+
export declare function formatSupportedAgentTargetLines(indent?: string, width?: number): string[];
|
|
9
|
+
export declare function formatAgentAliasLines(indent?: string): string[];
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export const DEFAULT_AGENT = "universal";
|
|
2
|
+
export const AUTO_AGENT = "auto";
|
|
3
|
+
export const SUPPORTED_SKILL_AGENT_TARGETS = [
|
|
4
|
+
"adal",
|
|
5
|
+
"aider-desk",
|
|
6
|
+
"amp",
|
|
7
|
+
"antigravity",
|
|
8
|
+
"augment",
|
|
9
|
+
"bob",
|
|
10
|
+
"claude-code",
|
|
11
|
+
"cline",
|
|
12
|
+
"codearts-agent",
|
|
13
|
+
"codebuddy",
|
|
14
|
+
"codemaker",
|
|
15
|
+
"codestudio",
|
|
16
|
+
"codex",
|
|
17
|
+
"command-code",
|
|
18
|
+
"continue",
|
|
19
|
+
"cortex",
|
|
20
|
+
"crush",
|
|
21
|
+
"cursor",
|
|
22
|
+
"deepagents",
|
|
23
|
+
"devin",
|
|
24
|
+
"dexto",
|
|
25
|
+
"droid",
|
|
26
|
+
"firebender",
|
|
27
|
+
"forgecode",
|
|
28
|
+
"gemini-cli",
|
|
29
|
+
"github-copilot",
|
|
30
|
+
"goose",
|
|
31
|
+
"hermes-agent",
|
|
32
|
+
"iflow-cli",
|
|
33
|
+
"junie",
|
|
34
|
+
"kilo",
|
|
35
|
+
"kimi-cli",
|
|
36
|
+
"kiro-cli",
|
|
37
|
+
"kode",
|
|
38
|
+
"mcpjam",
|
|
39
|
+
"mistral-vibe",
|
|
40
|
+
"mux",
|
|
41
|
+
"neovate",
|
|
42
|
+
"openclaw",
|
|
43
|
+
"opencode",
|
|
44
|
+
"openhands",
|
|
45
|
+
"pi",
|
|
46
|
+
"pochi",
|
|
47
|
+
"qoder",
|
|
48
|
+
"qwen-code",
|
|
49
|
+
"replit",
|
|
50
|
+
"roo",
|
|
51
|
+
"rovodev",
|
|
52
|
+
"tabnine-cli",
|
|
53
|
+
"trae",
|
|
54
|
+
"trae-cn",
|
|
55
|
+
"universal",
|
|
56
|
+
"warp",
|
|
57
|
+
"windsurf",
|
|
58
|
+
"zencoder"
|
|
59
|
+
];
|
|
60
|
+
export const AGENT_TARGET_ALIASES = {
|
|
61
|
+
claude: "claude-code",
|
|
62
|
+
claude_code: "claude-code"
|
|
63
|
+
};
|
|
64
|
+
const SUPPORTED_AGENT_TARGETS = new Set([
|
|
65
|
+
AUTO_AGENT,
|
|
66
|
+
...SUPPORTED_SKILL_AGENT_TARGETS
|
|
67
|
+
]);
|
|
68
|
+
export function normalizeAgentTarget(agent) {
|
|
69
|
+
const value = agent?.trim();
|
|
70
|
+
if (!value)
|
|
71
|
+
return DEFAULT_AGENT;
|
|
72
|
+
const normalized = value.toLowerCase();
|
|
73
|
+
return AGENT_TARGET_ALIASES[normalized] ?? normalized;
|
|
74
|
+
}
|
|
75
|
+
export function assertKnownAgentTarget(agent) {
|
|
76
|
+
const normalized = normalizeAgentTarget(agent);
|
|
77
|
+
if (!SUPPORTED_AGENT_TARGETS.has(normalized)) {
|
|
78
|
+
const value = agent?.trim() || DEFAULT_AGENT;
|
|
79
|
+
throw new Error([
|
|
80
|
+
`unknown agent target: ${value}`,
|
|
81
|
+
`Use ${DEFAULT_AGENT}, ${AUTO_AGENT}, or one supported skills.sh agent id.`,
|
|
82
|
+
"List targets with: npx -p create-academic-research academic-research agents list",
|
|
83
|
+
`Supported ids: ${specificAgentTargets().join(", ")}`,
|
|
84
|
+
`Aliases: ${formatAgentAliasesInline()}`
|
|
85
|
+
].join("\n"));
|
|
86
|
+
}
|
|
87
|
+
return normalized;
|
|
88
|
+
}
|
|
89
|
+
export function formatAgentTargetList() {
|
|
90
|
+
const lines = [
|
|
91
|
+
`${DEFAULT_AGENT}\tRecommended shared project-local .agents/skills copy`,
|
|
92
|
+
`${AUTO_AGENT}\tLet the skills CLI detect installed agents; may create multiple agent-specific copies`,
|
|
93
|
+
...specificAgentTargets().map((agent) => `${agent}\tskills.sh agent id`),
|
|
94
|
+
...Object.entries(AGENT_TARGET_ALIASES).map(([alias, target]) => `alias\t${alias}\t${target}`)
|
|
95
|
+
];
|
|
96
|
+
return `${lines.join("\n")}\n`;
|
|
97
|
+
}
|
|
98
|
+
export function formatSupportedAgentTargetLines(indent = " ", width = 100) {
|
|
99
|
+
const labels = specificAgentTargets();
|
|
100
|
+
const lines = [];
|
|
101
|
+
let current = indent;
|
|
102
|
+
for (const label of labels) {
|
|
103
|
+
const next = current === indent ? label : `, ${label}`;
|
|
104
|
+
if (current.length + next.length > width) {
|
|
105
|
+
lines.push(current);
|
|
106
|
+
current = `${indent}${label}`;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
current += next;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (current.trim())
|
|
113
|
+
lines.push(current);
|
|
114
|
+
return lines;
|
|
115
|
+
}
|
|
116
|
+
export function formatAgentAliasLines(indent = " ") {
|
|
117
|
+
return Object.entries(AGENT_TARGET_ALIASES).map(([alias, target]) => `${indent}${alias} -> ${target}`);
|
|
118
|
+
}
|
|
119
|
+
function formatAgentAliasesInline() {
|
|
120
|
+
return Object.entries(AGENT_TARGET_ALIASES)
|
|
121
|
+
.map(([alias, target]) => `${alias} -> ${target}`)
|
|
122
|
+
.join(", ");
|
|
123
|
+
}
|
|
124
|
+
function specificAgentTargets() {
|
|
125
|
+
return SUPPORTED_SKILL_AGENT_TARGETS.filter((agent) => agent !== DEFAULT_AGENT);
|
|
126
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { DEFAULT_AGENT, SUPPORTED_SKILL_AGENT_TARGETS } from "./agents.js";
|
|
1
2
|
import { type Runner } from "./runner.js";
|
|
2
3
|
import { type McpToolCommandKey } from "./stack.js";
|
|
3
|
-
export
|
|
4
|
+
export { DEFAULT_AGENT, SUPPORTED_SKILL_AGENT_TARGETS };
|
|
4
5
|
export interface CapabilityState {
|
|
5
6
|
agent: string;
|
|
6
7
|
preset: string;
|
|
@@ -51,4 +52,3 @@ export declare function installMcpTools(root: string, servers: string[], runner?
|
|
|
51
52
|
export declare function uninstallMcpTools(root: string, servers: string[], runner?: Runner): Promise<CapabilityCommandResult>;
|
|
52
53
|
export declare function doctorMcpServers(root: string): Promise<McpDoctorResult>;
|
|
53
54
|
export declare function assertKnownMcpServers(servers: string[]): void;
|
|
54
|
-
export {};
|
package/dist/src/capabilities.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { appendFile, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join, relative } from "node:path";
|
|
3
3
|
import YAML from "yaml";
|
|
4
|
+
import { assertKnownAgentTarget, AUTO_AGENT, DEFAULT_AGENT, normalizeAgentTarget, SUPPORTED_SKILL_AGENT_TARGETS } from "./agents.js";
|
|
4
5
|
import { defaultRunner } from "./runner.js";
|
|
5
6
|
import { AGENT_STACK, presetMcpServers } from "./stack.js";
|
|
6
|
-
export
|
|
7
|
-
const AUTO_AGENT = "auto";
|
|
7
|
+
export { DEFAULT_AGENT, SUPPORTED_SKILL_AGENT_TARGETS };
|
|
8
8
|
export async function readCapabilities(root) {
|
|
9
9
|
try {
|
|
10
10
|
return readCapabilitiesFile(root);
|
|
@@ -18,7 +18,7 @@ export async function readCapabilities(root) {
|
|
|
18
18
|
}
|
|
19
19
|
export async function writeCapabilities(root, state) {
|
|
20
20
|
const next = {
|
|
21
|
-
agent:
|
|
21
|
+
agent: assertKnownAgentTarget(state.agent),
|
|
22
22
|
preset: state.preset ?? "default",
|
|
23
23
|
scope: "project-local",
|
|
24
24
|
mcp_servers: [...(state.mcp_servers ?? [])]
|
|
@@ -42,7 +42,7 @@ export async function buildSkillInstallCommands(root, preset = "default", option
|
|
|
42
42
|
if (!selected)
|
|
43
43
|
throw new Error(`unknown skill preset: ${preset}`);
|
|
44
44
|
const state = await readCapabilities(root);
|
|
45
|
-
const agent =
|
|
45
|
+
const agent = assertKnownAgentTarget(options.agent ?? state.agent);
|
|
46
46
|
const commands = [];
|
|
47
47
|
for (const bundleName of selected.skill_bundles) {
|
|
48
48
|
const bundle = AGENT_STACK.skill_bundles[bundleName];
|
|
@@ -61,7 +61,7 @@ export async function buildSkillInstallCommands(root, preset = "default", option
|
|
|
61
61
|
}
|
|
62
62
|
export async function installSkills(root, preset = "default", options = {}, runner = defaultRunner) {
|
|
63
63
|
const state = await readCapabilities(root);
|
|
64
|
-
const agent =
|
|
64
|
+
const agent = assertKnownAgentTarget(options.agent ?? state.agent);
|
|
65
65
|
const commands = await buildSkillInstallCommands(root, preset, options);
|
|
66
66
|
for (const command of commands) {
|
|
67
67
|
await runner.run(command, { cwd: root });
|
|
@@ -135,7 +135,7 @@ export async function enableMcpServers(root, servers, options = {}) {
|
|
|
135
135
|
const selected = dedupe([...(state.mcp_servers ?? []), ...servers]);
|
|
136
136
|
await writeCapabilities(root, {
|
|
137
137
|
...state,
|
|
138
|
-
agent: options.agent ?? state.agent,
|
|
138
|
+
agent: assertKnownAgentTarget(options.agent ?? state.agent),
|
|
139
139
|
mcp_servers: selected
|
|
140
140
|
});
|
|
141
141
|
return { ok: true, servers: selected };
|
|
@@ -147,7 +147,7 @@ export async function disableMcpServers(root, servers, options = {}) {
|
|
|
147
147
|
const selected = (state.mcp_servers ?? []).filter((server) => !blocked.has(server));
|
|
148
148
|
await writeCapabilities(root, {
|
|
149
149
|
...state,
|
|
150
|
-
agent: options.agent ?? state.agent,
|
|
150
|
+
agent: assertKnownAgentTarget(options.agent ?? state.agent),
|
|
151
151
|
mcp_servers: selected
|
|
152
152
|
});
|
|
153
153
|
return { ok: true, servers: selected };
|
|
@@ -269,7 +269,7 @@ async function writeCapabilityProfile(root, state) {
|
|
|
269
269
|
const lines = [
|
|
270
270
|
"# Agent Capability Profile",
|
|
271
271
|
"",
|
|
272
|
-
`- Agent target: \`${
|
|
272
|
+
`- Agent target: \`${assertKnownAgentTarget(state.agent)}\``,
|
|
273
273
|
`- Preset: \`${state.preset ?? "default"}\``,
|
|
274
274
|
"- Scope: `project-local`",
|
|
275
275
|
"",
|
|
@@ -307,7 +307,7 @@ function dedupe(values) {
|
|
|
307
307
|
return [...new Set(values)];
|
|
308
308
|
}
|
|
309
309
|
function renderSkillCommand(command, agent) {
|
|
310
|
-
const normalized =
|
|
310
|
+
const normalized = assertKnownAgentTarget(agent);
|
|
311
311
|
const agentFlag = normalized === AUTO_AGENT ? "" : `--agent '${normalized}'`;
|
|
312
312
|
return command.replaceAll("{agent_flag}", agentFlag).replaceAll("{agent}", normalized);
|
|
313
313
|
}
|
|
@@ -352,7 +352,7 @@ function splitCommand(command) {
|
|
|
352
352
|
function normalizeCapabilityState(value) {
|
|
353
353
|
const record = typeof value === "object" && value !== null ? value : {};
|
|
354
354
|
return {
|
|
355
|
-
agent:
|
|
355
|
+
agent: assertKnownAgentTarget(typeof record.agent === "string" ? record.agent : undefined),
|
|
356
356
|
preset: typeof record.preset === "string" ? record.preset : "default",
|
|
357
357
|
scope: "project-local",
|
|
358
358
|
mcp_servers: Array.isArray(record.mcp_servers)
|
|
@@ -397,12 +397,8 @@ async function removeSkillsFromLock(root, skills) {
|
|
|
397
397
|
await writeFile(path, `${JSON.stringify(record, null, 2)}\n`, "utf8");
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
|
-
function normalizeAgent(agent) {
|
|
401
|
-
const value = agent?.trim();
|
|
402
|
-
return value ? value : DEFAULT_AGENT;
|
|
403
|
-
}
|
|
404
400
|
function mcpSnippetFileName(agent) {
|
|
405
|
-
const normalized =
|
|
401
|
+
const normalized = normalizeAgentTarget(agent);
|
|
406
402
|
return normalized === DEFAULT_AGENT || normalized === AUTO_AGENT ? "mcp.json" : `${normalized}-mcp.json`;
|
|
407
403
|
}
|
|
408
404
|
async function removeInactiveMcpSnippets(outputDir, activeFile) {
|
package/dist/src/cli.d.ts
CHANGED
package/dist/src/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ import { disableMcpServers, doctorMcpServers, enableMcpServers, DEFAULT_AGENT, i
|
|
|
5
5
|
import { createProject, doctorProject, renameProject } from "./project.js";
|
|
6
6
|
import { askCreateOptions } from "./prompts.js";
|
|
7
7
|
import { AGENT_STACK, presetMcpServers } from "./stack.js";
|
|
8
|
+
import { formatAgentAliasLines, formatAgentTargetList, formatSupportedAgentTargetLines } from "./agents.js";
|
|
8
9
|
import { packageify, slugify, titleFromSlug } from "./names.js";
|
|
9
10
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
10
11
|
const packageVersion = readPackageVersion();
|
|
@@ -16,8 +17,8 @@ const MCP_FLAGS = flagSchema(["help"], ["root", "agent"]);
|
|
|
16
17
|
export async function main(argv = process.argv.slice(2), mode = "create") {
|
|
17
18
|
try {
|
|
18
19
|
if (mode === "create")
|
|
19
|
-
return createMain(argv);
|
|
20
|
-
return lifecycleMain(argv);
|
|
20
|
+
return await createMain(argv);
|
|
21
|
+
return await lifecycleMain(argv);
|
|
21
22
|
}
|
|
22
23
|
catch (error) {
|
|
23
24
|
console.error(error instanceof Error ? error.message : String(error));
|
|
@@ -61,7 +62,7 @@ async function createMain(argv) {
|
|
|
61
62
|
: undefined;
|
|
62
63
|
const installMcpToolsLock = flagBool(parsed.flags, "install-mcp-tools") ? true : undefined;
|
|
63
64
|
const answers = interactive
|
|
64
|
-
? await
|
|
65
|
+
? await askInteractiveCreateOptions(defaults, {
|
|
65
66
|
installSkills: installSkillsLock,
|
|
66
67
|
installMcpTools: installMcpToolsLock
|
|
67
68
|
})
|
|
@@ -83,6 +84,10 @@ async function createMain(argv) {
|
|
|
83
84
|
console.log("Next: cd into the project and run `npx academic-research doctor`.");
|
|
84
85
|
return 0;
|
|
85
86
|
}
|
|
87
|
+
async function askInteractiveCreateOptions(defaults, locks) {
|
|
88
|
+
console.log(formatInteractiveCreateGuide());
|
|
89
|
+
return askCreateOptions(defaults, locks);
|
|
90
|
+
}
|
|
86
91
|
async function lifecycleMain(argv) {
|
|
87
92
|
const command = argv[0] ?? "help";
|
|
88
93
|
if (command === "--help" || command === "-h") {
|
|
@@ -97,6 +102,8 @@ async function lifecycleMain(argv) {
|
|
|
97
102
|
return doctorCommand(argv.slice(1));
|
|
98
103
|
if (command === "rename")
|
|
99
104
|
return renameCommand(argv.slice(1));
|
|
105
|
+
if (command === "agents")
|
|
106
|
+
return agentsCommand(argv.slice(1));
|
|
100
107
|
if (command === "skills")
|
|
101
108
|
return skillsCommand(argv.slice(1));
|
|
102
109
|
if (command === "mcp")
|
|
@@ -133,6 +140,21 @@ async function renameCommand(argv) {
|
|
|
133
140
|
console.log(`Renamed project to ${result.slug}`);
|
|
134
141
|
return 0;
|
|
135
142
|
}
|
|
143
|
+
async function agentsCommand(argv) {
|
|
144
|
+
const subcommand = argv[0] ?? "list";
|
|
145
|
+
const parsed = parseFlags(argv.slice(1), ROOT_FLAGS);
|
|
146
|
+
if (subcommand === "help" || subcommand === "--help" || subcommand === "-h" || flagBool(parsed.flags, "help")) {
|
|
147
|
+
printAgentsHelp();
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
if (subcommand === "list") {
|
|
151
|
+
assertOnlyOptions(parsed.flags, "agents list", []);
|
|
152
|
+
assertNoArguments(parsed.positionals, "agents list");
|
|
153
|
+
process.stdout.write(formatAgentTargetList());
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
throw new Error(`unknown agents command: ${subcommand}`);
|
|
157
|
+
}
|
|
136
158
|
async function skillsCommand(argv) {
|
|
137
159
|
const subcommand = argv[0] ?? "list";
|
|
138
160
|
const parsed = parseFlags(argv.slice(1), SKILLS_FLAGS);
|
|
@@ -388,6 +410,33 @@ function mcpInstallMode(installCommand, runtimeCommand) {
|
|
|
388
410
|
return installCommand;
|
|
389
411
|
return runtimeCommand ? "runtime-only" : "manual";
|
|
390
412
|
}
|
|
413
|
+
export function formatInteractiveCreateGuide() {
|
|
414
|
+
const presetLines = Object.entries(AGENT_STACK.presets).map(([name, preset]) => ` ${name.padEnd(10)} ${preset.description}`);
|
|
415
|
+
return [
|
|
416
|
+
"Setup choices:",
|
|
417
|
+
"",
|
|
418
|
+
"Capability presets:",
|
|
419
|
+
...presetLines,
|
|
420
|
+
"",
|
|
421
|
+
"Agent target:",
|
|
422
|
+
" universal Recommended. One shared project-local .agents/skills copy.",
|
|
423
|
+
" auto Let the skills CLI detect installed agents; may create multiple agent-specific copies.",
|
|
424
|
+
" <id> Any supported skills.sh agent id.",
|
|
425
|
+
"",
|
|
426
|
+
"Supported specific agent ids:",
|
|
427
|
+
...formatSupportedAgentTargetLines(),
|
|
428
|
+
"",
|
|
429
|
+
"Aliases:",
|
|
430
|
+
...formatAgentAliasLines(),
|
|
431
|
+
"",
|
|
432
|
+
"Skill and MCP behavior:",
|
|
433
|
+
" Skills are copied into the project, not installed globally.",
|
|
434
|
+
" MCP records are written into configs/capabilities.yaml and docs/agent/generated/.",
|
|
435
|
+
" MCP installers are optional and run only finite installer commands.",
|
|
436
|
+
" runtime-only MCP servers are configured for the MCP client but have no install step.",
|
|
437
|
+
""
|
|
438
|
+
].join("\n");
|
|
439
|
+
}
|
|
391
440
|
function printCreateHelp() {
|
|
392
441
|
console.log([
|
|
393
442
|
"Usage: create-academic-research <project-name> [options]",
|
|
@@ -401,7 +450,7 @@ function printCreateHelp() {
|
|
|
401
450
|
" --package <name> Python package name. Default: normalized project name.",
|
|
402
451
|
" --preset <name> Capability preset: minimal, default, enhanced, literature, writing, full.",
|
|
403
452
|
" --profile <name> Project profile metadata. Default: academic-general.",
|
|
404
|
-
" --agent <
|
|
453
|
+
" --agent <id> Agent target: universal, auto, or a supported skills.sh id.",
|
|
405
454
|
" --install-skills Install project-local skills without prompting.",
|
|
406
455
|
" --no-install-skills Skip project-local skill installation.",
|
|
407
456
|
" --install-mcp-tools Run finite external MCP install commands after creation.",
|
|
@@ -420,7 +469,7 @@ function printMissingTargetHelp() {
|
|
|
420
469
|
}
|
|
421
470
|
function printLifecycleHelp() {
|
|
422
471
|
console.log([
|
|
423
|
-
"Usage: academic-research <doctor|rename|skills|mcp>",
|
|
472
|
+
"Usage: academic-research <doctor|rename|agents|skills|mcp>",
|
|
424
473
|
"",
|
|
425
474
|
"Manage a generated academic research repository after creation.",
|
|
426
475
|
"",
|
|
@@ -429,6 +478,21 @@ function printLifecycleHelp() {
|
|
|
429
478
|
" -v, --version Show package version."
|
|
430
479
|
].join("\n"));
|
|
431
480
|
}
|
|
481
|
+
function printAgentsHelp() {
|
|
482
|
+
console.log([
|
|
483
|
+
"Usage: academic-research agents <list>",
|
|
484
|
+
"",
|
|
485
|
+
"List supported project-local agent targets.",
|
|
486
|
+
"",
|
|
487
|
+
"Targets:",
|
|
488
|
+
" universal Recommended shared project-local .agents/skills copy.",
|
|
489
|
+
" auto Let the skills CLI detect installed agents.",
|
|
490
|
+
" <id> A supported skills.sh agent id.",
|
|
491
|
+
"",
|
|
492
|
+
"Options:",
|
|
493
|
+
" -h, --help Show this help."
|
|
494
|
+
].join("\n"));
|
|
495
|
+
}
|
|
432
496
|
function printSkillsHelp() {
|
|
433
497
|
console.log([
|
|
434
498
|
"Usage: academic-research skills <list|status|presets|install|remove|uninstall|update> [options]",
|
|
@@ -438,7 +502,7 @@ function printSkillsHelp() {
|
|
|
438
502
|
"Options:",
|
|
439
503
|
" --root <path> Project root for list, status, install, remove, uninstall, update.",
|
|
440
504
|
" --preset <name> Capability preset for install.",
|
|
441
|
-
" --agent <
|
|
505
|
+
" --agent <id> Agent selector for install. Default: project capability agent.",
|
|
442
506
|
" -h, --help Show this help."
|
|
443
507
|
].join("\n"));
|
|
444
508
|
}
|
|
@@ -450,7 +514,7 @@ function printMcpHelp() {
|
|
|
450
514
|
"",
|
|
451
515
|
"Options:",
|
|
452
516
|
" --root <path> Project root for project-state commands.",
|
|
453
|
-
" --agent <
|
|
517
|
+
" --agent <id> Agent for enable/disable generated snippets.",
|
|
454
518
|
" -h, --help Show this help."
|
|
455
519
|
].join("\n"));
|
|
456
520
|
}
|
package/dist/src/project.js
CHANGED
|
@@ -3,6 +3,7 @@ import { basename, dirname, join, resolve } from "node:path";
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import YAML from "yaml";
|
|
5
5
|
import { DEFAULT_AGENT, initializeCapabilities, installSkills } from "./capabilities.js";
|
|
6
|
+
import { assertKnownAgentTarget } from "./agents.js";
|
|
6
7
|
import { copyDirectory, exists, isNonEmptyDirectory, movePath, readJson, writeJson } from "./files.js";
|
|
7
8
|
import { packageify, slugify, titleFromSlug } from "./names.js";
|
|
8
9
|
import { AGENT_STACK } from "./stack.js";
|
|
@@ -90,9 +91,9 @@ export async function createProject(options) {
|
|
|
90
91
|
const slug = slugify(options.slug ?? title);
|
|
91
92
|
const packageName = packageify(options.packageName ?? slug);
|
|
92
93
|
const preset = options.preset ?? "default";
|
|
93
|
-
const agent = options.agent ?? DEFAULT_AGENT;
|
|
94
|
+
const agent = assertKnownAgentTarget(options.agent ?? DEFAULT_AGENT);
|
|
94
95
|
if (!AGENT_STACK.presets[preset]) {
|
|
95
|
-
throw new Error(`unknown capability preset: ${preset}`);
|
|
96
|
+
throw new Error(`unknown capability preset: ${preset}. Expected one of: ${Object.keys(AGENT_STACK.presets).join(", ")}`);
|
|
96
97
|
}
|
|
97
98
|
await mkdir(dirname(target), { recursive: true });
|
|
98
99
|
await copyDirectory(templateRoot, target);
|
|
@@ -205,7 +206,7 @@ async function writeGeneratedPackageJson(root, { slug }) {
|
|
|
205
206
|
const path = join(root, "package.json");
|
|
206
207
|
const data = await readJson(path);
|
|
207
208
|
const existingSpec = data.devDependencies?.["create-academic-research"];
|
|
208
|
-
const packageSpec = process.env.CREATE_ACADEMIC_RESEARCH_PACKAGE_SPEC ?? existingSpec ?? "
|
|
209
|
+
const packageSpec = process.env.CREATE_ACADEMIC_RESEARCH_PACKAGE_SPEC ?? existingSpec ?? "0.1.5";
|
|
209
210
|
data.name = slug;
|
|
210
211
|
data.devDependencies = {
|
|
211
212
|
...(data.devDependencies ?? {}),
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -53,6 +53,7 @@ Project-local skills and MCP records are managed with:
|
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
55
|
npx academic-research skills presets
|
|
56
|
+
npx academic-research agents list
|
|
56
57
|
npx academic-research skills install --preset default
|
|
57
58
|
npx academic-research skills install --preset enhanced
|
|
58
59
|
npx academic-research skills list
|