@shnitzel/plugscout 0.3.13 → 0.3.14

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.
@@ -0,0 +1,20 @@
1
+ .-----------------------------------------.
2
+ | Scouting plugins so you don't have to. |
3
+ '-----------------------------------------'
4
+ \/
5
+ ___________
6
+ _/ ★ ☆ ★ \_
7
+ /_______________\
8
+ |_________________|
9
+ | (◉) (◉) |
10
+ | ∧ |
11
+ | '~~~~~~~' |
12
+ |_________________|
13
+ _/| [ * ] |\_
14
+ / |_______________| \
15
+ | |
16
+ _| |_
17
+ (_) (_)
18
+
19
+ PlugScout {{version}}
20
+ maintained by {{author}}
@@ -11,7 +11,8 @@ export const colors = {
11
11
  red: (value) => wrap(31, value),
12
12
  cyan: (value) => wrap(36, value),
13
13
  gray: (value) => wrap(90, value),
14
- bold: (value) => wrap(1, value)
14
+ bold: (value) => wrap(1, value),
15
+ dim: (value) => wrap(2, value)
15
16
  };
16
17
  export function colorRisk(tier, value) {
17
18
  if (tier === 'low') {
@@ -7,8 +7,10 @@ import { getPackagePath } from '../../../lib/paths.js';
7
7
  import { colors } from '../formatters/colors.js';
8
8
  import { isSetUp, loadCatalogItems } from '../../../api/index.js';
9
9
  export async function renderHomeScreen() {
10
+ const termCols = process.stdout.columns ?? 80;
11
+ const useCompact = termCols < 82;
10
12
  const [logo, pkg, catalogStats, runtimeStats] = await Promise.all([
11
- readLogo(),
13
+ readLogo(useCompact),
12
14
  readPackageMeta(),
13
15
  readCatalogStats(),
14
16
  readRuntimeStats()
@@ -21,40 +23,56 @@ export async function renderHomeScreen() {
21
23
  .replace('{{author}}', author || 'unknown');
22
24
  lines.push(colorIfTty(renderedLogo.trimEnd(), colors.cyan));
23
25
  lines.push('');
24
- lines.push('Discover and safely install Claude plugins, Claude connectors, Copilot extensions, Skills, and MCP servers.');
26
+ lines.push(colorIfTty('Discover and safely install Claude plugins, connectors,', colors.dim));
27
+ lines.push(colorIfTty('Copilot/Cursor/Gemini extensions, Skills, and MCP servers.', colors.dim));
25
28
  lines.push('');
26
29
  lines.push(colorIfTty('Catalog', colors.bold));
27
- lines.push(`- items=${catalogStats.items} skill=${catalogStats.skill} mcp=${catalogStats.mcp} claude-plugin=${catalogStats.claudePlugin} claude-connector=${catalogStats.claudeConnector} copilot-extension=${catalogStats.copilotExtension}`);
28
- lines.push(`- stale-registries=${runtimeStats.staleRegistries} whitelist=${runtimeStats.whitelist} quarantined=${runtimeStats.quarantined}`);
30
+ lines.push(colorIfTty(` items=${catalogStats.items} skill=${catalogStats.skill} mcp=${catalogStats.mcp} claude-plugin=${catalogStats.claudePlugin} claude-connector=${catalogStats.claudeConnector}`, colors.dim));
31
+ lines.push(colorIfTty(` copilot-extension=${catalogStats.copilotExtension} cursor-extension=${catalogStats.cursorExtension} gemini-extension=${catalogStats.geminiExtension}`, colors.dim));
32
+ lines.push(colorIfTty(` stale-registries=${runtimeStats.staleRegistries} whitelist=${runtimeStats.whitelist} quarantined=${runtimeStats.quarantined}`, colors.dim));
29
33
  lines.push('');
30
34
  lines.push(colorIfTty('Quick actions', colors.bold));
31
- lines.push('- plugscout doctor');
32
- lines.push('- plugscout status --verbose');
33
- lines.push('- plugscout recommend --project . --only-safe --limit 10');
34
- lines.push('- plugscout sync --dry-run');
35
- lines.push('- plugscout help');
35
+ for (const cmd of [
36
+ 'plugscout doctor',
37
+ 'plugscout status --verbose',
38
+ 'plugscout recommend --project . --only-safe --limit 10',
39
+ 'plugscout sync --dry-run',
40
+ 'plugscout help',
41
+ ]) {
42
+ lines.push(` ${colorIfTty(cmd, colors.green)}`);
43
+ }
36
44
  lines.push('');
37
45
  lines.push(colorIfTty('Examples', colors.bold));
38
- lines.push('- plugscout list --kind connectors --limit 10');
39
- lines.push('- plugscout search github');
40
- lines.push('- plugscout show --id claude-connector:asana');
46
+ for (const cmd of [
47
+ 'plugscout list --kind connectors --limit 10',
48
+ 'plugscout list --kind cursor --limit 15',
49
+ 'plugscout search github',
50
+ 'plugscout show --id claude-connector:asana',
51
+ ]) {
52
+ lines.push(` ${colorIfTty(cmd, colors.green)}`);
53
+ }
41
54
  lines.push('');
42
55
  lines.push(colorIfTty('Kind aliases', colors.bold));
43
- lines.push('- skills, mcps, plugins, connectors, extensions');
56
+ lines.push(colorIfTty(' skills · mcps · plugins · connectors · extensions · cursor · gemini', colors.dim));
44
57
  lines.push('');
45
58
  lines.push(colorIfTty('Ranking meaning', colors.bold));
46
- lines.push('- `top` and `recommend` are repo-aware suggestions, not global popularity charts.');
47
- lines.push('- score = fit + trust + freshness - security - blocked');
48
- lines.push('- higher score means a better match for this repo under current policy');
49
- lines.push('- review each suggestion before installing; do not install blindly from rank alone');
59
+ lines.push(colorIfTty(' top/recommend output is repo-aware suggestions, not a global popularity chart', colors.dim));
60
+ lines.push(colorIfTty(' score = fit + trust + freshness - security - blocked', colors.dim));
61
+ lines.push(colorIfTty(' review before installing do not install blindly from rank alone', colors.dim));
50
62
  return lines.join('\n');
51
63
  }
52
- async function readLogo() {
64
+ async function readLogo(compact = false) {
65
+ const file = compact ? 'assets/cli/logo-compact.txt' : 'assets/cli/logo.txt';
53
66
  try {
54
- return await fs.readFile(getPackagePath('assets/cli/logo.txt'), 'utf8');
67
+ return await fs.readFile(getPackagePath(file), 'utf8');
55
68
  }
56
69
  catch {
57
- return 'PlugScout';
70
+ try {
71
+ return await fs.readFile(getPackagePath('assets/cli/logo.txt'), 'utf8');
72
+ }
73
+ catch {
74
+ return 'PlugScout';
75
+ }
58
76
  }
59
77
  }
60
78
  async function readPackageMeta() {
@@ -68,38 +86,32 @@ async function readPackageMeta() {
68
86
  }
69
87
  async function readCatalogStats() {
70
88
  const items = await loadCatalogItems();
71
- let skill = 0;
72
- let mcp = 0;
73
- let claudePlugin = 0;
74
- let claudeConnector = 0;
75
- let copilotExtension = 0;
89
+ let skill = 0, mcp = 0, claudePlugin = 0, claudeConnector = 0;
90
+ let copilotExtension = 0, cursorExtension = 0, geminiExtension = 0;
76
91
  items.forEach((item) => {
77
92
  if (item.kind === 'skill') {
78
93
  skill += 1;
79
- return;
80
94
  }
81
- if (item.kind === 'mcp') {
95
+ else if (item.kind === 'mcp') {
82
96
  mcp += 1;
83
- return;
84
97
  }
85
- if (item.kind === 'claude-plugin') {
98
+ else if (item.kind === 'claude-plugin') {
86
99
  claudePlugin += 1;
87
- return;
88
100
  }
89
- if (item.kind === 'claude-connector') {
101
+ else if (item.kind === 'claude-connector') {
90
102
  claudeConnector += 1;
91
- return;
92
103
  }
93
- copilotExtension += 1;
104
+ else if (item.kind === 'cursor-extension') {
105
+ cursorExtension += 1;
106
+ }
107
+ else if (item.kind === 'gemini-extension') {
108
+ geminiExtension += 1;
109
+ }
110
+ else {
111
+ copilotExtension += 1;
112
+ }
94
113
  });
95
- return {
96
- items: items.length,
97
- skill,
98
- mcp,
99
- claudePlugin,
100
- claudeConnector,
101
- copilotExtension
102
- };
114
+ return { items: items.length, skill, mcp, claudePlugin, claudeConnector, copilotExtension, cursorExtension, geminiExtension };
103
115
  }
104
116
  async function readRuntimeStats() {
105
117
  const [syncState, whitelist, quarantine] = await Promise.all([loadSyncState(), loadWhitelist(), loadQuarantine()]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shnitzel/plugscout",
3
- "version": "0.3.13",
3
+ "version": "0.3.14",
4
4
  "description": "Claude plugins + Claude connectors + Copilot extensions + Skills + MCP security intelligence framework",
5
5
  "private": false,
6
6
  "type": "module",