ai-devx 1.0.4 → 1.0.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/bin/cli.js CHANGED
@@ -6,6 +6,7 @@ const pkg = require("../package.json");
6
6
  const initCommand = require("../src/commands/init");
7
7
  const updateCommand = require("../src/commands/update");
8
8
  const statusCommand = require("../src/commands/status");
9
+ const shellCommand = require("../src/commands/shell");
9
10
 
10
11
  console.log(
11
12
  chalk.cyan.bold(`
@@ -59,6 +60,13 @@ program
59
60
  .option("-p, --path <path>", "Check specific directory", process.cwd())
60
61
  .action(statusCommand);
61
62
 
63
+ program
64
+ .command("shell [path]")
65
+ .description(
66
+ "Start interactive shell to browse skills, agents, and workflows",
67
+ )
68
+ .action(shellCommand);
69
+
62
70
  program.on("--help", () => {
63
71
  console.log("");
64
72
  console.log(chalk.bold("Examples:"));
@@ -77,6 +85,9 @@ program.on("--help", () => {
77
85
  console.log(
78
86
  " $ ai-devx init --assistant claude,gemini # Install with both assistants",
79
87
  );
88
+ console.log(
89
+ " $ ai-devx shell # Start interactive shell",
90
+ );
80
91
  console.log(" $ ai-devx update # Update templates");
81
92
  console.log(
82
93
  " $ ai-devx status # Check installation status",
@@ -84,6 +95,7 @@ program.on("--help", () => {
84
95
  console.log("");
85
96
  console.log(chalk.bold("Quick Start:"));
86
97
  console.log(" $ npx ai-devx init");
98
+ console.log(" $ npx ai-devx shell");
87
99
  console.log("");
88
100
  });
89
101
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-devx",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "AI Agent templates with Skills, Agents, and Workflows for enhanced coding assistance",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -0,0 +1,349 @@
1
+ const path = require("path");
2
+ const fs = require("fs-extra");
3
+ const chalk = require("chalk");
4
+ const readline = require("readline");
5
+
6
+ class InteractiveCLI {
7
+ constructor(agentPath) {
8
+ this.agentPath = agentPath;
9
+ this.workflows = [];
10
+ this.skills = [];
11
+ this.agents = [];
12
+ this.scripts = [];
13
+ this.rules = [];
14
+ this.shared = [];
15
+ this.workflowsPath = path.join(agentPath, "workflows");
16
+ this.skillsPath = path.join(agentPath, "skills");
17
+ this.agentsPath = path.join(agentPath, "agents");
18
+ this.scriptsPath = path.join(agentPath, "scripts");
19
+ this.rulesPath = path.join(agentPath, "rules");
20
+ this.sharedPath = path.join(agentPath, ".shared");
21
+ }
22
+
23
+ async loadResources() {
24
+ // Load workflows
25
+ if (await fs.pathExists(this.workflowsPath)) {
26
+ const files = await fs.readdir(this.workflowsPath);
27
+ this.workflows = files
28
+ .filter((f) => f.endsWith(".md"))
29
+ .map((f) => ({
30
+ name: `/${path.basename(f, ".md")}`,
31
+ file: f,
32
+ type: "workflow",
33
+ }));
34
+ }
35
+
36
+ // Load skills
37
+ if (await fs.pathExists(this.skillsPath)) {
38
+ const entries = await fs.readdir(this.skillsPath, {
39
+ withFileTypes: true,
40
+ });
41
+ this.skills = entries
42
+ .filter((e) => e.isDirectory())
43
+ .map((e) => ({
44
+ name: e.name,
45
+ path: path.join(this.skillsPath, e.name),
46
+ type: "skill",
47
+ }));
48
+ }
49
+
50
+ // Load agents
51
+ if (await fs.pathExists(this.agentsPath)) {
52
+ const files = await fs.readdir(this.agentsPath);
53
+ this.agents = files
54
+ .filter((f) => f.endsWith(".md"))
55
+ .map((f) => ({
56
+ name: `@${path.basename(f, ".md")}`,
57
+ file: f,
58
+ type: "agent",
59
+ }));
60
+ }
61
+
62
+ // Load scripts
63
+ if (await fs.pathExists(this.scriptsPath)) {
64
+ const files = await fs.readdir(this.scriptsPath);
65
+ this.scripts = files
66
+ .filter((f) => f.endsWith(".py"))
67
+ .map((f) => ({
68
+ name: f,
69
+ file: f,
70
+ type: "script",
71
+ }));
72
+ }
73
+
74
+ // Load rules
75
+ if (await fs.pathExists(this.rulesPath)) {
76
+ const files = await fs.readdir(this.rulesPath);
77
+ this.rules = files
78
+ .filter((f) => f.endsWith(".md"))
79
+ .map((f) => ({
80
+ name: path.basename(f, ".md"),
81
+ file: f,
82
+ type: "rule",
83
+ }));
84
+ }
85
+
86
+ // Load shared
87
+ if (await fs.pathExists(this.sharedPath)) {
88
+ const entries = await fs.readdir(this.sharedPath, {
89
+ withFileTypes: true,
90
+ });
91
+ this.shared = entries
92
+ .filter((e) => e.isDirectory())
93
+ .map((e) => ({
94
+ name: e.name,
95
+ path: path.join(this.sharedPath, e.name),
96
+ type: "shared",
97
+ }));
98
+ }
99
+ }
100
+
101
+ showHelp() {
102
+ console.log(chalk.bold("\nšŸ“š Available Commands:\n"));
103
+
104
+ console.log(chalk.yellow.bold("Slash Commands (Workflows):"));
105
+ this.workflows.forEach((w) => {
106
+ console.log(` ${chalk.cyan(w.name)} - Workflow command`);
107
+ });
108
+
109
+ console.log(chalk.yellow.bold("\nSkills:"));
110
+ this.skills.slice(0, 15).forEach((s) => {
111
+ console.log(` ${chalk.green(s.name)} - Domain knowledge module`);
112
+ });
113
+ if (this.skills.length > 15) {
114
+ console.log(` ${chalk.gray(`... and ${this.skills.length - 15} more`)}`);
115
+ }
116
+
117
+ console.log(chalk.yellow.bold("\nAgents:"));
118
+ this.agents.slice(0, 10).forEach((a) => {
119
+ console.log(` ${chalk.magenta(a.name)} - Specialist agent`);
120
+ });
121
+ if (this.agents.length > 10) {
122
+ console.log(` ${chalk.gray(`... and ${this.agents.length - 10} more`)}`);
123
+ }
124
+
125
+ console.log(chalk.yellow.bold("\nScripts:"));
126
+ this.scripts.slice(0, 8).forEach((s) => {
127
+ console.log(` ${chalk.blue(s.name)} - Automation script`);
128
+ });
129
+ if (this.scripts.length > 8) {
130
+ console.log(` ${chalk.gray(`... and ${this.scripts.length - 8} more`)}`);
131
+ }
132
+
133
+ console.log(chalk.yellow.bold("\nRules:"));
134
+ this.rules.forEach((r) => {
135
+ console.log(` ${chalk.red(r.name)} - Assistant rules`);
136
+ });
137
+
138
+ if (this.shared.length > 0) {
139
+ console.log(chalk.yellow.bold("\nShared Resources:"));
140
+ this.shared.forEach((s) => {
141
+ console.log(` ${chalk.gray(s.name)} - Shared utilities`);
142
+ });
143
+ }
144
+
145
+ console.log(chalk.yellow.bold("\nOther Commands:"));
146
+ console.log(` ${chalk.cyan("/help")} - Show this menu`);
147
+ console.log(` ${chalk.cyan("/exit")} - Exit interactive mode`);
148
+ console.log(` ${chalk.cyan("clear")} - Clear screen`);
149
+ console.log();
150
+ }
151
+
152
+ async executeWorkflow(workflowName, args = "") {
153
+ const workflow = this.workflows.find((w) => w.name === workflowName);
154
+ if (!workflow) {
155
+ console.log(chalk.red(`āŒ Workflow '${workflowName}' not found`));
156
+ return;
157
+ }
158
+
159
+ const workflowPath = path.join(this.workflowsPath, workflow.file);
160
+ try {
161
+ const content = await fs.readFile(workflowPath, "utf-8");
162
+ console.log(chalk.bold(`\nšŸ“„ Workflow: ${workflowName}\n`));
163
+
164
+ // Show first 50 lines or until first separator
165
+ const lines = content.split("\n");
166
+ const previewLines = [];
167
+ for (const line of lines) {
168
+ if (line.startsWith("---") && previewLines.length > 0) break;
169
+ previewLines.push(line);
170
+ if (previewLines.length >= 30) break;
171
+ }
172
+
173
+ console.log(previewLines.join("\n"));
174
+ console.log(chalk.gray("\n... (truncated)"));
175
+ console.log(chalk.yellow(`\nFull file: ${workflowPath}\n`));
176
+ } catch (error) {
177
+ console.log(chalk.red(`āŒ Error reading workflow: ${error.message}`));
178
+ }
179
+ }
180
+
181
+ async executeSkill(skillName) {
182
+ const skill = this.skills.find((s) => s.name === skillName);
183
+ if (!skill) {
184
+ console.log(chalk.red(`āŒ Skill '${skillName}' not found`));
185
+ return;
186
+ }
187
+
188
+ const skillMdPath = path.join(skill.path, "SKILL.md");
189
+ try {
190
+ if (await fs.pathExists(skillMdPath)) {
191
+ const content = await fs.readFile(skillMdPath, "utf-8");
192
+ console.log(chalk.bold(`\nšŸ“š Skill: ${skillName}\n`));
193
+
194
+ const lines = content.split("\n").slice(0, 40);
195
+ console.log(lines.join("\n"));
196
+ console.log(chalk.gray("\n... (truncated)"));
197
+ console.log(chalk.yellow(`\nFull file: ${skillMdPath}\n`));
198
+ } else {
199
+ console.log(chalk.bold(`\nšŸ“š Skill: ${skillName}\n`));
200
+ console.log(`Path: ${skill.path}`);
201
+
202
+ const files = await fs.readdir(skill.path);
203
+ console.log("\nContents:");
204
+ files.forEach((f) => console.log(` - ${f}`));
205
+ console.log();
206
+ }
207
+ } catch (error) {
208
+ console.log(chalk.red(`āŒ Error reading skill: ${error.message}`));
209
+ }
210
+ }
211
+
212
+ async executeAgent(agentName) {
213
+ const agent = this.agents.find((a) => a.name === agentName);
214
+ if (!agent) {
215
+ console.log(chalk.red(`āŒ Agent '${agentName}' not found`));
216
+ return;
217
+ }
218
+
219
+ const agentPath = path.join(this.agentsPath, agent.file);
220
+ try {
221
+ const content = await fs.readFile(agentPath, "utf-8");
222
+ console.log(chalk.bold(`\nšŸ¤– Agent: ${agentName}\n`));
223
+
224
+ const lines = content.split("\n").slice(0, 40);
225
+ console.log(lines.join("\n"));
226
+ console.log(chalk.gray("\n... (truncated)"));
227
+ console.log(chalk.yellow(`\nFull file: ${agentPath}\n`));
228
+ } catch (error) {
229
+ console.log(chalk.red(`āŒ Error reading agent: ${error.message}`));
230
+ }
231
+ }
232
+
233
+ async executeRule(ruleName) {
234
+ const rule = this.rules.find((r) => r.name === ruleName);
235
+ if (!rule) {
236
+ console.log(chalk.red(`āŒ Rule '${ruleName}' not found`));
237
+ return;
238
+ }
239
+
240
+ const rulePath = path.join(this.rulesPath, rule.file);
241
+ try {
242
+ const content = await fs.readFile(rulePath, "utf-8");
243
+ console.log(chalk.bold(`\nšŸ“œ Rule: ${ruleName}\n`));
244
+
245
+ const lines = content.split("\n").slice(0, 40);
246
+ console.log(lines.join("\n"));
247
+ console.log(chalk.gray("\n... (truncated)"));
248
+ console.log(chalk.yellow(`\nFull file: ${rulePath}\n`));
249
+ } catch (error) {
250
+ console.log(chalk.red(`āŒ Error reading rule: ${error.message}`));
251
+ }
252
+ }
253
+
254
+ async start() {
255
+ await this.loadResources();
256
+
257
+ console.log(
258
+ chalk.cyan.bold(`
259
+ ╔════════════════════════════════════════════════╗
260
+ ā•‘ šŸ¤– AI-DEVX Interactive Shell ā•‘
261
+ ā•‘ Type / to see all commands and resources ā•‘
262
+ ā•‘ Type /help for help or /exit to quit ā•‘
263
+ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
264
+ `),
265
+ );
266
+
267
+ const rl = readline.createInterface({
268
+ input: process.stdin,
269
+ output: process.stdout,
270
+ prompt: chalk.cyan("ai-devx> "),
271
+ });
272
+
273
+ rl.prompt();
274
+
275
+ rl.on("line", async (line) => {
276
+ const input = line.trim();
277
+
278
+ if (input === "/exit" || input === "exit" || input === "quit") {
279
+ console.log(chalk.yellow("šŸ‘‹ Goodbye!"));
280
+ rl.close();
281
+ return;
282
+ }
283
+
284
+ if (input === "" || input === "/") {
285
+ this.showHelp();
286
+ } else if (input === "/help" || input === "help") {
287
+ console.log(chalk.bold("\nšŸŽÆ Quick Guide:\n"));
288
+ console.log("Type any of the following:");
289
+ console.log(
290
+ ` ${chalk.cyan("/")} - Show all available commands and resources`,
291
+ );
292
+ console.log(
293
+ ` ${chalk.cyan("/<workflow>")} - View workflow details (e.g., /plan)`,
294
+ );
295
+ console.log(
296
+ ` ${chalk.cyan("@<agent>")} - View agent details (e.g., @orchestrator)`,
297
+ );
298
+ console.log(
299
+ ` ${chalk.cyan("<skill-name>")} - View skill details (e.g., clean-code)`,
300
+ );
301
+ console.log(
302
+ ` ${chalk.cyan("<rule-name>")} - View rule details (e.g., CLAUDE)`,
303
+ );
304
+ console.log(` ${chalk.cyan("clear")} - Clear the screen`);
305
+ console.log(` ${chalk.cyan("/exit")} - Exit interactive mode\n`);
306
+ } else if (input === "clear") {
307
+ console.clear();
308
+ } else if (input.startsWith("/")) {
309
+ // Workflow command
310
+ await this.executeWorkflow(input);
311
+ } else if (input.startsWith("@")) {
312
+ // Agent command
313
+ await this.executeAgent(input);
314
+ } else if (this.skills.find((s) => s.name === input)) {
315
+ // Skill command
316
+ await this.executeSkill(input);
317
+ } else if (this.rules.find((r) => r.name === input)) {
318
+ // Rule command
319
+ await this.executeRule(input);
320
+ } else {
321
+ console.log(chalk.yellow(`āš ļø Unknown command: ${input}`));
322
+ console.log(chalk.gray("Type / to see available commands\n"));
323
+ }
324
+
325
+ rl.prompt();
326
+ });
327
+
328
+ rl.on("close", () => {
329
+ console.log(chalk.yellow("\nšŸ‘‹ Goodbye!"));
330
+ process.exit(0);
331
+ });
332
+ }
333
+ }
334
+
335
+ async function shellCommand(targetPath) {
336
+ const cwd = targetPath || process.cwd();
337
+ const agentPath = path.join(path.resolve(cwd), ".agent");
338
+
339
+ if (!(await fs.pathExists(agentPath))) {
340
+ console.log(chalk.red(`āŒ AI-DEVX not installed in ${cwd}`));
341
+ console.log(chalk.yellow("Run: npx ai-devx init"));
342
+ process.exit(1);
343
+ }
344
+
345
+ const cli = new InteractiveCLI(agentPath);
346
+ await cli.start();
347
+ }
348
+
349
+ module.exports = shellCommand;