@maccesar/titools 2.0.6 → 2.2.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/{AGENTS-TEMPLATE.md → AGENTS-VERCEL-RESEARCH.md} +16 -18
- package/README.md +250 -168
- package/agents/{ti-researcher.md → ti-pro.md} +10 -10
- package/bin/titools.js +16 -12
- package/lib/cleanup.js +95 -0
- package/lib/commands/agents.js +146 -70
- package/lib/commands/skills.js +349 -0
- package/lib/commands/uninstall.js +189 -154
- package/lib/commands/update.js +104 -21
- package/lib/config.js +26 -20
- package/lib/downloader.js +1 -1
- package/lib/installer.js +37 -97
- package/lib/platform.js +9 -5
- package/lib/prompts/checkboxCancel.js +264 -0
- package/lib/prompts/selectCancel.js +204 -0
- package/lib/symlink.js +19 -7
- package/lib/utils.js +21 -31
- package/package.json +10 -10
- package/skills/alloy-guides/SKILL.md +8 -30
- package/skills/alloy-guides/references/CLI_TASKS.md +14 -24
- package/skills/alloy-guides/references/CONCEPTS.md +5 -25
- package/skills/alloy-guides/references/CONTROLLERS.md +2 -19
- package/skills/alloy-guides/references/MODELS.md +40 -10
- package/skills/alloy-guides/references/PURGETSS.md +1 -11
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +8 -14
- package/skills/alloy-guides/references/VIEWS_STYLES.md +14 -25
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +2 -8
- package/skills/alloy-guides/references/VIEWS_XML.md +29 -40
- package/skills/alloy-guides/references/WIDGETS.md +1 -17
- package/skills/alloy-howtos/SKILL.md +1 -22
- package/skills/alloy-howtos/references/best_practices.md +0 -17
- package/skills/alloy-howtos/references/cli_reference.md +1 -23
- package/skills/alloy-howtos/references/config_files.md +86 -15
- package/skills/alloy-howtos/references/custom_tags.md +14 -13
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +3 -22
- package/skills/alloy-howtos/references/samples.md +4 -14
- package/skills/purgetss/SKILL.md +11 -37
- package/skills/purgetss/references/EXAMPLES.md +106 -17
- package/skills/purgetss/references/animation-system.md +0 -67
- package/skills/purgetss/references/apply-directive.md +0 -18
- package/skills/purgetss/references/arbitrary-values.md +0 -25
- package/skills/purgetss/references/class-index.md +0 -46
- package/skills/purgetss/references/cli-commands.md +0 -41
- package/skills/purgetss/references/configurable-properties.md +0 -55
- package/skills/purgetss/references/custom-rules.md +0 -14
- package/skills/purgetss/references/customization-deep-dive.md +0 -49
- package/skills/purgetss/references/dynamic-component-creation.md +56 -37
- package/skills/purgetss/references/grid-layout.md +0 -32
- package/skills/purgetss/references/icon-fonts.md +0 -50
- package/skills/purgetss/references/installation-setup.md +61 -32
- package/skills/purgetss/references/migration-guide.md +127 -0
- package/skills/purgetss/references/opacity-modifier.md +0 -34
- package/skills/purgetss/references/performance-tips.md +261 -0
- package/skills/purgetss/references/platform-modifiers.md +0 -46
- package/skills/purgetss/references/smart-mappings.md +0 -12
- package/skills/purgetss/references/tikit-components.md +393 -0
- package/skills/purgetss/references/titanium-resets.md +1 -27
- package/skills/purgetss/references/ui-ux-design.md +467 -117
- package/skills/{alloy-expert → ti-expert}/SKILL.md +45 -54
- package/skills/ti-expert/references/alloy-builtins.md +387 -0
- package/skills/{alloy-expert → ti-expert}/references/alloy-structure.md +147 -40
- package/skills/ti-expert/references/anti-patterns.md +90 -0
- package/skills/ti-expert/references/cli-expert.md +109 -0
- package/skills/{alloy-expert → ti-expert}/references/code-conventions.md +182 -49
- package/skills/{alloy-expert → ti-expert}/references/controller-patterns.md +103 -93
- package/skills/{alloy-expert → ti-expert}/references/error-handling.md +12 -12
- package/skills/{alloy-expert → ti-expert}/references/examples.md +144 -85
- package/skills/{alloy-expert → ti-expert}/references/migration-patterns.md +38 -36
- package/skills/{alloy-expert → ti-expert}/references/patterns.md +8 -8
- package/skills/ti-expert/references/performance-listview.md +251 -0
- package/skills/{alloy-expert/references/performance-patterns.md → ti-expert/references/performance-optimization.md} +67 -283
- package/skills/{alloy-expert/references/security-patterns.md → ti-expert/references/security-device.md} +12 -295
- package/skills/ti-expert/references/security-fundamentals.md +284 -0
- package/skills/{alloy-expert → ti-expert}/references/state-management.md +10 -10
- package/skills/ti-expert/references/testing-e2e-ci.md +432 -0
- package/skills/ti-expert/references/testing-unit.md +433 -0
- package/skills/ti-expert/references/theming.md +394 -0
- package/skills/ti-guides/SKILL.md +1 -14
- package/skills/ti-guides/references/advanced-data-and-images.md +126 -10
- package/skills/ti-guides/references/app-distribution.md +48 -10
- package/skills/ti-guides/references/application-frameworks.md +9 -2
- package/skills/ti-guides/references/cli-reference.md +338 -82
- package/skills/ti-guides/references/coding-best-practices.md +14 -4
- package/skills/ti-guides/references/commonjs-advanced.md +103 -6
- package/skills/ti-guides/references/hello-world.md +5 -2
- package/skills/ti-guides/references/hyperloop-native-access.md +439 -46
- package/skills/ti-guides/references/javascript-primer.md +4 -3
- package/skills/ti-guides/references/resources.md +0 -1
- package/skills/ti-guides/references/style-and-conventions.md +57 -9
- package/skills/ti-guides/references/tiapp-config.md +48 -6
- package/skills/ti-howtos/SKILL.md +2 -27
- package/skills/ti-howtos/references/android-platform-deep-dives.md +41 -90
- package/skills/ti-howtos/references/automation-fastlane-appium.md +15 -14
- package/skills/ti-howtos/references/buffer-codec-streams.md +22 -22
- package/skills/ti-howtos/references/cross-platform-development.md +68 -37
- package/skills/ti-howtos/references/debugging-profiling.md +8 -53
- package/skills/ti-howtos/references/extending-titanium.md +12 -51
- package/skills/ti-howtos/references/google-maps-v2.md +30 -29
- package/skills/ti-howtos/references/ios-map-kit.md +19 -25
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +95 -283
- package/skills/ti-howtos/references/local-data-sources.md +45 -37
- package/skills/ti-howtos/references/location-and-maps.md +47 -28
- package/skills/ti-howtos/references/media-apis.md +84 -27
- package/skills/ti-howtos/references/notification-services.md +40 -89
- package/skills/ti-howtos/references/remote-data-sources.md +21 -36
- package/skills/ti-howtos/references/tutorials.md +79 -39
- package/skills/ti-howtos/references/using-modules.md +4 -30
- package/skills/ti-howtos/references/web-content-integration.md +28 -45
- package/skills/ti-howtos/references/webpack-build-pipeline.md +54 -18
- package/skills/ti-ui/SKILL.md +1 -21
- package/skills/ti-ui/references/accessibility-deep-dive.md +71 -25
- package/skills/ti-ui/references/animation-and-matrices.md +0 -47
- package/skills/ti-ui/references/application-structures.md +0 -46
- package/skills/ti-ui/references/custom-fonts-styling.md +9 -57
- package/skills/ti-ui/references/event-handling.md +32 -40
- package/skills/ti-ui/references/gestures.md +0 -40
- package/skills/ti-ui/references/icons-and-splash-screens.md +21 -44
- package/skills/ti-ui/references/layouts-and-positioning.md +47 -39
- package/skills/ti-ui/references/listviews-and-performance.md +187 -73
- package/skills/ti-ui/references/orientation.md +57 -71
- package/skills/ti-ui/references/platform-ui-android.md +114 -48
- package/skills/ti-ui/references/platform-ui-ios.md +63 -38
- package/skills/ti-ui/references/scrolling-views.md +14 -23
- package/skills/ti-ui/references/tableviews.md +6 -56
- package/lib/commands/install.js +0 -188
- package/skills/alloy-expert/references/anti-patterns.md +0 -133
- package/skills/alloy-expert/references/testing.md +0 -872
- package/skills/ti-guides/references/alloy-cli-advanced.md +0 -84
- package/skills/ti-guides/references/alloy-data-mastery.md +0 -29
- package/skills/ti-guides/references/alloy-widgets-and-themes.md +0 -19
- /package/skills/{alloy-expert → ti-expert}/assets/ControllerAutoCleanup.js +0 -0
- /package/skills/{alloy-expert → ti-expert}/references/contracts.md +0 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills command
|
|
3
|
+
* Installs and manages skills in AI coding assistant directories
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import {
|
|
9
|
+
SKILLS,
|
|
10
|
+
getPlatforms,
|
|
11
|
+
getAgentsSkillsDir,
|
|
12
|
+
} from '../config.js';
|
|
13
|
+
import select from '../prompts/selectCancel.js';
|
|
14
|
+
import checkbox, { Separator } from '../prompts/checkboxCancel.js';
|
|
15
|
+
import {
|
|
16
|
+
detectPlatforms,
|
|
17
|
+
detectOS,
|
|
18
|
+
} from '../platform.js';
|
|
19
|
+
import {
|
|
20
|
+
getSkillList,
|
|
21
|
+
removeSkillSymlinks,
|
|
22
|
+
removeLegacySkillSymlinks,
|
|
23
|
+
removeSkills,
|
|
24
|
+
removeAgents,
|
|
25
|
+
} from '../cleanup.js';
|
|
26
|
+
import {
|
|
27
|
+
installSkills,
|
|
28
|
+
installAgents,
|
|
29
|
+
getLocalRepoDir,
|
|
30
|
+
} from '../installer.js';
|
|
31
|
+
import { agentsCommand } from './agents.js';
|
|
32
|
+
import { downloadRepoArchive } from '../downloader.js';
|
|
33
|
+
import { createSkillSymlinks } from '../symlink.js';
|
|
34
|
+
import { formatList, isTitaniumProject } from '../utils.js';
|
|
35
|
+
import { mkdtemp } from 'fs/promises';
|
|
36
|
+
import { existsSync } from 'fs';
|
|
37
|
+
import { join, resolve } from 'path';
|
|
38
|
+
import { tmpdir } from 'os';
|
|
39
|
+
|
|
40
|
+
function hasAnySkillSymlink(platformSkillsDir) {
|
|
41
|
+
if (!platformSkillsDir || !existsSync(platformSkillsDir)) return false;
|
|
42
|
+
const skillList = getSkillList();
|
|
43
|
+
return skillList.some((skill) => existsSync(join(platformSkillsDir, skill)));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Skills command handler
|
|
48
|
+
* @param {Object} options - Command options
|
|
49
|
+
*/
|
|
50
|
+
export async function skillsCommand(options) {
|
|
51
|
+
console.log('');
|
|
52
|
+
console.log(chalk.bold.blue('Titanium SDK Skills Manager'));
|
|
53
|
+
console.log('');
|
|
54
|
+
|
|
55
|
+
let isLocal = options.local;
|
|
56
|
+
let customPath = options.path;
|
|
57
|
+
|
|
58
|
+
// Auto-detection logic: If no explicit mode, check if we are in a Titanium project
|
|
59
|
+
if (!isLocal && !customPath) {
|
|
60
|
+
const projectDir = process.cwd();
|
|
61
|
+
const isProject = isTitaniumProject(projectDir);
|
|
62
|
+
|
|
63
|
+
if (isProject) {
|
|
64
|
+
try {
|
|
65
|
+
const mode = await select({
|
|
66
|
+
message: 'Titanium project detected. Where do you want to install the skills:',
|
|
67
|
+
choices: [
|
|
68
|
+
{ name: 'Global (user home) - Recommended for personal use', value: 'global' },
|
|
69
|
+
{ name: 'Local (current project) - Best for shared repositories', value: 'local' },
|
|
70
|
+
],
|
|
71
|
+
theme: {
|
|
72
|
+
style: {
|
|
73
|
+
answer: () => '',
|
|
74
|
+
prefix: () => chalk.cyan('?'),
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
if (mode === 'cancel') {
|
|
79
|
+
console.log('Cancelled.');
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
isLocal = mode === 'local';
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.log('\nCancelled.');
|
|
85
|
+
process.exit(0);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Determine base directory (Local vs Global)
|
|
91
|
+
const baseDir = isLocal ? process.cwd() : (customPath ? resolve(customPath) : undefined);
|
|
92
|
+
|
|
93
|
+
if (isLocal) {
|
|
94
|
+
console.log(chalk.cyan('Mode: Local installation (current project)'));
|
|
95
|
+
} else if (customPath) {
|
|
96
|
+
console.log(chalk.cyan(`Mode: Custom path (${baseDir})`));
|
|
97
|
+
} else {
|
|
98
|
+
console.log(chalk.cyan('Mode: Global installation (user home)'));
|
|
99
|
+
}
|
|
100
|
+
console.log('');
|
|
101
|
+
|
|
102
|
+
// Detect installed platforms at the target base directory
|
|
103
|
+
const localPlatforms = detectPlatforms(baseDir);
|
|
104
|
+
const globalPlatforms = detectPlatforms();
|
|
105
|
+
let detectedPlatforms = localPlatforms;
|
|
106
|
+
|
|
107
|
+
if (isLocal || options.path) {
|
|
108
|
+
const localNames = new Set(localPlatforms.map((platform) => platform.name));
|
|
109
|
+
const globalNames = new Set(globalPlatforms.map((platform) => platform.name));
|
|
110
|
+
const allPlatforms = getPlatforms(baseDir);
|
|
111
|
+
const merged = [...localPlatforms];
|
|
112
|
+
for (const platform of allPlatforms) {
|
|
113
|
+
if (globalNames.has(platform.name) && !localNames.has(platform.name)) {
|
|
114
|
+
merged.push(platform);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
detectedPlatforms = merged;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (detectedPlatforms.length === 0 && !options.path && !isLocal) {
|
|
121
|
+
console.log(chalk.yellow('No AI coding assistants detected globally.'));
|
|
122
|
+
console.log('Install one of: Claude Code, Gemini CLI, or Codex CLI');
|
|
123
|
+
console.log('Or use: titools install --local');
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Show detected platforms
|
|
128
|
+
if (detectedPlatforms.length > 0) {
|
|
129
|
+
for (const platform of detectedPlatforms) {
|
|
130
|
+
console.log(chalk.green('✓'), `${platform.displayName} detected`);
|
|
131
|
+
}
|
|
132
|
+
console.log('');
|
|
133
|
+
} else if (isLocal) {
|
|
134
|
+
// If local and none detected, still allow selection
|
|
135
|
+
detectedPlatforms = getPlatforms(baseDir);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Select platforms to install
|
|
139
|
+
let selectedPlatforms = [];
|
|
140
|
+
|
|
141
|
+
if (options.path) {
|
|
142
|
+
// Custom path mode - skip platform selection
|
|
143
|
+
selectedPlatforms = detectedPlatforms;
|
|
144
|
+
} else if (options.all) {
|
|
145
|
+
// Install to all detected platforms
|
|
146
|
+
selectedPlatforms = detectedPlatforms;
|
|
147
|
+
} else {
|
|
148
|
+
// Modern functional selection
|
|
149
|
+
try {
|
|
150
|
+
const platformChoices = await checkbox({
|
|
151
|
+
message: 'Select platforms to sync:',
|
|
152
|
+
choices: [
|
|
153
|
+
...detectedPlatforms.map((p) => ({
|
|
154
|
+
name: p.displayName,
|
|
155
|
+
value: p.name,
|
|
156
|
+
checked: hasAnySkillSymlink(p.skillsDir),
|
|
157
|
+
})),
|
|
158
|
+
new Separator(' ')
|
|
159
|
+
],
|
|
160
|
+
shortcuts: { invert: null },
|
|
161
|
+
theme: {
|
|
162
|
+
style: {
|
|
163
|
+
renderSelectedChoices: () => '',
|
|
164
|
+
prefix: () => chalk.cyan('?'),
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
if (platformChoices.includes('cancel')) {
|
|
170
|
+
console.log('Cancelled.');
|
|
171
|
+
process.exit(0);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
selectedPlatforms = detectedPlatforms.filter((p) =>
|
|
175
|
+
platformChoices.includes(p.name)
|
|
176
|
+
);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.log('\nCancelled.');
|
|
179
|
+
process.exit(0);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const removeOnly = selectedPlatforms.length === 0;
|
|
184
|
+
if (removeOnly) {
|
|
185
|
+
console.log(chalk.yellow('No platforms selected. Removing all platform symlinks and agents.'));
|
|
186
|
+
}
|
|
187
|
+
const showGeminiWarning = (() => {
|
|
188
|
+
if (removeOnly || !isLocal) return false;
|
|
189
|
+
const globalGemini = globalPlatforms.find((platform) => platform.name === 'gemini');
|
|
190
|
+
const geminiSelected = selectedPlatforms.some((platform) => platform.name === 'gemini');
|
|
191
|
+
return !!(geminiSelected && globalGemini && hasAnySkillSymlink(globalGemini.skillsDir));
|
|
192
|
+
})();
|
|
193
|
+
|
|
194
|
+
// Get repository directory (local or download)
|
|
195
|
+
const spinner = ora();
|
|
196
|
+
let repoDir = null;
|
|
197
|
+
let tempDir = null;
|
|
198
|
+
|
|
199
|
+
if (!removeOnly) {
|
|
200
|
+
repoDir = getLocalRepoDir();
|
|
201
|
+
|
|
202
|
+
if (!repoDir) {
|
|
203
|
+
// Download from GitHub
|
|
204
|
+
spinner.start('Downloading from GitHub...');
|
|
205
|
+
try {
|
|
206
|
+
tempDir = await mkdtemp(join(tmpdir(), 'titanium-skills-'));
|
|
207
|
+
repoDir = await downloadRepoArchive(tempDir);
|
|
208
|
+
spinner.succeed('Downloaded from GitHub');
|
|
209
|
+
} catch (error) {
|
|
210
|
+
spinner.fail('Failed to download');
|
|
211
|
+
console.error(chalk.red(error.message));
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
console.log(chalk.green('Using local repository'));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const selectedPlatformNames = new Set(selectedPlatforms.map((platform) => platform.name));
|
|
220
|
+
const removedPlatformNames = [];
|
|
221
|
+
const claudeSelected = selectedPlatformNames.has('claude');
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
if (!removeOnly) {
|
|
225
|
+
// Install skills
|
|
226
|
+
spinner.start('Installing skills...');
|
|
227
|
+
const skillsResult = await installSkills(repoDir, baseDir);
|
|
228
|
+
spinner.succeed(`${SKILLS.length} skills installed`);
|
|
229
|
+
|
|
230
|
+
if (claudeSelected) {
|
|
231
|
+
// Install agents
|
|
232
|
+
spinner.start('Installing agents...');
|
|
233
|
+
const agentsResult = await installAgents(repoDir, baseDir);
|
|
234
|
+
if (agentsResult.installed.length > 0) {
|
|
235
|
+
spinner.succeed('Platform agents installed');
|
|
236
|
+
} else {
|
|
237
|
+
spinner.info('No agents to install (Claude Code not detected)');
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
spinner.start('Removing agents...');
|
|
241
|
+
const agentsResult = removeAgents(baseDir);
|
|
242
|
+
if (agentsResult.removed.length > 0) {
|
|
243
|
+
spinner.succeed('Platform agents removed');
|
|
244
|
+
} else {
|
|
245
|
+
spinner.info('No agents to remove');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Create symlinks for selected platforms
|
|
250
|
+
for (const platform of selectedPlatforms) {
|
|
251
|
+
removeLegacySkillSymlinks(platform.skillsDir);
|
|
252
|
+
spinner.start(`Linking ${platform.displayName}...`);
|
|
253
|
+
const symlinkResult = await createSkillSymlinks(
|
|
254
|
+
platform.skillsDir,
|
|
255
|
+
SKILLS,
|
|
256
|
+
baseDir
|
|
257
|
+
);
|
|
258
|
+
if (symlinkResult.linked.length === SKILLS.length) {
|
|
259
|
+
spinner.succeed(`${platform.displayName}: Skills linked`);
|
|
260
|
+
} else {
|
|
261
|
+
spinner.warn(
|
|
262
|
+
`${platform.displayName}: ${symlinkResult.linked.length}/${SKILLS.length} skills linked`
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
const agentsResult = removeAgents(baseDir);
|
|
268
|
+
const skillsResult = removeSkills(baseDir);
|
|
269
|
+
const platformResults = detectedPlatforms.map((platform) => {
|
|
270
|
+
const symlinkResult = removeSkillSymlinks(platform.skillsDir);
|
|
271
|
+
return {
|
|
272
|
+
displayName: platform.displayName,
|
|
273
|
+
removedCount: symlinkResult.removed.length,
|
|
274
|
+
};
|
|
275
|
+
});
|
|
276
|
+
const anyRemoved = platformResults.some((result) => result.removedCount > 0);
|
|
277
|
+
|
|
278
|
+
if (skillsResult.removed.length > 0) {
|
|
279
|
+
console.log(chalk.green('✓'), `${skillsResult.removed.length} skills removed`);
|
|
280
|
+
} else {
|
|
281
|
+
console.log(chalk.gray('ℹ'), 'No skills to remove');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (agentsResult.removed.length > 0) {
|
|
285
|
+
console.log(chalk.green('✓'), 'Platform agents removed');
|
|
286
|
+
} else {
|
|
287
|
+
console.log(chalk.gray('ℹ'), 'No agents to remove');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
for (const result of platformResults) {
|
|
291
|
+
if (result.removedCount > 0) {
|
|
292
|
+
console.log(chalk.green('✓'), `${result.displayName}: Skills unlinked`);
|
|
293
|
+
} else {
|
|
294
|
+
console.log(chalk.gray('ℹ'), `${result.displayName}: No symlinks found`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Remove symlinks for unselected detected platforms
|
|
300
|
+
if (!removeOnly) {
|
|
301
|
+
for (const platform of detectedPlatforms) {
|
|
302
|
+
if (selectedPlatformNames.has(platform.name)) continue;
|
|
303
|
+
spinner.start(`Unlinking ${platform.displayName}...`);
|
|
304
|
+
const symlinkResult = removeSkillSymlinks(platform.skillsDir);
|
|
305
|
+
if (symlinkResult.removed.length > 0) {
|
|
306
|
+
spinner.succeed(`${platform.displayName}: Skills unlinked`);
|
|
307
|
+
removedPlatformNames.push(platform.displayName);
|
|
308
|
+
} else {
|
|
309
|
+
spinner.info(`${platform.displayName}: No symlinks found`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Summary
|
|
315
|
+
console.log('');
|
|
316
|
+
console.log(chalk.green('✓ skills sync complete!'));
|
|
317
|
+
if (showGeminiWarning) {
|
|
318
|
+
console.log('');
|
|
319
|
+
console.log(chalk.yellow('⚠ Gemini CLI: local skills will override global skills for this project.'));
|
|
320
|
+
}
|
|
321
|
+
console.log('');
|
|
322
|
+
const isProjectDir = isTitaniumProject(process.cwd());
|
|
323
|
+
if (!removeOnly && selectedPlatforms.length > 0 && isProjectDir) {
|
|
324
|
+
if (process.stdin.isTTY) {
|
|
325
|
+
await agentsCommand(process.cwd(), { inline: true });
|
|
326
|
+
} else {
|
|
327
|
+
console.log(
|
|
328
|
+
chalk.bold('▸'),
|
|
329
|
+
'Sync knowledge index files (AGENTS.md/CLAUDE.md/GEMINI.md):',
|
|
330
|
+
chalk.cyan('titools sync')
|
|
331
|
+
);
|
|
332
|
+
console.log('');
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (!removeOnly && !isLocal && detectOS() === 'windows') {
|
|
337
|
+
console.log(chalk.yellow('▸'), 'Windows: Ensure ~/bin is in your PATH');
|
|
338
|
+
console.log('');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
} finally {
|
|
342
|
+
// Clean up temp directory if we downloaded
|
|
343
|
+
if (tempDir) {
|
|
344
|
+
await import('fs-extra').then(({ remove }) => remove(tempDir));
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export default skillsCommand;
|