@orchestra-research/ai-research-skills 1.0.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 ADDED
@@ -0,0 +1,97 @@
1
+ # @orchestra-research/ai-research-skills
2
+
3
+ Install AI research engineering skills to your coding agents (Claude Code, Cursor, Gemini CLI, and more).
4
+
5
+ ```bash
6
+ npx @orchestra-research/ai-research-skills
7
+ ```
8
+
9
+ ## Features
10
+
11
+ - **82 skills** across 20 categories for AI research engineering
12
+ - **Auto-detects** installed coding agents
13
+ - **Interactive installer** with guided experience
14
+ - **One canonical copy** with symlinks to all agents
15
+ - **Works with 7 agents**: Claude Code, Cursor, Codex, Windsurf, Gemini CLI, Kilo Code, Qwen Code
16
+
17
+ ## Quick Start
18
+
19
+ Run the interactive installer:
20
+
21
+ ```bash
22
+ npx @orchestra-research/ai-research-skills
23
+ ```
24
+
25
+ This will:
26
+ 1. Detect your installed coding agents
27
+ 2. Let you choose what to install (everything, categories, or quick start bundle)
28
+ 3. Download skills from GitHub
29
+ 4. Create symlinks to each agent's skills directory
30
+
31
+ ## Commands
32
+
33
+ ```bash
34
+ # Interactive mode (recommended)
35
+ npx @orchestra-research/ai-research-skills
36
+
37
+ # Install everything
38
+ npx @orchestra-research/ai-research-skills install --all
39
+
40
+ # Install a specific category
41
+ npx @orchestra-research/ai-research-skills install post-training
42
+
43
+ # List installed skills
44
+ npx @orchestra-research/ai-research-skills list
45
+
46
+ # Update all skills
47
+ npx @orchestra-research/ai-research-skills update
48
+ ```
49
+
50
+ ## Categories
51
+
52
+ | Category | Skills | Description |
53
+ |----------|--------|-------------|
54
+ | Model Architecture | 6 | LitGPT, Mamba, TorchTitan, Megatron... |
55
+ | Post-Training | 8 | GRPO, verl, slime, miles, torchforge... |
56
+ | Fine-Tuning | 5 | Axolotl, Unsloth, PEFT, Torchtune... |
57
+ | Distributed Training | 6 | DeepSpeed, FSDP, Megatron... |
58
+ | Inference Serving | 4 | vLLM, TensorRT-LLM, SGLang... |
59
+ | Optimization | 6 | Flash Attention, GPTQ, AWQ... |
60
+ | And 14 more... | | |
61
+
62
+ ## How It Works
63
+
64
+ 1. **Canonical Storage**: Skills are stored once at `~/.agents/skills/`
65
+ 2. **Symlinks**: Each agent gets symlinks pointing to the canonical copy
66
+ 3. **Auto-activation**: Skills activate when you discuss relevant topics
67
+
68
+ ```
69
+ ~/.agents/skills/ # Single source of truth
70
+ ├── 06-post-training/
71
+ │ ├── verl/
72
+ │ └── grpo-rl-training/
73
+ └── ...
74
+
75
+ ~/.claude/skills/ # Symlinks for Claude Code
76
+ ├── verl → ~/.agents/skills/.../verl
77
+ └── grpo-rl-training → ...
78
+
79
+ ~/.cursor/skills/ # Symlinks for Cursor
80
+ └── (same links)
81
+ ```
82
+
83
+ ## Supported Agents
84
+
85
+ | Agent | Config Directory |
86
+ |-------|-----------------|
87
+ | Claude Code | `~/.claude` |
88
+ | Cursor | `~/.cursor` |
89
+ | Codex (OpenAI) | `~/.codex` |
90
+ | Windsurf | `~/.windsurf` |
91
+ | Gemini CLI | `~/.gemini` |
92
+ | Kilo Code | `~/.kilocode` |
93
+ | Qwen Code | `~/.qwen` |
94
+
95
+ ## License
96
+
97
+ MIT - Orchestra Research
package/bin/cli.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { main } from '../src/index.js';
4
+
5
+ main().catch((error) => {
6
+ console.error('Error:', error.message);
7
+ process.exit(1);
8
+ });
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@orchestra-research/ai-research-skills",
3
+ "version": "1.0.0",
4
+ "description": "Install AI research engineering skills to your coding agents (Claude Code, Cursor, Gemini CLI, and more)",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "ai-research-skills": "./bin/cli.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "start": "node bin/cli.js",
12
+ "test": "node --test"
13
+ },
14
+ "keywords": [
15
+ "ai",
16
+ "research",
17
+ "skills",
18
+ "claude",
19
+ "cursor",
20
+ "gemini",
21
+ "codex",
22
+ "windsurf",
23
+ "llm",
24
+ "machine-learning",
25
+ "deep-learning",
26
+ "cli"
27
+ ],
28
+ "author": "Orchestra Research",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/orchestra-research/ai-research-skills.git"
33
+ },
34
+ "homepage": "https://github.com/orchestra-research/ai-research-skills",
35
+ "bugs": {
36
+ "url": "https://github.com/orchestra-research/ai-research-skills/issues"
37
+ },
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ },
41
+ "dependencies": {
42
+ "chalk": "^5.3.0",
43
+ "inquirer": "^9.2.12",
44
+ "ora": "^8.0.1"
45
+ }
46
+ }
package/src/agents.js ADDED
@@ -0,0 +1,81 @@
1
+ import { existsSync } from 'fs';
2
+ import { homedir } from 'os';
3
+ import { join } from 'path';
4
+
5
+ /**
6
+ * Supported coding agents with their global config directories and skills paths
7
+ * All agents now support ~/.{agent}/skills/ format
8
+ */
9
+ export const SUPPORTED_AGENTS = [
10
+ {
11
+ id: 'claude',
12
+ name: 'Claude Code',
13
+ configDir: '.claude',
14
+ skillsDir: 'skills',
15
+ },
16
+ {
17
+ id: 'cursor',
18
+ name: 'Cursor',
19
+ configDir: '.cursor',
20
+ skillsDir: 'skills',
21
+ },
22
+ {
23
+ id: 'codex',
24
+ name: 'Codex',
25
+ configDir: '.codex',
26
+ skillsDir: 'skills',
27
+ },
28
+ {
29
+ id: 'gemini',
30
+ name: 'Gemini CLI',
31
+ configDir: '.gemini',
32
+ skillsDir: 'skills',
33
+ },
34
+ {
35
+ id: 'qwen',
36
+ name: 'Qwen Code',
37
+ configDir: '.qwen',
38
+ skillsDir: 'skills',
39
+ },
40
+ ];
41
+
42
+ /**
43
+ * Detect which coding agents are installed on the system
44
+ * @returns {Array} List of detected agents with their paths
45
+ */
46
+ export function detectAgents() {
47
+ const home = homedir();
48
+ const detected = [];
49
+
50
+ for (const agent of SUPPORTED_AGENTS) {
51
+ const configPath = join(home, agent.configDir);
52
+
53
+ if (existsSync(configPath)) {
54
+ detected.push({
55
+ ...agent,
56
+ path: `~/${agent.configDir}`,
57
+ fullPath: configPath,
58
+ skillsPath: join(configPath, agent.skillsDir),
59
+ });
60
+ }
61
+ }
62
+
63
+ return detected;
64
+ }
65
+
66
+ /**
67
+ * Get agent by ID
68
+ * @param {string} id Agent ID
69
+ * @returns {Object|null} Agent configuration or null
70
+ */
71
+ export function getAgentById(id) {
72
+ return SUPPORTED_AGENTS.find(agent => agent.id === id) || null;
73
+ }
74
+
75
+ /**
76
+ * Get all supported agent IDs
77
+ * @returns {Array<string>} List of agent IDs
78
+ */
79
+ export function getSupportedAgentIds() {
80
+ return SUPPORTED_AGENTS.map(agent => agent.id);
81
+ }
package/src/ascii.js ADDED
@@ -0,0 +1,126 @@
1
+ import chalk from 'chalk';
2
+
3
+ // Clean capital ORCHESTRA
4
+ const logo = `
5
+
6
+ ██████╗ ██████╗ ██████╗ ██╗ ██╗ ███████╗ ███████╗ ████████╗ ██████╗ █████╗
7
+ ██╔═══██╗██╔══██╗██╔════╝ ██║ ██║ ██╔════╝ ██╔════╝ ╚══██╔══╝ ██╔══██╗ ██╔══██╗
8
+ ██║ ██║██████╔╝██║ ███████║ █████╗ ███████╗ ██║ ██████╔╝ ███████║
9
+ ██║ ██║██╔══██╗██║ ██╔══██║ ██╔══╝ ╚════██║ ██║ ██╔══██╗ ██╔══██║
10
+ ╚██████╔╝██║ ██║╚██████╗ ██║ ██║ ███████╗ ███████║ ██║ ██║ ██║ ██║ ██║
11
+ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
12
+
13
+ `;
14
+
15
+ /**
16
+ * Welcome screen
17
+ */
18
+ export function showWelcome(skillCount = 82, categoryCount = 20, agentCount = 5) {
19
+ console.clear();
20
+ console.log(chalk.white(logo));
21
+ console.log();
22
+ console.log(chalk.bold.white(' AI Research Skills'));
23
+ console.log();
24
+ console.log();
25
+ console.log(chalk.dim(' Expert-level knowledge for AI research engineering'));
26
+ console.log();
27
+ console.log();
28
+ console.log(` ${skillCount} skills · ${categoryCount} categories · ${agentCount} agents`);
29
+ console.log();
30
+ console.log();
31
+ }
32
+
33
+ /**
34
+ * Agents detected screen
35
+ */
36
+ export function showAgentsDetected(agents) {
37
+ console.clear();
38
+ console.log(chalk.white(logo));
39
+ console.log();
40
+ console.log(chalk.bold.white(' AI Research Skills'));
41
+ console.log();
42
+ console.log();
43
+ console.log(chalk.green(` ✓ Found ${agents.length} coding agent${agents.length !== 1 ? 's' : ''}`));
44
+ console.log();
45
+
46
+ for (const agent of agents) {
47
+ console.log(` ${chalk.green('●')} ${chalk.white(agent.name.padEnd(14))} ${chalk.dim(agent.path)}`);
48
+ }
49
+
50
+ console.log();
51
+ console.log();
52
+ }
53
+
54
+ /**
55
+ * Menu header for inner screens
56
+ */
57
+ export function showMenuHeader() {
58
+ console.clear();
59
+ console.log();
60
+ console.log(chalk.dim(' ────────────────────────────────────────────────────────────'));
61
+ console.log(chalk.white(' ORCHESTRA · AI Research Skills'));
62
+ console.log(chalk.dim(' ────────────────────────────────────────────────────────────'));
63
+ console.log();
64
+ }
65
+
66
+ /**
67
+ * Success screen
68
+ */
69
+ export function showSuccess(skillCount, agents) {
70
+ console.clear();
71
+ console.log();
72
+ console.log();
73
+ console.log(chalk.green.bold(' ✓ Installation Complete'));
74
+ console.log();
75
+ console.log();
76
+ console.log(` Installed ${chalk.white(skillCount)} skills to ${chalk.white(agents.length)} agent${agents.length !== 1 ? 's' : ''}`);
77
+ console.log();
78
+ console.log(chalk.dim(' Your skills are now active and will appear when relevant.'));
79
+ console.log();
80
+ console.log();
81
+ console.log(chalk.dim(' ────────────────────────────────────────────────────────────'));
82
+ console.log();
83
+ console.log(chalk.white(' Examples:'));
84
+ console.log();
85
+ console.log(chalk.dim(' → "Help me set up GRPO training with verl"'));
86
+ console.log(chalk.dim(' → "How do I serve a model with vLLM?"'));
87
+ console.log(chalk.dim(' → "Write a NeurIPS paper introduction"'));
88
+ console.log();
89
+ console.log(chalk.dim(' ────────────────────────────────────────────────────────────'));
90
+ console.log();
91
+ console.log(chalk.white(' Commands:'));
92
+ console.log();
93
+ console.log(` ${chalk.dim('$')} ${chalk.cyan('npx @orchestra-research/ai-research-skills')}`);
94
+ console.log(` ${chalk.dim('$')} ${chalk.cyan('npx @orchestra-research/ai-research-skills list')}`);
95
+ console.log(` ${chalk.dim('$')} ${chalk.cyan('npx @orchestra-research/ai-research-skills update')}`);
96
+ console.log();
97
+ console.log(chalk.dim(' ────────────────────────────────────────────────────────────'));
98
+ console.log();
99
+ console.log(chalk.dim(' github.com/orchestra-research/ai-research-skills'));
100
+ console.log();
101
+ }
102
+
103
+ /**
104
+ * No agents found screen
105
+ */
106
+ export function showNoAgents() {
107
+ console.clear();
108
+ console.log(chalk.white(logo));
109
+ console.log();
110
+ console.log(chalk.bold.white(' AI Research Skills'));
111
+ console.log();
112
+ console.log();
113
+ console.log(chalk.yellow(' ⚠ No coding agents detected'));
114
+ console.log();
115
+ console.log(chalk.dim(' Install one of these supported agents:'));
116
+ console.log();
117
+ console.log(' ○ Claude Code');
118
+ console.log(' ○ Cursor');
119
+ console.log(' ○ Codex (OpenAI)');
120
+ console.log(' ○ Windsurf');
121
+ console.log(' ○ Gemini CLI');
122
+ console.log(' ○ Kilo Code');
123
+ console.log(' ○ Qwen Code');
124
+ console.log();
125
+ console.log();
126
+ }
package/src/index.js ADDED
@@ -0,0 +1,282 @@
1
+ import ora from 'ora';
2
+ import chalk from 'chalk';
3
+
4
+ import { detectAgents } from './agents.js';
5
+ import { showWelcome, showAgentsDetected, showSuccess, showNoAgents, showMenuHeader } from './ascii.js';
6
+ import {
7
+ askInstallChoice,
8
+ askCategories,
9
+ askIndividualSkills,
10
+ askConfirmation,
11
+ askMainMenuAction,
12
+ askSelectAgents,
13
+ askAfterAction,
14
+ parseArgs,
15
+ CATEGORIES,
16
+ INDIVIDUAL_SKILLS,
17
+ QUICK_START_SKILLS,
18
+ getTotalSkillCount,
19
+ } from './prompts.js';
20
+ import { installSkills, installSpecificSkills, listInstalledSkills, getAllCategoryIds } from './installer.js';
21
+
22
+ /**
23
+ * Sleep utility
24
+ */
25
+ function sleep(ms) {
26
+ return new Promise(resolve => setTimeout(resolve, ms));
27
+ }
28
+
29
+ /**
30
+ * Interactive flow - the main guided experience with navigation
31
+ */
32
+ async function interactiveFlow() {
33
+ let agents = [];
34
+
35
+ // STEP 1: Welcome + Agent Detection
36
+ showWelcome();
37
+ const spinner = ora({
38
+ text: chalk.cyan('Detecting coding agents...'),
39
+ spinner: 'dots',
40
+ prefixText: ' ',
41
+ }).start();
42
+
43
+ await sleep(1200);
44
+ agents = detectAgents();
45
+ spinner.stop();
46
+
47
+ if (agents.length === 0) {
48
+ showNoAgents();
49
+ console.log(chalk.yellow(' Please install a supported coding agent first.'));
50
+ console.log();
51
+ return;
52
+ }
53
+
54
+ // STEP 2: Show detected agents + main menu
55
+ step2_menu:
56
+ while (true) {
57
+ showAgentsDetected(agents);
58
+ const menuAction = await askMainMenuAction();
59
+
60
+ if (menuAction === 'exit') {
61
+ console.log(chalk.dim(' Goodbye!'));
62
+ console.log();
63
+ return;
64
+ }
65
+
66
+ if (menuAction === 'view') {
67
+ // View installed skills
68
+ showMenuHeader();
69
+ listInstalledSkills();
70
+ const afterView = await askAfterAction();
71
+ if (afterView === 'exit') {
72
+ console.log(chalk.dim(' Goodbye!'));
73
+ console.log();
74
+ return;
75
+ }
76
+ continue step2_menu;
77
+ }
78
+
79
+ if (menuAction === 'update') {
80
+ // Update all skills
81
+ showMenuHeader();
82
+ console.log(chalk.cyan(' Updating all skills...'));
83
+ console.log();
84
+ const categories = getAllCategoryIds();
85
+ await installSkills(categories, agents);
86
+ console.log();
87
+ console.log(chalk.green(' ✓ All skills updated!'));
88
+ const afterUpdate = await askAfterAction();
89
+ if (afterUpdate === 'exit') {
90
+ console.log(chalk.dim(' Goodbye!'));
91
+ console.log();
92
+ return;
93
+ }
94
+ continue step2_menu;
95
+ }
96
+
97
+ // STEP 3: Choose what to install (menuAction === 'install')
98
+ step3_choice:
99
+ while (true) {
100
+ showMenuHeader();
101
+ const choice = await askInstallChoice();
102
+
103
+ if (choice === 'back') {
104
+ continue step2_menu;
105
+ }
106
+
107
+ let categories = [];
108
+ let selectedSkills = [];
109
+ let skillCount = 0;
110
+ let installType = choice;
111
+
112
+ // Handle different choices
113
+ if (choice === 'everything') {
114
+ categories = getAllCategoryIds();
115
+ skillCount = getTotalSkillCount();
116
+ } else if (choice === 'quickstart') {
117
+ categories = [...new Set(QUICK_START_SKILLS.map(s => s.split('/')[0]))];
118
+ skillCount = QUICK_START_SKILLS.length;
119
+ } else if (choice === 'categories') {
120
+ // Category selection
121
+ step4_categories:
122
+ while (true) {
123
+ showMenuHeader();
124
+ const result = await askCategories();
125
+
126
+ if (result.action === 'back') {
127
+ continue step3_choice;
128
+ }
129
+ if (result.action === 'retry') {
130
+ continue step4_categories;
131
+ }
132
+
133
+ categories = result.categories;
134
+ skillCount = CATEGORIES
135
+ .filter(c => categories.includes(c.id))
136
+ .reduce((sum, c) => sum + c.skills, 0);
137
+ break;
138
+ }
139
+ } else if (choice === 'individual') {
140
+ // Individual skill selection
141
+ step4_individual:
142
+ while (true) {
143
+ showMenuHeader();
144
+ const result = await askIndividualSkills();
145
+
146
+ if (result.action === 'back') {
147
+ continue step3_choice;
148
+ }
149
+ if (result.action === 'retry') {
150
+ continue step4_individual;
151
+ }
152
+
153
+ selectedSkills = result.skills;
154
+ skillCount = selectedSkills.length;
155
+ break;
156
+ }
157
+ }
158
+
159
+ // STEP 5: Select agents + Confirmation
160
+ let targetAgents = agents;
161
+ step5_agents:
162
+ while (true) {
163
+ showMenuHeader();
164
+ const agentResult = await askSelectAgents(agents);
165
+
166
+ if (agentResult.action === 'back') {
167
+ continue step3_choice;
168
+ }
169
+ if (agentResult.action === 'retry') {
170
+ continue step5_agents;
171
+ }
172
+
173
+ targetAgents = agentResult.agents;
174
+
175
+ // STEP 6: Confirmation
176
+ showMenuHeader();
177
+ const confirmAction = await askConfirmation(skillCount, targetAgents, categories, selectedSkills, installType);
178
+
179
+ if (confirmAction === 'exit') {
180
+ console.log(chalk.dim(' Goodbye!'));
181
+ console.log();
182
+ return;
183
+ }
184
+ if (confirmAction === 'back') {
185
+ continue step5_agents;
186
+ }
187
+
188
+ break;
189
+ }
190
+
191
+ // STEP 7: Installation
192
+ console.log();
193
+ console.log(chalk.cyan(' Installing...'));
194
+ console.log();
195
+
196
+ let installedCount;
197
+ if (selectedSkills.length > 0) {
198
+ // Install specific skills
199
+ installedCount = await installSpecificSkills(selectedSkills, targetAgents);
200
+ } else {
201
+ // Install by categories
202
+ installedCount = await installSkills(categories, targetAgents);
203
+ }
204
+
205
+ // STEP 8: Success!
206
+ await sleep(500);
207
+ showSuccess(installedCount, targetAgents);
208
+ return;
209
+ }
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Direct command mode (for power users)
215
+ */
216
+ async function commandMode(options) {
217
+ if (options.command === 'list') {
218
+ listInstalledSkills();
219
+ return;
220
+ }
221
+
222
+ if (options.command === 'update') {
223
+ console.log(chalk.cyan('Updating skills...'));
224
+ const agents = detectAgents();
225
+ if (agents.length === 0) {
226
+ console.log(chalk.yellow('No agents detected.'));
227
+ return;
228
+ }
229
+ const categories = getAllCategoryIds();
230
+ await installSkills(categories, agents);
231
+ console.log(chalk.green('✓ Skills updated!'));
232
+ return;
233
+ }
234
+
235
+ if (options.command === 'install' || options.all || options.category || options.skill) {
236
+ const agents = detectAgents();
237
+ if (agents.length === 0) {
238
+ console.log(chalk.yellow('No agents detected.'));
239
+ return;
240
+ }
241
+
242
+ let categories;
243
+ if (options.all) {
244
+ categories = getAllCategoryIds();
245
+ } else if (options.category) {
246
+ categories = [options.category];
247
+ } else if (options.skill) {
248
+ const matchingCategory = CATEGORIES.find(c =>
249
+ c.id.includes(options.skill) || c.name.toLowerCase().includes(options.skill.toLowerCase())
250
+ );
251
+ if (matchingCategory) {
252
+ categories = [matchingCategory.id];
253
+ } else {
254
+ console.log(chalk.yellow(`Category or skill "${options.skill}" not found.`));
255
+ return;
256
+ }
257
+ } else {
258
+ categories = getAllCategoryIds();
259
+ }
260
+
261
+ console.log(chalk.cyan('Installing skills...'));
262
+ await installSkills(categories, agents);
263
+ console.log(chalk.green('✓ Done!'));
264
+ return;
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Main entry point
270
+ */
271
+ export async function main() {
272
+ const args = process.argv.slice(2);
273
+ const options = parseArgs(args);
274
+
275
+ // If any command-line options provided, use command mode
276
+ if (options.command || options.all || options.category || options.skill) {
277
+ await commandMode(options);
278
+ } else {
279
+ // Otherwise, use interactive flow
280
+ await interactiveFlow();
281
+ }
282
+ }