skillfish 1.0.17 → 1.0.18
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/README.md +57 -8
- package/dist/commands/add.js +2 -5
- package/dist/commands/init.js +2 -5
- package/dist/commands/list.js +12 -5
- package/dist/commands/remove.js +2 -5
- package/dist/commands/update.js +2 -5
- package/dist/index.js +40 -12
- package/dist/lib/banner.d.ts +14 -0
- package/dist/lib/banner.js +68 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -169,10 +169,52 @@ skillfish update --yes # Update all without prompting
|
|
|
169
169
|
skillfish update --json # Check for updates (JSON output)
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Non-Interactive Mode
|
|
175
|
+
|
|
176
|
+
All commands work without prompts for use in scripts, CI pipelines, and automation. Non-interactive mode activates when:
|
|
177
|
+
|
|
178
|
+
- The `--json` flag is passed, or
|
|
179
|
+
- stdin is not a TTY (piped input, CI runners, cron jobs)
|
|
180
|
+
|
|
181
|
+
In non-interactive mode, commands use default values where possible and error with guidance when required flags are missing.
|
|
182
|
+
|
|
183
|
+
### Required flags
|
|
184
|
+
|
|
185
|
+
| Command | Required | Defaults |
|
|
186
|
+
|---------|----------|----------|
|
|
187
|
+
| `add` | `<owner/repo>` + skill name, `--path`, or `--all` if repo has multiple skills | Location: global (`~/`), Agents: all detected |
|
|
188
|
+
| `init` | `--name`, `--description` | Location: project (`./`), Agents: all detected |
|
|
189
|
+
| `list` | (none) | Both locations, all agents |
|
|
190
|
+
| `remove` | Skill name or `--all` | Both locations, all agents |
|
|
191
|
+
| `update` | `--yes` to apply updates | All tracked skills |
|
|
192
|
+
|
|
193
|
+
All commands accept `--project` or `--global` to override the default location.
|
|
194
|
+
|
|
195
|
+
### Confirmation behavior
|
|
196
|
+
|
|
197
|
+
Confirmation prompts are skipped in non-interactive mode. Commands that modify skills (`add`, `init`, `remove`) proceed automatically. The `update` command is the exception: `--json` without `--yes` runs in **check-only mode**, reporting outdated skills without applying changes.
|
|
198
|
+
|
|
199
|
+
Use `--yes` to explicitly skip confirmations in interactive mode.
|
|
174
200
|
|
|
175
|
-
|
|
201
|
+
### JSON output
|
|
202
|
+
|
|
203
|
+
Pass `--json` to get structured output on stdout. All commands return a common shape:
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"success": true,
|
|
208
|
+
"exit_code": 0,
|
|
209
|
+
"errors": []
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Each command adds its own fields: `installed` and `skipped` (add), `created` and `skipped` (init), `removed` (remove), `outdated` and `updated` (update), `installed` and `agents_detected` (list).
|
|
214
|
+
|
|
215
|
+
### Exit codes
|
|
216
|
+
|
|
217
|
+
Exit codes are consistent across all commands:
|
|
176
218
|
|
|
177
219
|
| Code | Name | Meaning |
|
|
178
220
|
|------|------|---------|
|
|
@@ -182,14 +224,21 @@ Exit codes help agents and scripts understand command results without parsing er
|
|
|
182
224
|
| 3 | Network Error | Network failure (timeout, rate limit) |
|
|
183
225
|
| 4 | Not Found | Requested resource not found (skill, agent, repo) |
|
|
184
226
|
|
|
185
|
-
|
|
227
|
+
### CI example
|
|
186
228
|
|
|
187
229
|
```bash
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
```
|
|
230
|
+
# Install skills in CI (non-interactive, JSON output)
|
|
231
|
+
skillfish add owner/repo --yes --json
|
|
191
232
|
|
|
192
|
-
|
|
233
|
+
# Create a skill template in CI
|
|
234
|
+
skillfish init --name my-skill --description "My skill" --project --json
|
|
235
|
+
|
|
236
|
+
# Check for outdated skills without applying
|
|
237
|
+
skillfish update --json
|
|
238
|
+
|
|
239
|
+
# Apply updates
|
|
240
|
+
skillfish update --yes --json
|
|
241
|
+
```
|
|
193
242
|
|
|
194
243
|
---
|
|
195
244
|
|
package/dist/commands/add.js
CHANGED
|
@@ -6,6 +6,7 @@ import { homedir } from 'os';
|
|
|
6
6
|
import { dirname, basename } from 'path';
|
|
7
7
|
import * as p from '@clack/prompts';
|
|
8
8
|
import pc from 'picocolors';
|
|
9
|
+
import { printBanner } from '../lib/banner.js';
|
|
9
10
|
import { trackInstall } from '../telemetry.js';
|
|
10
11
|
import { isValidPath, parseFrontmatter, deriveSkillName, toTitleCase, truncate, batchMap, createJsonOutput, isInputTTY, isTTY, } from '../utils.js';
|
|
11
12
|
import { getDetectedAgents, AGENT_CONFIGS } from '../lib/agents.js';
|
|
@@ -67,11 +68,7 @@ Examples:
|
|
|
67
68
|
}
|
|
68
69
|
// Show banner and intro (TTY only, not in JSON mode)
|
|
69
70
|
if (isTTY() && !jsonMode) {
|
|
70
|
-
|
|
71
|
-
console.log(pc.cyan(' ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋'));
|
|
72
|
-
console.log(` ${pc.cyan('><>')} ${pc.bold('SKILL FISH')} ${pc.cyan('><>')}`);
|
|
73
|
-
console.log(pc.cyan(' ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋'));
|
|
74
|
-
console.log();
|
|
71
|
+
printBanner();
|
|
75
72
|
p.intro(`${pc.bgCyan(pc.black(' skillfish '))} ${pc.dim(`v${version}`)}`);
|
|
76
73
|
}
|
|
77
74
|
const force = options.force ?? false;
|
package/dist/commands/init.js
CHANGED
|
@@ -7,6 +7,7 @@ import { join } from 'path';
|
|
|
7
7
|
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
8
8
|
import * as p from '@clack/prompts';
|
|
9
9
|
import pc from 'picocolors';
|
|
10
|
+
import { printBanner } from '../lib/banner.js';
|
|
10
11
|
import { getDetectedAgents, getAgentSkillDir } from '../lib/agents.js';
|
|
11
12
|
import { SKILL_FILENAME } from '../lib/github.js';
|
|
12
13
|
import { EXIT_CODES } from '../lib/constants.js';
|
|
@@ -155,11 +156,7 @@ Examples:
|
|
|
155
156
|
}
|
|
156
157
|
// Show banner and intro (TTY only, not in JSON mode)
|
|
157
158
|
if (isTTY() && !jsonMode) {
|
|
158
|
-
|
|
159
|
-
console.log(pc.cyan(' ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋'));
|
|
160
|
-
console.log(` ${pc.cyan('><>')} ${pc.bold('SKILL FISH')} ${pc.cyan('><>')}`);
|
|
161
|
-
console.log(pc.cyan(' ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋'));
|
|
162
|
-
console.log();
|
|
159
|
+
printBanner();
|
|
163
160
|
p.intro(`${pc.bgCyan(pc.black(' skillfish '))} ${pc.dim(`v${version}`)} ${pc.dim('· Create a skill')}`);
|
|
164
161
|
}
|
|
165
162
|
const skipPrompts = options.yes ?? false;
|
package/dist/commands/list.js
CHANGED
|
@@ -6,10 +6,11 @@ import { homedir } from 'os';
|
|
|
6
6
|
import { join } from 'path';
|
|
7
7
|
import * as p from '@clack/prompts';
|
|
8
8
|
import pc from 'picocolors';
|
|
9
|
+
import { printBanner } from '../lib/banner.js';
|
|
9
10
|
import { getDetectedAgents, getAgentSkillDir } from '../lib/agents.js';
|
|
10
11
|
import { listInstalledSkillsInDir } from '../lib/installer.js';
|
|
11
12
|
import { EXIT_CODES } from '../lib/constants.js';
|
|
12
|
-
import { isInputTTY } from '../utils.js';
|
|
13
|
+
import { isTTY, isInputTTY } from '../utils.js';
|
|
13
14
|
export const listCommand = new Command('list')
|
|
14
15
|
.description('List installed skills across all detected agents')
|
|
15
16
|
.option('--project', 'List project-level skills only (./.claude)')
|
|
@@ -134,8 +135,10 @@ Examples:
|
|
|
134
135
|
agents_detected: detected.map((a) => a.name),
|
|
135
136
|
});
|
|
136
137
|
}
|
|
137
|
-
// Display intro
|
|
138
|
-
|
|
138
|
+
// Display intro (TTY only, not in JSON mode)
|
|
139
|
+
if (isTTY() && !jsonMode) {
|
|
140
|
+
printBanner();
|
|
141
|
+
}
|
|
139
142
|
p.intro(`${pc.bgCyan(pc.black(' skillfish '))} ${pc.dim(`Skills for ${found[0].name}`)}`);
|
|
140
143
|
if (globalSkills.length === 0 && projectSkills.length === 0) {
|
|
141
144
|
p.outro(pc.dim('No skills installed'));
|
|
@@ -184,7 +187,9 @@ Examples:
|
|
|
184
187
|
}
|
|
185
188
|
// Interactive mode: show agent selector
|
|
186
189
|
if (isInputTTY()) {
|
|
187
|
-
|
|
190
|
+
if (isTTY() && !jsonMode) {
|
|
191
|
+
printBanner();
|
|
192
|
+
}
|
|
188
193
|
p.intro(`${pc.bgCyan(pc.black(' skillfish '))} ${pc.dim('Installed skills')}`);
|
|
189
194
|
// Step 1: Build options with skill counts in label (always visible)
|
|
190
195
|
const agentOptions = detected.map((agent) => {
|
|
@@ -254,7 +259,9 @@ Examples:
|
|
|
254
259
|
}
|
|
255
260
|
// Non-interactive mode: display all agents with skills
|
|
256
261
|
const { installed, globalSkills, projectSkills } = collectSkills(detected);
|
|
257
|
-
|
|
262
|
+
if (isTTY() && !jsonMode) {
|
|
263
|
+
printBanner();
|
|
264
|
+
}
|
|
258
265
|
p.intro(`${pc.bgCyan(pc.black(' skillfish '))} ${pc.dim('Installed skills')}`);
|
|
259
266
|
console.log();
|
|
260
267
|
console.log(pc.bold('Detected Agents'));
|
package/dist/commands/remove.js
CHANGED
|
@@ -7,6 +7,7 @@ import { join } from 'path';
|
|
|
7
7
|
import { existsSync, rmSync } from 'fs';
|
|
8
8
|
import * as p from '@clack/prompts';
|
|
9
9
|
import pc from 'picocolors';
|
|
10
|
+
import { printBanner } from '../lib/banner.js';
|
|
10
11
|
import { getDetectedAgents, getAgentSkillDir } from '../lib/agents.js';
|
|
11
12
|
import { listInstalledSkillsInDir } from '../lib/installer.js';
|
|
12
13
|
import { isTTY, isInputTTY } from '../utils.js';
|
|
@@ -63,11 +64,7 @@ Examples:
|
|
|
63
64
|
}
|
|
64
65
|
// Show banner (TTY only, not in JSON mode)
|
|
65
66
|
if (isTTY() && !jsonMode) {
|
|
66
|
-
|
|
67
|
-
console.log(pc.cyan(' ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋'));
|
|
68
|
-
console.log(` ${pc.cyan('><>')} ${pc.bold('SKILL FISH')} ${pc.cyan('><>')}`);
|
|
69
|
-
console.log(pc.cyan(' ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋'));
|
|
70
|
-
console.log();
|
|
67
|
+
printBanner();
|
|
71
68
|
p.intro(`${pc.bgCyan(pc.black(' skillfish '))} ${pc.dim(`v${version}`)}`);
|
|
72
69
|
}
|
|
73
70
|
const skipConfirm = options.yes ?? false;
|
package/dist/commands/update.js
CHANGED
|
@@ -6,6 +6,7 @@ import { homedir } from 'os';
|
|
|
6
6
|
import { join } from 'path';
|
|
7
7
|
import * as p from '@clack/prompts';
|
|
8
8
|
import pc from 'picocolors';
|
|
9
|
+
import { printBanner } from '../lib/banner.js';
|
|
9
10
|
import { getDetectedAgents, getAgentSkillDir } from '../lib/agents.js';
|
|
10
11
|
import { listInstalledSkillsInDir, installSkill } from '../lib/installer.js';
|
|
11
12
|
import { readManifest } from '../lib/manifest.js';
|
|
@@ -54,11 +55,7 @@ Examples:
|
|
|
54
55
|
}
|
|
55
56
|
// Show banner (TTY only, not in JSON mode)
|
|
56
57
|
if (isTTY() && !jsonMode) {
|
|
57
|
-
|
|
58
|
-
console.log(pc.cyan(' ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋'));
|
|
59
|
-
console.log(` ${pc.cyan('><>')} ${pc.bold('SKILL FISH')} ${pc.cyan('><>')}`);
|
|
60
|
-
console.log(pc.cyan(' ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋'));
|
|
61
|
-
console.log();
|
|
58
|
+
printBanner();
|
|
62
59
|
p.intro(`${pc.bgCyan(pc.black(' skillfish '))} ${pc.dim(`v${version}`)}`);
|
|
63
60
|
}
|
|
64
61
|
// Detect agents
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,9 @@ import { Command } from 'commander';
|
|
|
8
8
|
import { readFileSync } from 'fs';
|
|
9
9
|
import { fileURLToPath } from 'url';
|
|
10
10
|
import { dirname, join } from 'path';
|
|
11
|
+
import pc from 'picocolors';
|
|
11
12
|
import updateNotifier from 'update-notifier';
|
|
13
|
+
import { getBannerText } from './lib/banner.js';
|
|
12
14
|
import { addCommand } from './commands/add.js';
|
|
13
15
|
import { initCommand } from './commands/init.js';
|
|
14
16
|
import { listCommand } from './commands/list.js';
|
|
@@ -19,6 +21,16 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
19
21
|
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
20
22
|
// Check for updates (runs in background, non-blocking)
|
|
21
23
|
const notifier = updateNotifier({ pkg });
|
|
24
|
+
// Shared help styling for all commands
|
|
25
|
+
const helpStyles = {
|
|
26
|
+
sortSubcommands: true,
|
|
27
|
+
styleTitle: (str) => pc.bold(pc.underline(str)),
|
|
28
|
+
styleCommandText: (str) => pc.bold(pc.cyan(str)),
|
|
29
|
+
styleSubcommandText: (str) => pc.cyan(str),
|
|
30
|
+
styleOptionText: (str) => pc.yellow(str),
|
|
31
|
+
styleArgumentText: (str) => pc.dim(str),
|
|
32
|
+
styleDescriptionText: (str) => pc.dim(str),
|
|
33
|
+
};
|
|
22
34
|
const program = new Command()
|
|
23
35
|
.name('skillfish')
|
|
24
36
|
.description('Install and manage AI agent skills from GitHub repositories')
|
|
@@ -31,18 +43,30 @@ const program = new Command()
|
|
|
31
43
|
writeOut: (str) => process.stdout.write(str),
|
|
32
44
|
writeErr: (str) => process.stderr.write(str),
|
|
33
45
|
})
|
|
34
|
-
.configureHelp(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
.configureHelp(helpStyles)
|
|
47
|
+
.addHelpText('beforeAll', () => (process.stdout.isTTY ? getBannerText() : ''))
|
|
48
|
+
.addHelpText('after', () => {
|
|
49
|
+
const isTTY = process.stdout.isTTY;
|
|
50
|
+
const examples = [
|
|
51
|
+
['skillfish add owner/repo', 'Install skills from a repository'],
|
|
52
|
+
['skillfish add owner/repo/plugin/skill', 'Install a specific skill'],
|
|
53
|
+
['skillfish init', 'Create a new skill template'],
|
|
54
|
+
['skillfish list', 'Show installed skills'],
|
|
55
|
+
['skillfish remove my-skill', 'Remove a skill'],
|
|
56
|
+
];
|
|
57
|
+
const title = isTTY ? pc.bold(pc.underline('Examples:')) : 'Examples:';
|
|
58
|
+
const lines = examples.map(([cmd, desc]) => {
|
|
59
|
+
const prefix = isTTY ? pc.dim(' $ ') : ' $ ';
|
|
60
|
+
const command = isTTY ? pc.cyan(cmd) : cmd;
|
|
61
|
+
// Pad to align descriptions
|
|
62
|
+
const padding = ' '.repeat(Math.max(1, 42 - cmd.length));
|
|
63
|
+
const description = isTTY ? pc.dim(desc) : desc;
|
|
64
|
+
return `${prefix}${command}${padding}${description}`;
|
|
65
|
+
});
|
|
66
|
+
const docUrl = isTTY ? pc.bold(pc.cyan('https://skill.fish')) : 'https://skill.fish';
|
|
67
|
+
const docLabel = isTTY ? pc.dim('Documentation:') : 'Documentation:';
|
|
68
|
+
return `\n${title}\n${lines.join('\n')}\n\n${docLabel} ${docUrl}`;
|
|
69
|
+
});
|
|
46
70
|
// Store version in options for commands to access
|
|
47
71
|
program.hook('preAction', (thisCommand) => {
|
|
48
72
|
thisCommand.setOptionValue('version', pkg.version);
|
|
@@ -53,6 +77,10 @@ program.addCommand(initCommand);
|
|
|
53
77
|
program.addCommand(listCommand);
|
|
54
78
|
program.addCommand(removeCommand);
|
|
55
79
|
program.addCommand(updateCommand);
|
|
80
|
+
// Propagate help styling to all subcommands (must run after all addCommand() calls)
|
|
81
|
+
for (const cmd of program.commands) {
|
|
82
|
+
cmd.configureHelp(helpStyles);
|
|
83
|
+
}
|
|
56
84
|
// Handle --json flag for help output
|
|
57
85
|
program.on('option:json', () => {
|
|
58
86
|
// JSON mode is handled by commands
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared ASCII art logo and banner display for skillfish CLI.
|
|
3
|
+
*/
|
|
4
|
+
export declare const LOGO_LINES: readonly [" ███████╗██╗ ██╗██╗██╗ ██╗ ███████╗██╗███████╗██╗ ██╗", " ██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝██║██╔════╝██║ ██║", " ███████╗█████╔╝ ██║██║ ██║ █████╗ ██║███████╗███████║", " ╚════██║██╔═██╗ ██║██║ ██║ ██╔══╝ ██║╚════██║██╔══██║", " ███████║██║ ██╗██║███████╗███████╗██╗██║ ██║███████║██║ ██║", " ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝"];
|
|
5
|
+
/**
|
|
6
|
+
* Get the colored banner as a string.
|
|
7
|
+
* Returns the colored logo + tagline, or plain text when colors are disabled.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getBannerText(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Print the colored ASCII art banner with tagline.
|
|
12
|
+
* Only outputs when stdout is a TTY.
|
|
13
|
+
*/
|
|
14
|
+
export declare function printBanner(): void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared ASCII art logo and banner display for skillfish CLI.
|
|
3
|
+
*/
|
|
4
|
+
import pc from 'picocolors';
|
|
5
|
+
import { isTTY } from '../utils.js';
|
|
6
|
+
export const LOGO_LINES = [
|
|
7
|
+
' ███████╗██╗ ██╗██╗██╗ ██╗ ███████╗██╗███████╗██╗ ██╗',
|
|
8
|
+
' ██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝██║██╔════╝██║ ██║',
|
|
9
|
+
' ███████╗█████╔╝ ██║██║ ██║ █████╗ ██║███████╗███████║',
|
|
10
|
+
' ╚════██║██╔═██╗ ██║██║ ██║ ██╔══╝ ██║╚════██║██╔══██║',
|
|
11
|
+
' ███████║██║ ██╗██║███████╗███████╗██╗██║ ██║███████║██║ ██║',
|
|
12
|
+
' ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝',
|
|
13
|
+
];
|
|
14
|
+
// Ocean gradient colors (top to bottom): light cyan → deeper blue
|
|
15
|
+
// All colors kept bright enough to be readable on dark backgrounds
|
|
16
|
+
// Length must match LOGO_LINES (one color per line).
|
|
17
|
+
const GRADIENT_COLORS = [
|
|
18
|
+
[0, 230, 255],
|
|
19
|
+
[0, 210, 250],
|
|
20
|
+
[0, 190, 240],
|
|
21
|
+
[0, 170, 230],
|
|
22
|
+
[0, 155, 220],
|
|
23
|
+
[0, 140, 210],
|
|
24
|
+
];
|
|
25
|
+
/** Check if colors are disabled via NO_COLOR convention (https://no-color.org). */
|
|
26
|
+
function isColorDisabled() {
|
|
27
|
+
return 'NO_COLOR' in process.env;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if the terminal supports truecolor (24-bit) via COLORTERM env var.
|
|
31
|
+
*/
|
|
32
|
+
function supportsTruecolor() {
|
|
33
|
+
if (isColorDisabled())
|
|
34
|
+
return false;
|
|
35
|
+
const ct = process.env.COLORTERM;
|
|
36
|
+
return ct === 'truecolor' || ct === '24bit';
|
|
37
|
+
}
|
|
38
|
+
/** Apply truecolor gradient, fall back to picocolors cyan. */
|
|
39
|
+
function colorLine(line, index) {
|
|
40
|
+
if (supportsTruecolor()) {
|
|
41
|
+
const color = GRADIENT_COLORS[index % GRADIENT_COLORS.length];
|
|
42
|
+
const [r, g, b] = color;
|
|
43
|
+
return `\x1b[38;2;${r};${g};${b}m${line}\x1b[0m`;
|
|
44
|
+
}
|
|
45
|
+
return pc.cyan(line);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get the colored banner as a string.
|
|
49
|
+
* Returns the colored logo + tagline, or plain text when colors are disabled.
|
|
50
|
+
*/
|
|
51
|
+
export function getBannerText() {
|
|
52
|
+
const lines = [''];
|
|
53
|
+
for (let i = 0; i < LOGO_LINES.length; i++) {
|
|
54
|
+
lines.push(colorLine(LOGO_LINES[i], i));
|
|
55
|
+
}
|
|
56
|
+
lines.push(` ${pc.dim('The Skill Manager for AI Coding Agents')} — ${pc.bold(pc.cyan('https://skill.fish'))}`);
|
|
57
|
+
lines.push('');
|
|
58
|
+
return lines.join('\n');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Print the colored ASCII art banner with tagline.
|
|
62
|
+
* Only outputs when stdout is a TTY.
|
|
63
|
+
*/
|
|
64
|
+
export function printBanner() {
|
|
65
|
+
if (!isTTY())
|
|
66
|
+
return;
|
|
67
|
+
console.log(getBannerText());
|
|
68
|
+
}
|
package/package.json
CHANGED