@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,
|
|
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(
|
|
28
|
-
lines.push(
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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('
|
|
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('
|
|
47
|
-
lines.push('
|
|
48
|
-
lines.push('
|
|
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(
|
|
67
|
+
return await fs.readFile(getPackagePath(file), 'utf8');
|
|
55
68
|
}
|
|
56
69
|
catch {
|
|
57
|
-
|
|
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
|
|
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
|
-
|
|
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