Skip broken npx skills update, use direct download as primary path

npx skills update has a known upstream bug (vercel-labs/skills#775)
where it can't find the lock file. Instead of trying it first and
falling back, always use our direct download which is reliable.

Also:
- Site now recommends `npx impeccable skills update` everywhere
  instead of `npx skills update`
- Direct download path now re-applies prefix after updating
- Runs cleanup after download to strip deprecated stubs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-04-10 10:22:44 -07:00
co-authored by Claude Opus 4.6
parent 3395df9083
commit 697541f77e
2 changed files with 24 additions and 47 deletions
+20 -43
View File
@@ -369,8 +369,7 @@ function downloadFile(url, dest) {
async function update(flags = []) {
const yes = flags.includes('-y') || flags.includes('--yes');
// Clean up deprecated skills before updating, so npx skills update
// does not fail on entries that no longer exist in the source repo.
// Clean up deprecated skills from previous versions.
try {
const { cleanup } = await import('../../source/skills/impeccable/scripts/cleanup-deprecated.mjs');
const root = findProjectRoot();
@@ -383,47 +382,10 @@ async function update(flags = []) {
// Cleanup script not available (e.g. running from npm package) -- skip
}
// Try npx skills update first
console.log('Checking for skills manager...');
let noLockFile = true;
try {
const output = execSync('npx skills check', { encoding: 'utf8', timeout: 15000 });
noLockFile = output.includes('No skills tracked');
} catch {
// npx skills not available or errored
}
if (!noLockFile) {
const root = findProjectRoot();
const prefix = detectPrefix(root);
// Temporarily undo prefix so npx skills can find its tracked skill names
if (prefix) {
console.log(`Detected "${prefix}" prefix, temporarily reverting for update...`);
undoPrefix(root, prefix);
}
console.log('Updating via npx skills...\n');
try {
execSync('npx skills update', { stdio: 'inherit' });
} catch (e) {
// Re-apply prefix even if update fails
if (prefix) renameSkillsWithPrefix(root, prefix);
process.exit(e.status ?? 1);
}
// Re-apply prefix after update
if (prefix) {
const count = renameSkillsWithPrefix(root, prefix);
console.log(`\nRe-applied "${prefix}" prefix to ${count} skills.`);
}
process.exit(0);
}
// Fallback: direct download of the universal bundle.
// Note: npx skills update has a known bug where it can't find the
// lock file (vercel-labs/skills#775), so this path is common.
console.log('Updating skills via direct download...\n');
// Download the latest skills directly from impeccable.style.
// We skip `npx skills update` because it has a known upstream bug
// (vercel-labs/skills#775) where it can't find the lock file.
console.log('Checking for updates...\n');
const root = findProjectRoot();
const providers = findInstalledProviders(root);
@@ -502,6 +464,21 @@ async function update(flags = []) {
rmSync(tmpDir, { recursive: true, force: true });
rmSync(tmpZip, { force: true });
// Re-apply prefix if detected
const prefix = detectPrefix(root);
if (prefix) {
const count = renameSkillsWithPrefix(root, prefix);
if (count > 0) console.log(`Re-applied "${prefix}" prefix to ${count} skills.`);
}
// Run cleanup again to remove deprecated stubs from the fresh download
try {
const { cleanup: postCleanup } = await import('../../source/skills/impeccable/scripts/cleanup-deprecated.mjs');
postCleanup(root);
} catch {
// Not available -- skip
}
console.log(`Updated ${updated} skills across ${providers.length} provider(s).`);
console.log('Done!\n');
} catch (e) {
+4 -4
View File
@@ -457,8 +457,8 @@
<div class="install-cmd-block">
<div class="install-cmd-line">
<span class="terminal-prompt">$</span>
<code>npx skills update</code>
<button class="copy-btn" aria-label="Copy command" data-copy="npx skills update">
<code>npx impeccable skills update</code>
<button class="copy-btn" aria-label="Copy command" data-copy="npx impeccable skills update">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path>
@@ -636,9 +636,9 @@
<details class="faq-item">
<summary class="faq-question">How do I update to the latest version?</summary>
<div class="faq-answer">
<p>Run <code>npx skills update</code> from your project root.</p>
<p>Run <code>npx impeccable skills update</code> from your project root. It downloads the latest skills, cleans up deprecated files, and preserves any prefix you use.</p>
<ul>
<li><strong>Update fails?</strong> Run <code>npx skills add pbakaus/impeccable</code> instead, then invoke <code>/impeccable</code> once to clean up old files.</li>
<li><strong>Alternative:</strong> <code>npx skills add pbakaus/impeccable</code> re-installs from scratch.</li>
<li><strong>Claude Code plugin:</strong> Open <code>/plugin</code>, go to the Discover tab.</li>
<li><strong>Manual ZIP:</strong> Download from above and extract to the project root.</li>
</ul>