recur-skills 0.0.1
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/.claude-plugin/plugin.json +25 -0
- package/README.md +133 -0
- package/dist/cli.js +163 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +72 -0
- package/package.json +64 -0
- package/skills/recur-checkout/SKILL.md +248 -0
- package/skills/recur-entitlements/SKILL.md +389 -0
- package/skills/recur-quickstart/SKILL.md +114 -0
- package/skills/recur-quickstart/scripts/check-env.sh +57 -0
- package/skills/recur-webhooks/SKILL.md +349 -0
- package/skills/recur-webhooks/scripts/test-webhook.sh +111 -0
- package/skills/recur-webhooks/scripts/verify-signature.ts +59 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "recur-skills",
|
|
3
|
+
"description": "Claude Code skills for integrating Recur - Taiwan's subscription payment platform. Includes checkout, webhooks, and entitlements.",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Recur",
|
|
7
|
+
"email": "hi@recur.tw",
|
|
8
|
+
"url": "https://recur.tw"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/recur-tw/skills"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://recur.tw/skills",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"recur",
|
|
18
|
+
"payments",
|
|
19
|
+
"subscription",
|
|
20
|
+
"taiwan",
|
|
21
|
+
"checkout",
|
|
22
|
+
"webhooks",
|
|
23
|
+
"entitlements"
|
|
24
|
+
]
|
|
25
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Recur Skills for Claude Code
|
|
2
|
+
|
|
3
|
+
Claude Code skills to help developers integrate [Recur](https://recur.tw) - Taiwan's subscription payment platform.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Claude Code Plugin (Recommended)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
/plugin add recur-tw/skills
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### npm CLI
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Install all skills globally
|
|
17
|
+
npx recur-skills install --all --global
|
|
18
|
+
|
|
19
|
+
# Install specific skills
|
|
20
|
+
npx recur-skills install recur-quickstart recur-webhooks
|
|
21
|
+
|
|
22
|
+
# Install to current project
|
|
23
|
+
npx recur-skills install --all --project
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Manual Installation
|
|
27
|
+
|
|
28
|
+
Copy skills to your Claude Code skills directory:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Global (all projects)
|
|
32
|
+
cp -r skills/* ~/.claude/skills/
|
|
33
|
+
|
|
34
|
+
# Project-specific
|
|
35
|
+
cp -r skills/* .claude/skills/
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Available Skills
|
|
39
|
+
|
|
40
|
+
### recur-quickstart
|
|
41
|
+
|
|
42
|
+
Quick setup guide for Recur payment integration.
|
|
43
|
+
|
|
44
|
+
**Triggers:** "integrate Recur", "setup Recur", "Recur 串接", "金流設定"
|
|
45
|
+
|
|
46
|
+
- SDK installation
|
|
47
|
+
- API key configuration
|
|
48
|
+
- Basic provider setup
|
|
49
|
+
- First checkout implementation
|
|
50
|
+
|
|
51
|
+
### recur-checkout
|
|
52
|
+
|
|
53
|
+
Implement Recur checkout flows.
|
|
54
|
+
|
|
55
|
+
**Triggers:** "checkout", "結帳", "付款按鈕", "embedded checkout"
|
|
56
|
+
|
|
57
|
+
- Embedded, modal, and redirect modes
|
|
58
|
+
- useRecur and useSubscribe hooks
|
|
59
|
+
- Product types (subscription, one-time, credits, donation)
|
|
60
|
+
- Payment error handling
|
|
61
|
+
- 3D verification
|
|
62
|
+
|
|
63
|
+
### recur-webhooks
|
|
64
|
+
|
|
65
|
+
Set up and handle Recur webhook events.
|
|
66
|
+
|
|
67
|
+
**Triggers:** "webhook", "付款通知", "訂閱事件", "payment notification"
|
|
68
|
+
|
|
69
|
+
- All webhook event types
|
|
70
|
+
- Signature verification
|
|
71
|
+
- Next.js and Express handlers
|
|
72
|
+
- Testing webhooks locally
|
|
73
|
+
- Idempotency handling
|
|
74
|
+
|
|
75
|
+
### recur-entitlements
|
|
76
|
+
|
|
77
|
+
Implement access control and permission checking.
|
|
78
|
+
|
|
79
|
+
**Triggers:** "paywall", "權限檢查", "entitlements", "access control"
|
|
80
|
+
|
|
81
|
+
- useCustomer hook
|
|
82
|
+
- Cached vs live checks
|
|
83
|
+
- Paywall components
|
|
84
|
+
- Server-side verification
|
|
85
|
+
- Handling subscription statuses
|
|
86
|
+
|
|
87
|
+
## Usage
|
|
88
|
+
|
|
89
|
+
Once installed, Claude will automatically use these skills when you're working on Recur integration tasks.
|
|
90
|
+
|
|
91
|
+
You can also invoke them directly:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
/recur-quickstart
|
|
95
|
+
/recur-checkout
|
|
96
|
+
/recur-webhooks
|
|
97
|
+
/recur-entitlements
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Utility Scripts
|
|
101
|
+
|
|
102
|
+
### Check Environment
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
./skills/recur-quickstart/scripts/check-env.sh
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Test Webhook Locally
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
./skills/recur-webhooks/scripts/test-webhook.sh http://localhost:3000/api/webhooks/recur checkout.completed
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Verify Webhook Signature
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx tsx ./skills/recur-webhooks/scripts/verify-signature.ts '<payload>' '<signature>' '<secret>'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Links
|
|
121
|
+
|
|
122
|
+
- [Recur Website](https://recur.tw)
|
|
123
|
+
- [Documentation](https://recur.tw/docs)
|
|
124
|
+
- [SDK on npm](https://www.npmjs.com/package/recur-tw)
|
|
125
|
+
- [API Reference](https://recur.tw/docs/api)
|
|
126
|
+
|
|
127
|
+
## Contributing
|
|
128
|
+
|
|
129
|
+
Found an issue or want to improve a skill? Please open an issue or PR at [github.com/recur-tw/skills](https://github.com/recur-tw/skills).
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import { program } from "commander";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import { existsSync as existsSync2, mkdirSync, cpSync, readdirSync as readdirSync2 } from "fs";
|
|
7
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
8
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9
|
+
|
|
10
|
+
// src/index.ts
|
|
11
|
+
import { readFileSync, readdirSync, existsSync } from "fs";
|
|
12
|
+
import { join, dirname } from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
var SKILLS_DIR = join(__dirname, "..", "skills");
|
|
16
|
+
function parseFrontmatter(content) {
|
|
17
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
18
|
+
if (!match) {
|
|
19
|
+
return { data: {}, content };
|
|
20
|
+
}
|
|
21
|
+
const data = {};
|
|
22
|
+
const lines = match[1].split("\n");
|
|
23
|
+
for (const line of lines) {
|
|
24
|
+
const colonIndex = line.indexOf(":");
|
|
25
|
+
if (colonIndex > 0) {
|
|
26
|
+
const key = line.slice(0, colonIndex).trim();
|
|
27
|
+
const value = line.slice(colonIndex + 1).trim();
|
|
28
|
+
data[key] = value;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { data, content: match[2] };
|
|
32
|
+
}
|
|
33
|
+
function getAllSkills() {
|
|
34
|
+
if (!existsSync(SKILLS_DIR)) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const skillDirs = readdirSync(SKILLS_DIR, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
38
|
+
const skills = [];
|
|
39
|
+
for (const dir of skillDirs) {
|
|
40
|
+
const skillPath = join(SKILLS_DIR, dir, "SKILL.md");
|
|
41
|
+
if (!existsSync(skillPath)) continue;
|
|
42
|
+
const rawContent = readFileSync(skillPath, "utf-8");
|
|
43
|
+
const { data, content } = parseFrontmatter(rawContent);
|
|
44
|
+
skills.push({
|
|
45
|
+
slug: dir,
|
|
46
|
+
name: data.name || dir,
|
|
47
|
+
description: data.description || "",
|
|
48
|
+
content,
|
|
49
|
+
path: skillPath
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return skills;
|
|
53
|
+
}
|
|
54
|
+
function getSkill(slug) {
|
|
55
|
+
const skillPath = join(SKILLS_DIR, slug, "SKILL.md");
|
|
56
|
+
if (!existsSync(skillPath)) return null;
|
|
57
|
+
const rawContent = readFileSync(skillPath, "utf-8");
|
|
58
|
+
const { data, content } = parseFrontmatter(rawContent);
|
|
59
|
+
return {
|
|
60
|
+
slug,
|
|
61
|
+
name: data.name || slug,
|
|
62
|
+
description: data.description || "",
|
|
63
|
+
content,
|
|
64
|
+
path: skillPath
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function getSkillsDir() {
|
|
68
|
+
return SKILLS_DIR;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/cli.ts
|
|
72
|
+
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
73
|
+
var SKILLS_SOURCE = join2(__dirname2, "..", "skills");
|
|
74
|
+
program.name("recur-skills").description("Claude Code skills for Recur payment integration").version("0.0.1");
|
|
75
|
+
program.command("list").description("List all available skills").action(() => {
|
|
76
|
+
const skills = getAllSkills();
|
|
77
|
+
if (skills.length === 0) {
|
|
78
|
+
console.log(pc.yellow("No skills found."));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
console.log(pc.bold("\n\u{1F4E6} Available Recur Skills\n"));
|
|
82
|
+
for (const skill of skills) {
|
|
83
|
+
console.log(pc.cyan(` ${skill.name}`));
|
|
84
|
+
console.log(pc.dim(` ${skill.description}
|
|
85
|
+
`));
|
|
86
|
+
}
|
|
87
|
+
console.log(pc.dim(`Total: ${skills.length} skills
|
|
88
|
+
`));
|
|
89
|
+
});
|
|
90
|
+
program.command("info <skill>").description("Show detailed information about a skill").action((skillName) => {
|
|
91
|
+
const skill = getSkill(skillName);
|
|
92
|
+
if (!skill) {
|
|
93
|
+
console.log(pc.red(`Skill "${skillName}" not found.`));
|
|
94
|
+
console.log(pc.dim("\nRun `recur-skills list` to see available skills."));
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
console.log(pc.bold(`
|
|
98
|
+
\u{1F4E6} ${skill.name}
|
|
99
|
+
`));
|
|
100
|
+
console.log(pc.dim("Description:"));
|
|
101
|
+
console.log(` ${skill.description}
|
|
102
|
+
`);
|
|
103
|
+
console.log(pc.dim("Path:"));
|
|
104
|
+
console.log(` ${skill.path}
|
|
105
|
+
`);
|
|
106
|
+
});
|
|
107
|
+
program.command("install [skills...]").description("Install skills to your Claude Code skills directory").option("-g, --global", "Install to global ~/.claude/skills/", false).option("-p, --project", "Install to project .claude/skills/", false).option("-a, --all", "Install all skills", false).action((skillNames, options) => {
|
|
108
|
+
let targetDir;
|
|
109
|
+
if (options.global) {
|
|
110
|
+
targetDir = join2(process.env.HOME || "~", ".claude", "skills");
|
|
111
|
+
} else if (options.project) {
|
|
112
|
+
targetDir = join2(process.cwd(), ".claude", "skills");
|
|
113
|
+
} else {
|
|
114
|
+
targetDir = join2(process.env.HOME || "~", ".claude", "skills");
|
|
115
|
+
}
|
|
116
|
+
let toInstall;
|
|
117
|
+
if (options.all) {
|
|
118
|
+
toInstall = readdirSync2(SKILLS_SOURCE, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
119
|
+
} else if (skillNames.length === 0) {
|
|
120
|
+
console.log(pc.yellow("Please specify skills to install or use --all"));
|
|
121
|
+
console.log(pc.dim("\nExamples:"));
|
|
122
|
+
console.log(pc.dim(" recur-skills install recur-quickstart"));
|
|
123
|
+
console.log(pc.dim(" recur-skills install recur-checkout recur-webhooks"));
|
|
124
|
+
console.log(pc.dim(" recur-skills install --all"));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
} else {
|
|
127
|
+
toInstall = skillNames;
|
|
128
|
+
}
|
|
129
|
+
if (!existsSync2(targetDir)) {
|
|
130
|
+
mkdirSync(targetDir, { recursive: true });
|
|
131
|
+
}
|
|
132
|
+
console.log(pc.bold(`
|
|
133
|
+
\u{1F4E6} Installing skills to ${targetDir}
|
|
134
|
+
`));
|
|
135
|
+
let installed = 0;
|
|
136
|
+
for (const skillName of toInstall) {
|
|
137
|
+
const sourcePath = join2(SKILLS_SOURCE, skillName);
|
|
138
|
+
const destPath = join2(targetDir, skillName);
|
|
139
|
+
if (!existsSync2(sourcePath)) {
|
|
140
|
+
console.log(pc.red(` \u2717 ${skillName} - not found`));
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
cpSync(sourcePath, destPath, { recursive: true });
|
|
145
|
+
console.log(pc.green(` \u2713 ${skillName}`));
|
|
146
|
+
installed++;
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.log(pc.red(` \u2717 ${skillName} - ${error}`));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
console.log(pc.dim(`
|
|
152
|
+
Installed ${installed}/${toInstall.length} skills
|
|
153
|
+
`));
|
|
154
|
+
if (installed > 0) {
|
|
155
|
+
console.log(pc.cyan("Skills are now available in Claude Code!"));
|
|
156
|
+
console.log(pc.dim("Claude will automatically use them when relevant,"));
|
|
157
|
+
console.log(pc.dim("or you can invoke them directly with /skill-name\n"));
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
program.command("path").description("Show the path to the skills directory").action(() => {
|
|
161
|
+
console.log(getSkillsDir());
|
|
162
|
+
});
|
|
163
|
+
program.parse();
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
interface SkillMetadata {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
}
|
|
5
|
+
interface Skill extends SkillMetadata {
|
|
6
|
+
slug: string;
|
|
7
|
+
content: string;
|
|
8
|
+
path: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get all available skills
|
|
12
|
+
*/
|
|
13
|
+
declare function getAllSkills(): Skill[];
|
|
14
|
+
/**
|
|
15
|
+
* Get a single skill by slug
|
|
16
|
+
*/
|
|
17
|
+
declare function getSkill(slug: string): Skill | null;
|
|
18
|
+
/**
|
|
19
|
+
* Get skill names only (for listing)
|
|
20
|
+
*/
|
|
21
|
+
declare function getSkillNames(): string[];
|
|
22
|
+
/**
|
|
23
|
+
* Get the path to skills directory
|
|
24
|
+
*/
|
|
25
|
+
declare function getSkillsDir(): string;
|
|
26
|
+
|
|
27
|
+
export { type Skill, type SkillMetadata, getAllSkills, getSkill, getSkillNames, getSkillsDir };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { readFileSync, readdirSync, existsSync } from "fs";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
var SKILLS_DIR = join(__dirname, "..", "skills");
|
|
7
|
+
function parseFrontmatter(content) {
|
|
8
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
9
|
+
if (!match) {
|
|
10
|
+
return { data: {}, content };
|
|
11
|
+
}
|
|
12
|
+
const data = {};
|
|
13
|
+
const lines = match[1].split("\n");
|
|
14
|
+
for (const line of lines) {
|
|
15
|
+
const colonIndex = line.indexOf(":");
|
|
16
|
+
if (colonIndex > 0) {
|
|
17
|
+
const key = line.slice(0, colonIndex).trim();
|
|
18
|
+
const value = line.slice(colonIndex + 1).trim();
|
|
19
|
+
data[key] = value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return { data, content: match[2] };
|
|
23
|
+
}
|
|
24
|
+
function getAllSkills() {
|
|
25
|
+
if (!existsSync(SKILLS_DIR)) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
const skillDirs = readdirSync(SKILLS_DIR, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
29
|
+
const skills = [];
|
|
30
|
+
for (const dir of skillDirs) {
|
|
31
|
+
const skillPath = join(SKILLS_DIR, dir, "SKILL.md");
|
|
32
|
+
if (!existsSync(skillPath)) continue;
|
|
33
|
+
const rawContent = readFileSync(skillPath, "utf-8");
|
|
34
|
+
const { data, content } = parseFrontmatter(rawContent);
|
|
35
|
+
skills.push({
|
|
36
|
+
slug: dir,
|
|
37
|
+
name: data.name || dir,
|
|
38
|
+
description: data.description || "",
|
|
39
|
+
content,
|
|
40
|
+
path: skillPath
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return skills;
|
|
44
|
+
}
|
|
45
|
+
function getSkill(slug) {
|
|
46
|
+
const skillPath = join(SKILLS_DIR, slug, "SKILL.md");
|
|
47
|
+
if (!existsSync(skillPath)) return null;
|
|
48
|
+
const rawContent = readFileSync(skillPath, "utf-8");
|
|
49
|
+
const { data, content } = parseFrontmatter(rawContent);
|
|
50
|
+
return {
|
|
51
|
+
slug,
|
|
52
|
+
name: data.name || slug,
|
|
53
|
+
description: data.description || "",
|
|
54
|
+
content,
|
|
55
|
+
path: skillPath
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function getSkillNames() {
|
|
59
|
+
if (!existsSync(SKILLS_DIR)) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
return readdirSync(SKILLS_DIR, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).filter((dirent) => existsSync(join(SKILLS_DIR, dirent.name, "SKILL.md"))).map((dirent) => dirent.name);
|
|
63
|
+
}
|
|
64
|
+
function getSkillsDir() {
|
|
65
|
+
return SKILLS_DIR;
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
getAllSkills,
|
|
69
|
+
getSkill,
|
|
70
|
+
getSkillNames,
|
|
71
|
+
getSkillsDir
|
|
72
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "recur-skills",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Claude Code skills for Recur - Taiwan's subscription payment platform",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"recur",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"skills",
|
|
9
|
+
"subscription",
|
|
10
|
+
"payments",
|
|
11
|
+
"taiwan",
|
|
12
|
+
"agent-skills"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://recur.tw/skills",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/recur-tw/skills"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"author": {
|
|
21
|
+
"name": "Recur",
|
|
22
|
+
"email": "hi@recur.tw",
|
|
23
|
+
"url": "https://recur.tw"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"import": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts"
|
|
30
|
+
},
|
|
31
|
+
"./skills/*": "./skills/*"
|
|
32
|
+
},
|
|
33
|
+
"main": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"bin": {
|
|
36
|
+
"recur-skills": "./dist/cli.js"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"skills",
|
|
41
|
+
".claude-plugin"
|
|
42
|
+
],
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"commander": "^12.1.0",
|
|
45
|
+
"picocolors": "^1.1.1"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^22.0.0",
|
|
49
|
+
"tsup": "^8.3.5",
|
|
50
|
+
"typescript": "^5.7.3"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=18"
|
|
54
|
+
},
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsup",
|
|
60
|
+
"dev": "tsup --watch",
|
|
61
|
+
"lint": "eslint src/",
|
|
62
|
+
"typecheck": "tsc --noEmit"
|
|
63
|
+
}
|
|
64
|
+
}
|