skilluse 0.1.0
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 +100 -0
- package/dist/app.d.ts +6 -0
- package/dist/app.js +6 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +167 -0
- package/dist/commands/demo.d.ts +14 -0
- package/dist/commands/demo.js +46 -0
- package/dist/commands/index.d.ts +8 -0
- package/dist/commands/index.js +77 -0
- package/dist/commands/list.d.ts +14 -0
- package/dist/commands/list.js +54 -0
- package/dist/commands/login.d.ts +14 -0
- package/dist/commands/login.js +153 -0
- package/dist/commands/logout.d.ts +8 -0
- package/dist/commands/logout.js +47 -0
- package/dist/commands/repo/add.d.ts +22 -0
- package/dist/commands/repo/add.js +139 -0
- package/dist/commands/repo/edit.d.ts +19 -0
- package/dist/commands/repo/edit.js +117 -0
- package/dist/commands/repo/index.d.ts +8 -0
- package/dist/commands/repo/index.js +47 -0
- package/dist/commands/repo/list.d.ts +8 -0
- package/dist/commands/repo/list.js +47 -0
- package/dist/commands/repo/remove.d.ts +16 -0
- package/dist/commands/repo/remove.js +83 -0
- package/dist/commands/repo/sync.d.ts +10 -0
- package/dist/commands/repo/sync.js +78 -0
- package/dist/commands/repo/use.d.ts +10 -0
- package/dist/commands/repo/use.js +56 -0
- package/dist/commands/repos.d.ts +11 -0
- package/dist/commands/repos.js +50 -0
- package/dist/commands/search.d.ts +16 -0
- package/dist/commands/search.js +199 -0
- package/dist/commands/skills.d.ts +11 -0
- package/dist/commands/skills.js +43 -0
- package/dist/commands/whoami.d.ts +8 -0
- package/dist/commands/whoami.js +69 -0
- package/dist/components/CLIError.d.ts +27 -0
- package/dist/components/CLIError.js +24 -0
- package/dist/components/ProgressBar.d.ts +7 -0
- package/dist/components/ProgressBar.js +9 -0
- package/dist/components/Select.d.ts +11 -0
- package/dist/components/Select.js +6 -0
- package/dist/components/Spinner.d.ts +6 -0
- package/dist/components/Spinner.js +7 -0
- package/dist/components/StatusMessage.d.ts +9 -0
- package/dist/components/StatusMessage.js +13 -0
- package/dist/components/Table.d.ts +9 -0
- package/dist/components/Table.js +27 -0
- package/dist/components/TextInput.d.ts +9 -0
- package/dist/components/TextInput.js +6 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.js +8 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +43815 -0
- package/dist/services/credentials.d.ts +69 -0
- package/dist/services/credentials.js +216 -0
- package/dist/services/index.d.ts +6 -0
- package/dist/services/index.js +10 -0
- package/dist/services/oauth.d.ts +106 -0
- package/dist/services/oauth.js +208 -0
- package/dist/services/paths.d.ts +19 -0
- package/dist/services/paths.js +21 -0
- package/dist/services/store.d.ts +64 -0
- package/dist/services/store.js +107 -0
- package/dist/services/update.d.ts +20 -0
- package/dist/services/update.js +93 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Skilluse CLI
|
|
2
|
+
|
|
3
|
+
CLI tool for managing and installing AI Coding Agent Skills.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g skilluse
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Login to GitHub
|
|
15
|
+
skilluse login
|
|
16
|
+
|
|
17
|
+
# Add a skill repository
|
|
18
|
+
skilluse repo add owner/skill-repo
|
|
19
|
+
|
|
20
|
+
# Search for skills
|
|
21
|
+
skilluse search code-review
|
|
22
|
+
|
|
23
|
+
# Install a skill
|
|
24
|
+
skilluse install code-review
|
|
25
|
+
|
|
26
|
+
# List installed skills
|
|
27
|
+
skilluse list
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Commands
|
|
31
|
+
|
|
32
|
+
### Authentication
|
|
33
|
+
|
|
34
|
+
| Command | Description |
|
|
35
|
+
|---------|-------------|
|
|
36
|
+
| `skilluse` | Show status (user, repos, installed count) |
|
|
37
|
+
| `skilluse login` | Authenticate with GitHub |
|
|
38
|
+
| `skilluse logout` | Clear stored credentials |
|
|
39
|
+
|
|
40
|
+
### Repository Management
|
|
41
|
+
|
|
42
|
+
| Command | Description |
|
|
43
|
+
|---------|-------------|
|
|
44
|
+
| `skilluse repo list` | List configured repositories |
|
|
45
|
+
| `skilluse repo add <repo>` | Add a skill repository |
|
|
46
|
+
| `skilluse repo remove <name>` | Remove a repository |
|
|
47
|
+
| `skilluse repo use <name>` | Set default repository |
|
|
48
|
+
| `skilluse repo edit <name>` | Edit repository settings |
|
|
49
|
+
|
|
50
|
+
### Skill Management
|
|
51
|
+
|
|
52
|
+
| Command | Description |
|
|
53
|
+
|---------|-------------|
|
|
54
|
+
| `skilluse search <keyword>` | Search for skills |
|
|
55
|
+
| `skilluse install <skill>` | Install skill locally |
|
|
56
|
+
| `skilluse install <skill> --global` | Install globally |
|
|
57
|
+
| `skilluse uninstall <skill>` | Remove installed skill |
|
|
58
|
+
| `skilluse upgrade [skill]` | Upgrade skill(s) to latest |
|
|
59
|
+
| `skilluse list` | List installed skills |
|
|
60
|
+
| `skilluse list --outdated` | Show skills with updates |
|
|
61
|
+
| `skilluse info <skill>` | Show skill details |
|
|
62
|
+
|
|
63
|
+
## Authentication
|
|
64
|
+
|
|
65
|
+
Skilluse uses GitHub App OAuth for authentication.
|
|
66
|
+
|
|
67
|
+
### First-Time Login
|
|
68
|
+
|
|
69
|
+
1. Run `skilluse login`
|
|
70
|
+
2. Enter the code shown in your browser
|
|
71
|
+
3. Install the GitHub App when prompted
|
|
72
|
+
4. Select repository access (all or specific repos)
|
|
73
|
+
|
|
74
|
+
### Managing Repository Access
|
|
75
|
+
|
|
76
|
+
Modify access at: https://github.com/settings/installations
|
|
77
|
+
|
|
78
|
+
### Logging Out
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
skilluse logout
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Install Locations
|
|
85
|
+
|
|
86
|
+
| Scope | Path |
|
|
87
|
+
|-------|------|
|
|
88
|
+
| Local | `./.claude/skills/<name>/` |
|
|
89
|
+
| Global | `~/.claude/skills/<name>/` |
|
|
90
|
+
|
|
91
|
+
## Security
|
|
92
|
+
|
|
93
|
+
- **User tokens** stored in system keychain (macOS/Windows/Linux)
|
|
94
|
+
- **Fallback** to encrypted file if keychain unavailable
|
|
95
|
+
|
|
96
|
+
## Environment Variables
|
|
97
|
+
|
|
98
|
+
| Variable | Description |
|
|
99
|
+
|----------|-------------|
|
|
100
|
+
| `SKILLUSE_GITHUB_CLIENT_ID` | Override GitHub App client ID (dev only) |
|
package/dist/app.d.ts
ADDED
package/dist/app.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
export default function App({ name = "skilluse" }) {
|
|
4
|
+
return (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { color: "green", children: [name, " - AI Coding Agent Skills Manager"] }) }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=app.js.map
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Static CLI entry point for compiled binaries.
|
|
5
|
+
* This file imports all commands statically to work with Bun's single-file compilation.
|
|
6
|
+
*
|
|
7
|
+
* For development, use src/index.tsx which uses Pastel's dynamic command discovery.
|
|
8
|
+
*/
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
import { render } from "ink";
|
|
11
|
+
// Import all commands statically
|
|
12
|
+
import Demo, { options as demoOptions } from "./commands/demo.js";
|
|
13
|
+
import Login, { options as loginOptions } from "./commands/login.js";
|
|
14
|
+
import Logout from "./commands/logout.js";
|
|
15
|
+
import Whoami from "./commands/whoami.js";
|
|
16
|
+
import Repos from "./commands/repos.js";
|
|
17
|
+
import Skills from "./commands/skills.js";
|
|
18
|
+
import List, { options as listOptions } from "./commands/list.js";
|
|
19
|
+
import Search, { args as searchArgs, options as searchOptions } from "./commands/search.js";
|
|
20
|
+
// Import repo subcommands
|
|
21
|
+
import RepoIndex from "./commands/repo/index.js";
|
|
22
|
+
import RepoList from "./commands/repo/list.js";
|
|
23
|
+
import RepoAdd, { args as repoAddArgs, options as repoAddOptions } from "./commands/repo/add.js";
|
|
24
|
+
import RepoRemove, { args as repoRemoveArgs, options as repoRemoveOptions } from "./commands/repo/remove.js";
|
|
25
|
+
import RepoEdit, { args as repoEditArgs, options as repoEditOptions } from "./commands/repo/edit.js";
|
|
26
|
+
import RepoSync, { args as repoSyncArgs, options as repoSyncOptions } from "./commands/repo/sync.js";
|
|
27
|
+
import RepoUse, { args as repoUseArgs } from "./commands/repo/use.js";
|
|
28
|
+
// Version injected via --define at build time, fallback to package.json
|
|
29
|
+
const VERSION = process.env.VERSION || "0.1.0";
|
|
30
|
+
const BUILD_TIME = process.env.BUILD_TIME || new Date().toISOString();
|
|
31
|
+
const program = new Command();
|
|
32
|
+
program
|
|
33
|
+
.name("skilluse")
|
|
34
|
+
.description("CLI tool for managing and installing AI Coding Agent Skills")
|
|
35
|
+
.version(VERSION, "-v, --version", "Show version number")
|
|
36
|
+
.option("--version-verbose", "Show version with build info")
|
|
37
|
+
.on("option:version-verbose", () => {
|
|
38
|
+
console.log(`skilluse ${VERSION}`);
|
|
39
|
+
console.log(`Built: ${BUILD_TIME}`);
|
|
40
|
+
process.exit(0);
|
|
41
|
+
});
|
|
42
|
+
// demo command
|
|
43
|
+
program
|
|
44
|
+
.command("demo")
|
|
45
|
+
.description("Demo UI components")
|
|
46
|
+
.option("-a, --all", "Show all components")
|
|
47
|
+
.action((opts) => {
|
|
48
|
+
const options = demoOptions.parse(opts);
|
|
49
|
+
render(_jsx(Demo, { options: options }));
|
|
50
|
+
});
|
|
51
|
+
// login command
|
|
52
|
+
program
|
|
53
|
+
.command("login")
|
|
54
|
+
.description("Authenticate with GitHub")
|
|
55
|
+
.option("-f, --force", "Force re-authentication")
|
|
56
|
+
.action((opts) => {
|
|
57
|
+
const options = loginOptions.parse(opts);
|
|
58
|
+
render(_jsx(Login, { options: options }));
|
|
59
|
+
});
|
|
60
|
+
// logout command
|
|
61
|
+
program
|
|
62
|
+
.command("logout")
|
|
63
|
+
.description("Clear stored credentials")
|
|
64
|
+
.action(() => {
|
|
65
|
+
render(_jsx(Logout, { options: {} }));
|
|
66
|
+
});
|
|
67
|
+
// whoami command
|
|
68
|
+
program
|
|
69
|
+
.command("whoami")
|
|
70
|
+
.description("Show current user info")
|
|
71
|
+
.action(() => {
|
|
72
|
+
render(_jsx(Whoami, { options: {} }));
|
|
73
|
+
});
|
|
74
|
+
// repos command
|
|
75
|
+
program
|
|
76
|
+
.command("repos")
|
|
77
|
+
.description("List accessible GitHub repositories")
|
|
78
|
+
.action(() => {
|
|
79
|
+
render(_jsx(Repos, { options: {} }));
|
|
80
|
+
});
|
|
81
|
+
// skills command
|
|
82
|
+
program
|
|
83
|
+
.command("skills")
|
|
84
|
+
.description("List installed skills")
|
|
85
|
+
.action(() => {
|
|
86
|
+
render(_jsx(Skills, { options: {} }));
|
|
87
|
+
});
|
|
88
|
+
// list command
|
|
89
|
+
program
|
|
90
|
+
.command("list")
|
|
91
|
+
.description("List skills from a repository")
|
|
92
|
+
.option("-r, --repo <repo>", "Repository to list skills from")
|
|
93
|
+
.action((opts) => {
|
|
94
|
+
const options = listOptions.parse(opts);
|
|
95
|
+
render(_jsx(List, { options: options }));
|
|
96
|
+
});
|
|
97
|
+
// search command
|
|
98
|
+
program
|
|
99
|
+
.command("search <keyword>")
|
|
100
|
+
.description("Search for skills")
|
|
101
|
+
.option("-a, --all", "Search in all configured repos")
|
|
102
|
+
.action((keyword, opts) => {
|
|
103
|
+
const args = searchArgs.parse([keyword]);
|
|
104
|
+
const options = searchOptions.parse(opts);
|
|
105
|
+
render(_jsx(Search, { args: args, options: options }));
|
|
106
|
+
});
|
|
107
|
+
// repo command group
|
|
108
|
+
const repoCmd = program
|
|
109
|
+
.command("repo")
|
|
110
|
+
.description("Manage skill repositories");
|
|
111
|
+
repoCmd
|
|
112
|
+
.command("list")
|
|
113
|
+
.description("List configured repositories")
|
|
114
|
+
.action(() => {
|
|
115
|
+
render(_jsx(RepoList, { options: {} }));
|
|
116
|
+
});
|
|
117
|
+
repoCmd
|
|
118
|
+
.command("add <url>")
|
|
119
|
+
.description("Add a skill repository")
|
|
120
|
+
.option("-p, --path <path>", "Skill path within the repo")
|
|
121
|
+
.option("-b, --branch <branch>", "Branch to use")
|
|
122
|
+
.option("-d, --default", "Set as default repository")
|
|
123
|
+
.action((url, opts) => {
|
|
124
|
+
const args = repoAddArgs.parse([url]);
|
|
125
|
+
const options = repoAddOptions.parse(opts);
|
|
126
|
+
render(_jsx(RepoAdd, { args: args, options: options }));
|
|
127
|
+
});
|
|
128
|
+
repoCmd
|
|
129
|
+
.command("remove <name>")
|
|
130
|
+
.description("Remove a repository")
|
|
131
|
+
.option("-f, --force", "Skip confirmation")
|
|
132
|
+
.action((name, opts) => {
|
|
133
|
+
const args = repoRemoveArgs.parse([name]);
|
|
134
|
+
const options = repoRemoveOptions.parse(opts);
|
|
135
|
+
render(_jsx(RepoRemove, { args: args, options: options }));
|
|
136
|
+
});
|
|
137
|
+
repoCmd
|
|
138
|
+
.command("edit <name>")
|
|
139
|
+
.description("Edit repository settings")
|
|
140
|
+
.option("-p, --path <path>", "New skill path")
|
|
141
|
+
.option("-b, --branch <branch>", "New branch")
|
|
142
|
+
.action((name, opts) => {
|
|
143
|
+
const args = repoEditArgs.parse([name]);
|
|
144
|
+
const options = repoEditOptions.parse(opts);
|
|
145
|
+
render(_jsx(RepoEdit, { args: args, options: options }));
|
|
146
|
+
});
|
|
147
|
+
repoCmd
|
|
148
|
+
.command("sync [name]")
|
|
149
|
+
.description("Sync repository metadata")
|
|
150
|
+
.action((name, _opts) => {
|
|
151
|
+
const args = repoSyncArgs.parse([name || undefined]);
|
|
152
|
+
const options = repoSyncOptions.parse({});
|
|
153
|
+
render(_jsx(RepoSync, { args: args, options: options }));
|
|
154
|
+
});
|
|
155
|
+
repoCmd
|
|
156
|
+
.command("use <name>")
|
|
157
|
+
.description("Set default repository")
|
|
158
|
+
.action((name, _opts) => {
|
|
159
|
+
const args = repoUseArgs.parse([name]);
|
|
160
|
+
render(_jsx(RepoUse, { args: args, options: {} }));
|
|
161
|
+
});
|
|
162
|
+
// Default action shows help when just 'repo' is called
|
|
163
|
+
repoCmd.action(() => {
|
|
164
|
+
render(_jsx(RepoIndex, { options: {} }));
|
|
165
|
+
});
|
|
166
|
+
program.parse();
|
|
167
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const options: z.ZodObject<{
|
|
3
|
+
component: z.ZodDefault<z.ZodEnum<["spinner", "select", "table", "progress", "status", "input", "all"]>>;
|
|
4
|
+
}, "strip", z.ZodTypeAny, {
|
|
5
|
+
component: "spinner" | "select" | "table" | "progress" | "status" | "input" | "all";
|
|
6
|
+
}, {
|
|
7
|
+
component?: "spinner" | "select" | "table" | "progress" | "status" | "input" | "all" | undefined;
|
|
8
|
+
}>;
|
|
9
|
+
interface Props {
|
|
10
|
+
options: z.infer<typeof options>;
|
|
11
|
+
}
|
|
12
|
+
export default function Demo({ options: opts }: Props): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=demo.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Box, Text } from "ink";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { Spinner, Select, Table, ProgressBar, StatusMessage, TextInput, } from "../components/index.js";
|
|
6
|
+
export const options = z.object({
|
|
7
|
+
component: z
|
|
8
|
+
.enum(["spinner", "select", "table", "progress", "status", "input", "all"])
|
|
9
|
+
.default("all")
|
|
10
|
+
.describe("Component to demo"),
|
|
11
|
+
});
|
|
12
|
+
function SpinnerDemo() {
|
|
13
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "Spinner Component:" }), _jsx(Spinner, { text: "Loading..." })] }));
|
|
14
|
+
}
|
|
15
|
+
function SelectDemo() {
|
|
16
|
+
const [selected, setSelected] = useState(null);
|
|
17
|
+
const items = [
|
|
18
|
+
{ label: "Option 1", value: "1" },
|
|
19
|
+
{ label: "Option 2", value: "2" },
|
|
20
|
+
{ label: "Option 3", value: "3" },
|
|
21
|
+
];
|
|
22
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "Select Component:" }), selected ? (_jsxs(Text, { children: ["Selected: ", selected] })) : (_jsx(Select, { items: items, onSelect: (item) => setSelected(item.value) }))] }));
|
|
23
|
+
}
|
|
24
|
+
function TableDemo() {
|
|
25
|
+
const data = [
|
|
26
|
+
{ name: "skill-1", version: "1.0.0", status: "installed" },
|
|
27
|
+
{ name: "skill-2", version: "2.1.0", status: "available" },
|
|
28
|
+
{ name: "skill-3", version: "0.5.0", status: "installed" },
|
|
29
|
+
];
|
|
30
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "Table Component:" }), _jsx(Table, { data: data, columns: ["name", "version", "status"] })] }));
|
|
31
|
+
}
|
|
32
|
+
function ProgressDemo() {
|
|
33
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "ProgressBar Component:" }), _jsx(ProgressBar, { percent: 0, width: 20 }), _jsx(ProgressBar, { percent: 50, width: 20 }), _jsx(ProgressBar, { percent: 100, width: 20 })] }));
|
|
34
|
+
}
|
|
35
|
+
function StatusDemo() {
|
|
36
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "StatusMessage Component:" }), _jsx(StatusMessage, { type: "success", children: "Operation completed" }), _jsx(StatusMessage, { type: "error", children: "Something went wrong" }), _jsx(StatusMessage, { type: "warning", children: "Proceed with caution" })] }));
|
|
37
|
+
}
|
|
38
|
+
function TextInputDemo() {
|
|
39
|
+
const [value, setValue] = useState("");
|
|
40
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "TextInput Component:" }), _jsxs(Box, { children: [_jsx(Text, { children: "Enter text: " }), _jsx(TextInput, { value: value, onChange: setValue, placeholder: "Type something..." })] }), value && _jsxs(Text, { dimColor: true, children: ["You typed: ", value] })] }));
|
|
41
|
+
}
|
|
42
|
+
export default function Demo({ options: opts }) {
|
|
43
|
+
const { component } = opts;
|
|
44
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "green", bold: true, children: "UI Components Demo" }), (component === "all" || component === "spinner") && _jsx(SpinnerDemo, {}), (component === "all" || component === "select") && _jsx(SelectDemo, {}), (component === "all" || component === "table") && _jsx(TableDemo, {}), (component === "all" || component === "progress") && _jsx(ProgressDemo, {}), (component === "all" || component === "status") && _jsx(StatusDemo, {}), (component === "all" || component === "input") && _jsx(TextInputDemo, {})] }));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=demo.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const options: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
|
|
3
|
+
interface Props {
|
|
4
|
+
options: z.infer<typeof options>;
|
|
5
|
+
}
|
|
6
|
+
export default function Index(_props: Props): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { Box, Text, useApp } from "ink";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { Spinner, StatusMessage } from "../components/index.js";
|
|
6
|
+
import { getCredentials, getConfig, getInstallations, checkForUpdate, getCurrentVersion, } from "../services/index.js";
|
|
7
|
+
export const options = z.object({});
|
|
8
|
+
export default function Index(_props) {
|
|
9
|
+
const { exit } = useApp();
|
|
10
|
+
const [state, setState] = useState({ phase: "checking" });
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
async function checkStatus() {
|
|
13
|
+
// Check if logged in
|
|
14
|
+
const credentials = await getCredentials();
|
|
15
|
+
if (!credentials) {
|
|
16
|
+
setState({ phase: "not_logged_in" });
|
|
17
|
+
exit();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
// Fetch user info from GitHub
|
|
21
|
+
try {
|
|
22
|
+
const response = await fetch("https://api.github.com/user", {
|
|
23
|
+
headers: {
|
|
24
|
+
Authorization: `Bearer ${credentials.token}`,
|
|
25
|
+
Accept: "application/vnd.github+json",
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
if (response.status === 401) {
|
|
30
|
+
setState({ phase: "not_logged_in" });
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
setState({
|
|
34
|
+
phase: "error",
|
|
35
|
+
message: `GitHub API error: ${response.status}`,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
exit();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const userData = (await response.json());
|
|
42
|
+
const config = getConfig();
|
|
43
|
+
const installations = getInstallations();
|
|
44
|
+
// Check for updates (non-blocking, uses cache)
|
|
45
|
+
const updateInfo = await checkForUpdate();
|
|
46
|
+
setState({
|
|
47
|
+
phase: "logged_in",
|
|
48
|
+
user: userData,
|
|
49
|
+
defaultRepo: config.defaultRepo,
|
|
50
|
+
installedCount: config.installed.length,
|
|
51
|
+
repoCount: config.repos.length,
|
|
52
|
+
installations,
|
|
53
|
+
updateInfo,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
setState({
|
|
58
|
+
phase: "error",
|
|
59
|
+
message: err instanceof Error ? err.message : "Failed to fetch status",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
exit();
|
|
63
|
+
}
|
|
64
|
+
checkStatus();
|
|
65
|
+
}, [exit]);
|
|
66
|
+
switch (state.phase) {
|
|
67
|
+
case "checking":
|
|
68
|
+
return _jsx(Spinner, { text: "Loading..." });
|
|
69
|
+
case "not_logged_in":
|
|
70
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "green", bold: true, children: "Welcome to skilluse!" }) }), _jsx(Text, { dimColor: true, children: "Let's get you set up:" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: " 1. " }), _jsx(Text, { children: "skilluse login " }), _jsx(Text, { dimColor: true, children: "Connect to GitHub" })] }), _jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: " 2. " }), _jsx(Text, { children: "skilluse repo add " }), _jsx(Text, { dimColor: true, children: "Add a skill repository" })] }), _jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: " 3. " }), _jsx(Text, { children: "skilluse search " }), _jsx(Text, { dimColor: true, children: "Find skills to install" })] })] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { children: "Run " }), _jsx(Text, { color: "green", children: "skilluse login" }), _jsx(Text, { children: " to get started." })] })] }));
|
|
71
|
+
case "logged_in":
|
|
72
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "green", bold: true, children: "skilluse" }), _jsxs(Text, { dimColor: true, children: [" v", getCurrentVersion()] }), state.updateInfo?.hasUpdate && (_jsxs(Text, { color: "yellow", children: [" ", "(update available: v", state.updateInfo.latestVersion, " - run 'npm update -g skilluse')"] }))] }), _jsx(Box, { flexDirection: "column", marginBottom: 1, children: _jsxs(Box, { children: [_jsx(Text, { children: "Logged in as " }), _jsx(Text, { color: "green", bold: true, children: state.user.login }), state.user.name && _jsxs(Text, { dimColor: true, children: [" (", state.user.name, ")"] })] }) }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsx(Text, { children: "Default repo: " }), state.defaultRepo ? (_jsx(Text, { color: "cyan", children: state.defaultRepo })) : (_jsx(Text, { dimColor: true, children: "(not set)" }))] }), _jsxs(Box, { children: [_jsx(Text, { children: "Configured repos: " }), _jsx(Text, { children: state.repoCount })] }), _jsxs(Box, { children: [_jsx(Text, { children: "Installed skills: " }), _jsx(Text, { children: state.installedCount })] })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Quick Actions:" }), _jsx(Text, { dimColor: true, children: " skilluse repo add owner/repo Add a skill repository" }), _jsx(Text, { dimColor: true, children: " skilluse list Browse available skills" }), _jsx(Text, { dimColor: true, children: " skilluse install skill-name Install a skill" }), _jsx(Text, { dimColor: true, children: " skilluse --help Show all commands" })] })] }));
|
|
73
|
+
case "error":
|
|
74
|
+
return _jsx(StatusMessage, { type: "error", children: state.message });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const options: z.ZodObject<{
|
|
3
|
+
outdated: z.ZodDefault<z.ZodBoolean>;
|
|
4
|
+
}, "strip", z.ZodTypeAny, {
|
|
5
|
+
outdated: boolean;
|
|
6
|
+
}, {
|
|
7
|
+
outdated?: boolean | undefined;
|
|
8
|
+
}>;
|
|
9
|
+
interface Props {
|
|
10
|
+
options: z.infer<typeof options>;
|
|
11
|
+
}
|
|
12
|
+
export default function List({ options: opts }: Props): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { Box, Text, useApp } from "ink";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { Spinner, StatusMessage } from "../components/index.js";
|
|
6
|
+
import { getCredentials, getConfig, } from "../services/index.js";
|
|
7
|
+
export const options = z.object({
|
|
8
|
+
outdated: z
|
|
9
|
+
.boolean()
|
|
10
|
+
.default(false)
|
|
11
|
+
.describe("Show only outdated skills"),
|
|
12
|
+
});
|
|
13
|
+
export default function List({ options: opts }) {
|
|
14
|
+
const { exit } = useApp();
|
|
15
|
+
const [state, setState] = useState({ phase: "checking" });
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
async function loadSkills() {
|
|
18
|
+
// Check if logged in
|
|
19
|
+
const credentials = await getCredentials();
|
|
20
|
+
if (!credentials) {
|
|
21
|
+
setState({ phase: "not_logged_in" });
|
|
22
|
+
exit();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const config = getConfig();
|
|
26
|
+
let skills = config.installed;
|
|
27
|
+
// Filter for outdated if requested (placeholder - would need version checking)
|
|
28
|
+
if (opts.outdated) {
|
|
29
|
+
// TODO: Implement actual outdated check against remote versions
|
|
30
|
+
skills = [];
|
|
31
|
+
}
|
|
32
|
+
setState({ phase: "success", skills });
|
|
33
|
+
exit();
|
|
34
|
+
}
|
|
35
|
+
loadSkills();
|
|
36
|
+
}, [opts.outdated, exit]);
|
|
37
|
+
switch (state.phase) {
|
|
38
|
+
case "checking":
|
|
39
|
+
return _jsx(Spinner, { text: "Loading..." });
|
|
40
|
+
case "not_logged_in":
|
|
41
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StatusMessage, { type: "error", children: "Not authenticated" }), _jsx(Text, { dimColor: true, children: "Run 'skilluse login' to authenticate with GitHub" })] }));
|
|
42
|
+
case "success":
|
|
43
|
+
if (state.skills.length === 0) {
|
|
44
|
+
if (opts.outdated) {
|
|
45
|
+
return (_jsx(Box, { flexDirection: "column", children: _jsx(StatusMessage, { type: "success", children: "All skills are up to date" }) }));
|
|
46
|
+
}
|
|
47
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Installed Skills" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "(no skills installed)" }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Run 'skilluse install skill-name' to install one." }) })] }));
|
|
48
|
+
}
|
|
49
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Installed Skills" }), _jsx(Text, { children: " " }), state.skills.map((skill) => (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: "cyan", bold: true, children: skill.name }), _jsxs(Text, { dimColor: true, children: [" v", skill.version] }), _jsxs(Text, { dimColor: true, children: [" (", skill.scope, ")"] })] }), _jsx(Box, { marginLeft: 2, children: _jsxs(Text, { dimColor: true, children: ["From: ", skill.repo, " | Path: ", skill.installedPath] }) })] }, skill.name)))] }));
|
|
50
|
+
case "error":
|
|
51
|
+
return _jsx(StatusMessage, { type: "error", children: state.message });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const options: z.ZodObject<{
|
|
3
|
+
force: z.ZodDefault<z.ZodBoolean>;
|
|
4
|
+
}, "strip", z.ZodTypeAny, {
|
|
5
|
+
force: boolean;
|
|
6
|
+
}, {
|
|
7
|
+
force?: boolean | undefined;
|
|
8
|
+
}>;
|
|
9
|
+
interface Props {
|
|
10
|
+
options: z.infer<typeof options>;
|
|
11
|
+
}
|
|
12
|
+
export default function Login({ options: opts }: Props): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=login.d.ts.map
|