antikit 1.13.0 → 1.15.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 CHANGED
@@ -63,7 +63,7 @@ antikit list
63
63
  antikit ls -s <keyword>
64
64
 
65
65
  # Filter by source
66
- antikit ls --source official
66
+ antikit ls --source antiskills
67
67
  antikit ls --source claudekit
68
68
 
69
69
  # Text Mode (Non-interactive, good for scripting)
@@ -95,17 +95,36 @@ antikit install <skill-name> --force
95
95
  Keep your skills up-to-date with one command.
96
96
 
97
97
  ```bash
98
- # Upgrade all installed skills (Interactive confirmation)
98
+ # Interactive Mode (Default in TTY) - Select specific skills to upgrade
99
99
  antikit upgrade
100
+ # Select skills with checkbox, see version changes (local → remote)
100
101
  # Alias: antikit ug
101
102
 
103
+ # Explicit Interactive Mode
104
+ antikit upgrade -i
105
+ antikit upgrade --interactive
106
+
102
107
  # Upgrade a specific skill
103
108
  antikit upgrade <skill-name>
104
109
 
105
- # Upgrade all without confirmation (CI/Script mode)
110
+ # Auto-upgrade all (with confirmation)
111
+ antikit upgrade
112
+
113
+ # Auto-upgrade all without confirmation (CI/Script mode)
106
114
  antikit upgrade --yes
115
+ antikit upgrade -y
107
116
  ```
108
117
 
118
+ **Interactive Upgrade Features:**
119
+ - ✨ **Checkbox Selection** - Choose specific skills to upgrade
120
+ - 📊 **Version Display** - See current vs. latest version (e.g., `v1.0.0 → v1.2.0`)
121
+ - 🎯 **Smart Filtering** - Only upgradeable skills are selectable
122
+ - 🚦 **Visual Indicators**:
123
+ - `↑` Yellow - Update available
124
+ - `✓` Green - Already up-to-date (disabled)
125
+ - `✗` Red - Error/Cannot upgrade (disabled)
126
+
127
+
109
128
  **Manage Local Skills**
110
129
 
111
130
  ```bash
@@ -113,11 +132,30 @@ antikit upgrade --yes
113
132
  antikit local
114
133
  # Alias: antikit l
115
134
 
116
- # Remove a skill
135
+ # Remove a specific skill
117
136
  antikit remove <skill-name>
118
137
  # Alias: antikit rm <skill-name>
138
+
139
+ # Interactive Remove - Select multiple skills to remove
140
+ antikit remove
141
+ antikit remove -i
142
+ antikit remove --interactive
143
+
144
+ # Remove all skills (with confirmation)
145
+ antikit remove --all
146
+
147
+ # Remove all without confirmation (dangerous!)
148
+ antikit remove --all --yes
149
+ antikit remove -a -y
119
150
  ```
120
151
 
152
+ **Interactive Remove Features:**
153
+ - ✨ **Checkbox Selection** - Choose multiple skills to remove
154
+ - 📋 **Summary Preview** - See what will be removed before confirming
155
+ - 🚨 **Safety First** - Double confirmation with default=No
156
+ - ⚠️ **Warning Indicators** - Red text and warning icons for destructive operations
157
+
158
+
121
159
  ### 📡 Source Management
122
160
 
123
161
  You can fetch skills from multiple repositories, including monorepos with sub-directories.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antikit",
3
- "version": "1.13.0",
3
+ "version": "1.15.0",
4
4
  "description": "CLI tool to manage AI agent skills from Anti Gravity skills repository",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -66,4 +66,4 @@
66
66
  "prettier": "^3.7.4",
67
67
  "vitest": "^3.0.0"
68
68
  }
69
- }
69
+ }
@@ -1,7 +1,9 @@
1
1
  import chalk from 'chalk';
2
- import { removeLocalSkill, skillExists, findLocalSkillsDir } from '../utils/local.js';
2
+ import { checkbox, confirm } from '@inquirer/prompts';
3
+ import Table from 'cli-table3';
4
+ import { removeLocalSkill, skillExists, findLocalSkillsDir, getLocalSkills } from '../utils/local.js';
3
5
 
