diff --git a/plug/src/commands/install.js b/plug/src/commands/install.js index 95b45ae..76ddda6 100644 --- a/plug/src/commands/install.js +++ b/plug/src/commands/install.js @@ -6,6 +6,7 @@ import { findPackage, findAllPackages } from '../utils/registry.js'; import { downloadFile } from '../utils/fetcher.js'; import { trackInstall, isInstalled, getInstalled, addDependents } from '../utils/tracker.js'; import { getClaudeSkillsDir, getClaudeAgentsDir, getClaudeDirForType, ensureDir } from '../utils/paths.js'; +import { invalidateCommunityIndexCache } from '../utils/community-index.js'; import { createSpinner } from '../utils/ui.js'; import { ctx, verbose } from '../utils/context.js'; import { pkgVersion } from '../utils/pkg-version.js'; @@ -34,6 +35,8 @@ export function registerInstall(program) { export async function runInstall(name, options = {}) { const isGlobal = options.global || false; + await invalidateCommunityIndexCache(); + // Parse vault prefix (vault/name) let vaultName = null; let pkgName = name; diff --git a/plug/src/tui/components/package-detail.jsx b/plug/src/tui/components/package-detail.jsx index ace88c7..f0c0692 100644 --- a/plug/src/tui/components/package-detail.jsx +++ b/plug/src/tui/components/package-detail.jsx @@ -75,33 +75,6 @@ export default function PackageDetail({ pkg, onBack, onInstall, installedNames = - {pkg.dependencies?.length > 0 && ( - - Dependencies: - {pkg.dependencies.map(dep => ( - - {dep.required ? '•' : '○'} - {dep.name} - ({dep.vault}) - {installedNames.has(dep.name) - ? ✓ installed - : not installed} - - ))} - {pkg.dependencies.filter(d => d.required && !installedNames.has(d.name)).length > 0 && ( - - Installing this will also install: - - {pkg.dependencies - .filter(d => d.required && !installedNames.has(d.name)) - .map(d => d.name) - .join(', ')} - - - )} - - )} - {/* Usage hint */} {isInstalled ? ( diff --git a/plug/src/tui/components/package-item.jsx b/plug/src/tui/components/package-item.jsx index cd4ab45..5570246 100644 --- a/plug/src/tui/components/package-item.jsx +++ b/plug/src/tui/components/package-item.jsx @@ -26,7 +26,6 @@ export default function PackageItem({ isCursor, isToggled, isInstalled = false, - showDeps = false, mode = 'discover', terminalWidth = 80, }) { @@ -43,14 +42,10 @@ export default function PackageItem({ ? ` → v${item.latestVersion} ⬆` : ''; - const depStr = item.depCount > 0 - ? ` · ★ ${item.depCount} dep${item.depCount === 1 ? '' : 's'}` - : ' · no deps'; - // Prefix: "[ ] > " = 6 chars const prefixLen = 6; const suffixLen = (typeLabel ? typeLabel.length + 1 : 0) + (scopeLabel ? scopeLabel.length + 1 : 0); - const nameLine = `${item.name} · ${item.vault}${versionStr ? ` · ${versionStr}` : ''}${updateStr}${showDeps ? depStr : ''}`; + const nameLine = `${item.name} · ${item.vault}${versionStr ? ` · ${versionStr}` : ''}${updateStr}`; const maxNameLen = terminalWidth - prefixLen - suffixLen - 2; const truncatedName = nameLine.length > maxNameLen ? nameLine.slice(0, maxNameLen - 1) + '…' diff --git a/plug/src/tui/components/package-list.jsx b/plug/src/tui/components/package-list.jsx index 0bf3c84..5527dcd 100644 --- a/plug/src/tui/components/package-list.jsx +++ b/plug/src/tui/components/package-list.jsx @@ -15,7 +15,6 @@ import { useTerminalSize } from '../hooks/use-terminal-size.js'; * toggled?: Set, * onToggle?: (index: number) => void, * installedNames?: Set, - * showDeps?: boolean, * mode?: 'discover'|'installed', * emptyMessage?: string, * }} props @@ -29,7 +28,6 @@ export default function PackageList({ toggled: externalToggled, onToggle, installedNames, - showDeps = false, mode = 'discover', emptyMessage = 'No packages found.', }) { @@ -119,7 +117,6 @@ export default function PackageList({ isCursor={index === cursor} isToggled={toggled.has(index)} isInstalled={installedNames?.has(item.name) ?? false} - showDeps={showDeps} mode={mode} terminalWidth={terminalWidth} /> diff --git a/plug/src/tui/hooks/use-installed.js b/plug/src/tui/hooks/use-installed.js index 178c4ab..ddb79a9 100644 --- a/plug/src/tui/hooks/use-installed.js +++ b/plug/src/tui/hooks/use-installed.js @@ -1,8 +1,12 @@ import { useState, useEffect, useCallback } from 'react'; +import os from 'os'; +import path from 'path'; import { getInstalled } from '../../utils/tracker.js'; import { findPackage } from '../../utils/registry.js'; import { compareSemver } from '../../commands/update.js'; +const globalClaudeDir = path.resolve(os.homedir(), '.claude'); + /** * Loads installed packages from both local and global scopes. * Enriches each record with scope label, update-available info. @@ -45,15 +49,22 @@ export function useInstalled() { ]); const merged = []; - const localPaths = new Map(); + const seen = new Map(); + + function inferScope(record) { + if (!record.path) return 'local'; + return path.resolve(record.path).startsWith(globalClaudeDir) ? 'global' : 'local'; + } for (const [name, record] of Object.entries(localData.installed || {})) { - merged.push({ name, ...record, scope: 'local', hasUpdate: false, latestVersion: null }); - localPaths.set(name, record.path); + const scope = inferScope(record); + merged.push({ name, ...record, scope, hasUpdate: false, latestVersion: null }); + seen.set(name, record.path); } for (const [name, record] of Object.entries(globalData.installed || {})) { - if (localPaths.has(name) && localPaths.get(name) === record.path) continue; - merged.push({ name, ...record, scope: 'global', hasUpdate: false, latestVersion: null }); + if (seen.has(name) && seen.get(name) === record.path) continue; + const scope = inferScope(record); + merged.push({ name, ...record, scope, hasUpdate: false, latestVersion: null }); } // Sort by name then scope diff --git a/plug/src/tui/screens/discover.jsx b/plug/src/tui/screens/discover.jsx index 2b7621c..0bee232 100644 --- a/plug/src/tui/screens/discover.jsx +++ b/plug/src/tui/screens/discover.jsx @@ -328,7 +328,6 @@ export default function DiscoverScreen({ onInputCapture }) { toggled={toggled} onToggle={handleToggle} installedNames={installedNames} - showDeps={true} emptyMessage={emptyMessage} /> diff --git a/plug/src/utils/community-index.js b/plug/src/utils/community-index.js index ff68c05..5671cb2 100644 --- a/plug/src/utils/community-index.js +++ b/plug/src/utils/community-index.js @@ -35,6 +35,15 @@ export async function cacheCommunityIndex(data) { await fs.writeFile(cachePath, JSON.stringify(data, null, 2), 'utf8'); } +/** + * Deletes the community index cache so the next fetch hits the network. + */ +export async function invalidateCommunityIndexCache() { + try { + await fs.unlink(getCacheFilePath()); + } catch { /* ignore if missing */ } +} + /** * Returns cached community index data regardless of age (offline/stale fallback). */