4
- export async function removeSkill(skillName) {
6
+ export async function removeSkill(skillName, options = {}) {
5
7
  const skillsDir = findLocalSkillsDir();
6
8
 
7
9
  if (!skillsDir) {
@@ -9,6 +11,179 @@ export async function removeSkill(skillName) {
9
11
  process.exit(1);
10
12
  }
11
13
 
14
+ // 1. Remove specific skill
15
+ if (skillName) {
16
+ await removeSingleSkill(skillName);
17
+ return;
18
+ }
19
+
20
+ // 2. Get all installed skills
21
+ const skills = getLocalSkills();
22
+
23
+ if (skills.length === 0) {
24
+ console.log(chalk.yellow('No skills installed.'));
25
+ return;
26
+ }
27
+
28
+ // 3. Check mode: interactive, all, or error
29
+ if (options.all) {
30
+ await removeAllSkills(skills, options.yes);
31
+ } else if (options.interactive || process.stdout.isTTY) {
32
+ await interactiveRemove(skills);
33
+ } else {
34
+ console.log(chalk.yellow('Please specify a skill name to remove.'));
35
+ console.log(chalk.dim('Usage:'));
36
+ console.log(chalk.dim(' antikit remove <skill-name> Remove specific skill'));
37
+ console.log(chalk.dim(' antikit remove -i Interactive mode'));
38
+ console.log(chalk.dim(' antikit remove --all Remove all skills'));
39
+ process.exit(1);
40
+ }
41
+ }
42
+
43
+ async function interactiveRemove(skills) {
44
+ // Sort skills alphabetically
45
+ skills.sort((a, b) => a.name.localeCompare(b.name));
46
+
47
+ console.log(chalk.bold(`\nSelect skills to remove (${skills.length} installed):\n`));
48
+
49
+ const choices = skills.map(skill => {
50
+ let label = `${chalk.cyan(skill.name)}`;
51
+
52
+ if (skill.description) {
53
+ label += ` ${chalk.dim('- ' + skill.description.slice(0, 80) + (skill.description.length > 80 ? '...' : ''))}`;
54
+ }
55
+
56
+ return {
57
+ name: label,
58
+ value: skill
59
+ };
60
+ });
61
+
62
+ // Show checkbox selection
63
+ const selected = await checkbox({
64
+ message: 'Select skills to remove:',
65
+ choices,
66
+ pageSize: 20,
67
+ loop: false
68
+ });
69
+
70
+ if (selected.length === 0) {
71
+ console.log(chalk.yellow('\nNo skills selected.'));
72
+ return;
73
+ }
74
+
75
+ // Show summary table
76
+ console.log(chalk.bold.yellow(`\n⚠️ You are about to remove ${selected.length} skill(s):`));
77
+ const table = new Table({
78
+ head: [chalk.cyan('Skill Name'), chalk.cyan('Description')],
79
+ colWidths: [30, Math.max(20, (process.stdout.columns || 80) - 40)],
80
+ wordWrap: true,
81
+ style: { head: [], border: [] }
82
+ });
83
+
84
+ selected.forEach(skill => {
85
+ table.push([
86
+ chalk.bold.red(skill.name),
87
+ skill.description || chalk.dim('No description')
88
+ ]);
89
+ });
90
+
91
+ console.log(table.toString());
92
+ console.log();
93
+
94
+ // Confirm removal
95
+ const shouldRemove = await confirm({
96
+ message: chalk.red(`⚠️ Permanently remove ${selected.length} skill(s)?`),
97
+ default: false
98
+ });
99
+
100
+ if (!shouldRemove) {
101
+ console.log(chalk.yellow('Operation cancelled.'));
102
+ return;
103
+ }
104
+
105
+ // Remove selected skills
106
+ console.log();
107
+ let successCount = 0;
108
+ let failCount = 0;
109
+
110
+ for (const skill of selected) {
111
+ try {
112
+ removeLocalSkill(skill.name);
113
+ console.log(chalk.green(`✓ Removed ${chalk.bold(skill.name)}`));
114
+ successCount++;
115
+ } catch (error) {
116
+ console.error(chalk.red(`✗ Failed to remove ${skill.name}: ${error.message}`));
117
+ failCount++;
118
+ }
119
+ }
120
+
121
+ console.log('\n────────────────────────────────────────');
122
+ if (failCount === 0) {
123
+ console.log(chalk.green(`✓ Successfully removed ${successCount} skill(s)`));
124
+ } else {
125
+ console.log(chalk.yellow(`⚠ Removed ${successCount} skill(s), ${failCount} failed`));
126
+ }
127
+ }
128
+
129
+ async function removeAllSkills(skills, autoYes) {
130
+ console.log(chalk.bold.yellow(`\n⚠️ You are about to remove ALL ${skills.length} installed skills:\n`));
131
+
132
+ // Show table of all skills
133
+ const table = new Table({
134
+ head: [chalk.cyan('Skill Name'), chalk.cyan('Description')],
135
+ colWidths: [30, Math.max(20, (process.stdout.columns || 80) - 40)],
136
+ wordWrap: true,
137
+ style: { head: [], border: [] }
138
+ });
139
+
140
+ skills.forEach(skill => {
141
+ table.push([
142
+ chalk.bold.red(skill.name),
143
+ skill.description || chalk.dim('No description')
144
+ ]);
145
+ });
146
+
147
+ console.log(table.toString());
148
+ console.log();
149
+
150
+ let shouldProceed = autoYes;
151
+ if (!shouldProceed) {
152
+ shouldProceed = await confirm({
153
+ message: chalk.red(`⚠️ Permanently remove ALL ${skills.length} skills?`),
154
+ default: false
155
+ });
156
+ }
157
+
158
+ if (!shouldProceed) {
159
+ console.log(chalk.yellow('Operation cancelled.'));
160
+ return;
161
+ }
162
+
163
+ console.log();
164
+ let successCount = 0;
165
+ let failCount = 0;
166
+
167
+ for (const skill of skills) {
168
+ try {
169
+ removeLocalSkill(skill.name);
170
+ console.log(chalk.green(`✓ Removed ${chalk.bold(skill.name)}`));
171
+ successCount++;
172
+ } catch (error) {
173
+ console.error(chalk.red(`✗ Failed to remove ${skill.name}: ${error.message}`));
174
+ failCount++;
175
+ }
176
+ }
177
+
178
+ console.log('\n────────────────────────────────────────');
179
+ if (failCount === 0) {
180
+ console.log(chalk.green(`✓ Successfully removed all ${successCount} skills`));
181
+ } else {
182
+ console.log(chalk.yellow(`⚠ Removed ${successCount} skills, ${failCount} failed`));
183
+ }
184
+ }
185
+
186
+ async function removeSingleSkill(skillName) {
12
187
  if (!skillExists(skillName)) {
13
188
  console.log(chalk.yellow(`Skill "${skillName}" is not installed.`));
14
189
  process.exit(1);
@@ -22,3 +197,4 @@ export async function removeSkill(skillName) {
22
197
  process.exit(1);
23
198
  }
24
199
  }
200
+
package/src/index.js CHANGED
@@ -56,9 +56,12 @@ program
56
56
  .action(installSkill);
57
57
 
58
58
  program
59
- .command('remove <skill>')
59
+ .command('remove [skill]')
60
60
  .alias('rm')
61
- .description('Remove an installed skill')
61
+ .description('Remove installed skill(s)')
62
+ .option('-i, --interactive', 'Interactive mode to select skills (default in TTY)')
63
+ .option('-a, --all', 'Remove all installed skills')
64
+ .option('-y, --yes', 'Skip confirmation (use with --all)')
62
65
  .action(removeSkill);
63
66
 
64
67
  program