@clix-so/clix-agent-skills 0.2.3 → 0.2.5
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 +7 -4
- package/dist/bin/commands/install.js +8 -2
- package/llms.txt +26 -15
- package/package.json +1 -1
- package/skills/api-triggered-campaigns/SKILL.md +1 -2
- package/skills/event-tracking/SKILL.md +3 -3
- package/skills/integration/SKILL.md +1 -2
- package/skills/integration/references/error-handling.md +1 -2
- package/skills/personalization/SKILL.md +1 -2
- package/skills/skill-creator/LICENSE.txt +204 -0
- package/skills/skill-creator/SKILL.md +195 -0
- package/skills/skill-creator/examples/skill-brief-example.yaml +41 -0
- package/skills/skill-creator/references/mcp-research-playbook.md +75 -0
- package/skills/skill-creator/references/skill-template.md +74 -0
- package/skills/skill-creator/scripts/validate-same-scope.sh +61 -0
- package/skills/skill-creator/scripts/validate-skill-location.sh +204 -0
- package/skills/skill-creator/scripts/validate-skill-scaffold.sh +207 -0
- package/skills/user-management/SKILL.md +1 -2
package/README.md
CHANGED
|
@@ -21,6 +21,9 @@ by AI clients.
|
|
|
21
21
|
- **clix-api-triggered-campaigns**: Configure API-triggered campaigns in the
|
|
22
22
|
console and trigger them from your backend with safe auth, dynamic filters
|
|
23
23
|
(`trigger.*`), and personalization patterns
|
|
24
|
+
- **clix-skill-creator**: Create new Clix agent skills by researching Clix SDK +
|
|
25
|
+
docs via Clix MCP Server, then generating a complete skill folder (SKILL.md,
|
|
26
|
+
references, scripts, examples) aligned with this repo’s conventions
|
|
24
27
|
|
|
25
28
|
## Installing Skills
|
|
26
29
|
|
|
@@ -68,7 +71,7 @@ npx @clix-so/clix-agent-skills@latest install integration --client cursor --glob
|
|
|
68
71
|
|
|
69
72
|
# Install all available skills at once (repo root)
|
|
70
73
|
npx @clix-so/clix-agent-skills@latest install --all --client cursor
|
|
71
|
-
# This will install: integration, event-tracking, user-management, personalization, api-triggered-campaigns
|
|
74
|
+
# This will install: integration, event-tracking, user-management, personalization, api-triggered-campaigns, skill-creator
|
|
72
75
|
|
|
73
76
|
# Install all available skills globally (system root)
|
|
74
77
|
npx @clix-so/clix-agent-skills@latest install --all --client cursor --global
|
|
@@ -78,13 +81,13 @@ npx @clix-so/clix-agent-skills@latest install --all --client cursor --global
|
|
|
78
81
|
|
|
79
82
|
| Client | Flag | Default Path |
|
|
80
83
|
| -------------- | ------------------------------------ | ------------------ |
|
|
81
|
-
| Amp | `--client amp` | `.
|
|
84
|
+
| Amp | `--client amp` | `.agents/skills/` |
|
|
82
85
|
| Claude Code | `--client claude` (or `claude-code`) | `.claude/skills/` |
|
|
83
86
|
| Codex | `--client codex` | `.codex/skills/` |
|
|
84
87
|
| Cursor | `--client cursor` | `.cursor/skills/` |
|
|
85
88
|
| Gemini CLI | `--client gemini` | `.gemini/skills/` |
|
|
86
89
|
| GitHub Copilot | `--client github` | `.github/skills/` |
|
|
87
|
-
| Goose | `--client goose` | `.
|
|
90
|
+
| Goose | `--client goose` | `.agents/skills/` |
|
|
88
91
|
| Letta | `--client letta` | `.skills/` |
|
|
89
92
|
| OpenCode | `--client opencode` | `.opencode/skill/` |
|
|
90
93
|
| VS Code | `--client vscode` | `.vscode/skills/` |
|
|
@@ -103,7 +106,7 @@ To install specific skills:
|
|
|
103
106
|
1. Visit the Marketplace section in `/plugin`
|
|
104
107
|
2. Select `Browse plugins`
|
|
105
108
|
3. Choose the skills you wish to install
|
|
106
|
-
4. Install skill
|
|
109
|
+
4. Install your preferred skill
|
|
107
110
|
|
|
108
111
|
Alternatively, you can install a single skill directly by running:
|
|
109
112
|
|
|
@@ -67,7 +67,9 @@ async function installSkill(skillName, options) {
|
|
|
67
67
|
relativeDest = ".amazonq/skills";
|
|
68
68
|
break;
|
|
69
69
|
case "amp":
|
|
70
|
-
|
|
70
|
+
// Amp looks for workspace skills in `.agents/skills/` and user skills in `~/.config/agents/skills/`.
|
|
71
|
+
// We map `--global` to the user-level location.
|
|
72
|
+
relativeDest = options.global ? ".config/agents/skills" : ".agents/skills";
|
|
71
73
|
break;
|
|
72
74
|
case "claude":
|
|
73
75
|
case "claude-code":
|
|
@@ -92,7 +94,11 @@ async function installSkill(skillName, options) {
|
|
|
92
94
|
relativeDest = ".skills";
|
|
93
95
|
break;
|
|
94
96
|
case "goose":
|
|
95
|
-
|
|
97
|
+
// Goose supports portable skill locations too:
|
|
98
|
+
// - project: `./.agents/skills/`
|
|
99
|
+
// - global : `~/.config/agents/skills/`
|
|
100
|
+
// We default to the portable locations, but users can still override via --path.
|
|
101
|
+
relativeDest = options.global ? ".config/agents/skills" : ".agents/skills";
|
|
96
102
|
break;
|
|
97
103
|
case "kiro":
|
|
98
104
|
relativeDest = ".kiro/skills";
|
package/llms.txt
CHANGED
|
@@ -9,9 +9,7 @@ Each entry includes the file path, type, and description for semantic search.
|
|
|
9
9
|
|
|
10
10
|
## clix-api-triggered-campaigns
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- [clix-api-triggered-campaigns](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/api-triggered-campaigns/SKILL.md): Helps developers configure API-triggered campaigns in the Clix console and trigger them from backend services with safe auth, payload schemas, dynamic audience filters (trigger.*), and personalization best practices. Use when the user mentions transactional notifications, backend-triggered sends, campaign_id trigger APIs, or "API-triggered campaigns".
|
|
12
|
+
- [clix-api-triggered-campaigns](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/api-triggered-campaigns/SKILL.md): Main skill documentation
|
|
15
13
|
|
|
16
14
|
### References
|
|
17
15
|
|
|
@@ -35,9 +33,7 @@ Helps developers configure API-triggered campaigns in the Clix console and trigg
|
|
|
35
33
|
|
|
36
34
|
## clix-event-tracking
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- [clix-event-tracking](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/event-tracking/SKILL.md): Implements Clix event tracking (Clix.trackEvent) with consistent naming, safe property schemas, and campaign-ready validation. Use when adding, reviewing, or debugging event tracking; when configuring event-triggered campaigns; or when the user mentions events, tracking, funnels, or properties — or when the user types `clix-event-tracking`.
|
|
36
|
+
- [clix-event-tracking](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/event-tracking/SKILL.md): Main skill documentation
|
|
41
37
|
|
|
42
38
|
### References
|
|
43
39
|
|
|
@@ -55,9 +51,7 @@ Implements Clix event tracking (Clix.trackEvent) with consistent naming, safe pr
|
|
|
55
51
|
|
|
56
52
|
## clix-integration
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- [clix-integration](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/integration/SKILL.md): Integrates Clix Mobile SDK into iOS, Android, Flutter, and React Native projects. Provides step-by-step guidance for installation, initialization, and verification. Use when the user asks to install, setup, integrate Clix or when the user types `clix-integration` / "clix integration".
|
|
54
|
+
- [clix-integration](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/integration/SKILL.md): Main skill documentation
|
|
61
55
|
|
|
62
56
|
### References
|
|
63
57
|
|
|
@@ -82,9 +76,7 @@ Integrates Clix Mobile SDK into iOS, Android, Flutter, and React Native projects
|
|
|
82
76
|
|
|
83
77
|
## clix-personalization
|
|
84
78
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
- [clix-personalization](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/personalization/SKILL.md): Helps developers author and debug Clix personalization templates (Liquid-style) for message content, deep links/URLs, and audience targeting. Use when the user mentions personalization variables, Liquid, templates, conditional logic, loops, filters, deep links, message logs, or when the user types `clix-personalization`.
|
|
79
|
+
- [clix-personalization](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/personalization/SKILL.md): Main skill documentation
|
|
88
80
|
|
|
89
81
|
### References
|
|
90
82
|
|
|
@@ -98,11 +90,30 @@ Helps developers author and debug Clix personalization templates (Liquid-style)
|
|
|
98
90
|
|
|
99
91
|
---
|
|
100
92
|
|
|
101
|
-
## clix-
|
|
93
|
+
## clix-skill-creator
|
|
94
|
+
|
|
95
|
+
- [clix-skill-creator](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/skill-creator/SKILL.md): Main skill documentation
|
|
96
|
+
|
|
97
|
+
### References
|
|
98
|
+
|
|
99
|
+
- [Mcp Research Playbook (Reference)](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/skill-creator/references/mcp-research-playbook.md): Reference documentation for skill-creator skill
|
|
100
|
+
- [Skill Template (Reference)](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/skill-creator/references/skill-template.md): Reference documentation for skill-creator skill
|
|
102
101
|
|
|
103
|
-
|
|
102
|
+
### Examples
|
|
103
|
+
|
|
104
|
+
- [Skill Brief Example (Example)](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/skill-creator/examples/skill-brief-example.yaml): Code example for skill-creator skill
|
|
105
|
+
|
|
106
|
+
### Scripts
|
|
107
|
+
|
|
108
|
+
- [Validate Same Scope (Script)](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/skill-creator/scripts/validate-same-scope.sh): Utility script for skill-creator skill
|
|
109
|
+
- [Validate Skill Location (Script)](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/skill-creator/scripts/validate-skill-location.sh): Utility script for skill-creator skill
|
|
110
|
+
- [Validate Skill Scaffold (Script)](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/skill-creator/scripts/validate-skill-scaffold.sh): Utility script for skill-creator skill
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## clix-user-management
|
|
104
115
|
|
|
105
|
-
- [clix-user-management](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/user-management/SKILL.md):
|
|
116
|
+
- [clix-user-management](https://raw.githubusercontent.com/clix-so/skills/refs/heads/main/skills/user-management/SKILL.md): Main skill documentation
|
|
106
117
|
|
|
107
118
|
### References
|
|
108
119
|
|
package/package.json
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
name: clix-api-triggered-campaigns
|
|
3
3
|
display-name: API-Triggered Campaigns
|
|
4
4
|
short-description: API-triggered campaign setup
|
|
5
|
-
description:
|
|
6
|
-
Helps developers configure API-triggered campaigns in the Clix console and
|
|
5
|
+
description: Helps developers configure API-triggered campaigns in the Clix console and
|
|
7
6
|
trigger them from backend services with safe auth, payload schemas, dynamic
|
|
8
7
|
audience filters (trigger.*), and personalization best practices. Use when the
|
|
9
8
|
user mentions transactional notifications, backend-triggered sends,
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
name: clix-event-tracking
|
|
3
3
|
display-name: Event Tracking
|
|
4
4
|
short-description: Event tracking setup
|
|
5
|
-
description:
|
|
6
|
-
Implements Clix event tracking (Clix.trackEvent) with consistent naming, safe
|
|
5
|
+
description: Implements Clix event tracking (Clix.trackEvent) with consistent naming, safe
|
|
7
6
|
property schemas, and campaign-ready validation. Use when adding, reviewing,
|
|
8
7
|
or debugging event tracking; when configuring event-triggered campaigns; or
|
|
9
8
|
when the user mentions events, tracking, funnels, or properties — or when the
|
|
@@ -101,7 +100,8 @@ The skill directory is typically:
|
|
|
101
100
|
|
|
102
101
|
- `.cursor/skills/event-tracking/` (Cursor)
|
|
103
102
|
- `.claude/skills/event-tracking/` (Claude Code)
|
|
104
|
-
- `.vscode/skills/event-tracking/` (VS Code
|
|
103
|
+
- `.vscode/skills/event-tracking/` (VS Code)
|
|
104
|
+
- `.agents/skills/event-tracking/` (Amp)
|
|
105
105
|
- Or check where this skill was installed
|
|
106
106
|
|
|
107
107
|
If validation fails: fix the plan first, then implement.
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
name: clix-integration
|
|
3
3
|
display-name: SDK Integration
|
|
4
4
|
short-description: SDK integration guide
|
|
5
|
-
description:
|
|
6
|
-
Integrates Clix Mobile SDK into iOS, Android, Flutter, and React Native
|
|
5
|
+
description: Integrates Clix Mobile SDK into iOS, Android, Flutter, and React Native
|
|
7
6
|
projects. Provides step-by-step guidance for installation, initialization, and
|
|
8
7
|
verification. Use when the user asks to install, setup, integrate Clix or when
|
|
9
8
|
the user types `clix-integration` / "clix integration".
|
|
@@ -241,8 +241,7 @@ try {
|
|
|
241
241
|
### Provide Fallbacks
|
|
242
242
|
|
|
243
243
|
```typescript
|
|
244
|
-
const projectId =
|
|
245
|
-
process.env.CLIX_PROJECT_ID || process.env.REACT_APP_CLIX_PROJECT_ID || "";
|
|
244
|
+
const projectId = process.env.CLIX_PROJECT_ID || process.env.REACT_APP_CLIX_PROJECT_ID || "";
|
|
246
245
|
|
|
247
246
|
if (!projectId) {
|
|
248
247
|
console.warn("Clix: No project ID found, analytics disabled");
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
name: clix-personalization
|
|
3
3
|
display-name: Personalization
|
|
4
4
|
short-description: Personalization templates
|
|
5
|
-
description:
|
|
6
|
-
Helps developers author and debug Clix personalization templates
|
|
5
|
+
description: Helps developers author and debug Clix personalization templates
|
|
7
6
|
(Liquid-style) for message content, deep links/URLs, and audience targeting.
|
|
8
7
|
Use when the user mentions personalization variables, Liquid, templates,
|
|
9
8
|
conditional logic, loops, filters, deep links, message logs, or when the user
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
Copyright (c) 2026 Clix (https://clix.so/)
|
|
2
|
+
|
|
3
|
+
Apache License
|
|
4
|
+
Version 2.0, January 2004
|
|
5
|
+
http://www.apache.org/licenses/
|
|
6
|
+
|
|
7
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
8
|
+
|
|
9
|
+
1. Definitions.
|
|
10
|
+
|
|
11
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
12
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
13
|
+
|
|
14
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
15
|
+
the copyright owner that is granting the License.
|
|
16
|
+
|
|
17
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
18
|
+
other entities that control, are controlled by, or are under common
|
|
19
|
+
control with that entity. For the purposes of this definition,
|
|
20
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
21
|
+
direction or management of such entity, whether by contract or
|
|
22
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
23
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
24
|
+
|
|
25
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
26
|
+
exercising permissions granted by this License.
|
|
27
|
+
|
|
28
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
29
|
+
including but not limited to software source code, documentation
|
|
30
|
+
source, and configuration files.
|
|
31
|
+
|
|
32
|
+
"Object" form shall mean any form resulting from mechanical
|
|
33
|
+
transformation or translation of a Source form, including but
|
|
34
|
+
not limited to compiled object code, generated documentation,
|
|
35
|
+
and conversions to other media types.
|
|
36
|
+
|
|
37
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
38
|
+
Object form, made available under the License, as indicated by a
|
|
39
|
+
copyright notice that is included in or attached to the work
|
|
40
|
+
(an example is provided in the Appendix below).
|
|
41
|
+
|
|
42
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
43
|
+
form, that is based on (or derived from) the Work and for which the
|
|
44
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
45
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
46
|
+
of this License, Derivative Works shall not include works that remain
|
|
47
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
48
|
+
the Work and Derivative Works thereof.
|
|
49
|
+
|
|
50
|
+
"Contribution" shall mean any work of authorship, including
|
|
51
|
+
the original version of the Work and any modifications or additions
|
|
52
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
53
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
54
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
55
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
56
|
+
means any form of electronic, verbal, or written communication sent
|
|
57
|
+
to the Licensor or its representatives, including but not limited to
|
|
58
|
+
communication on electronic mailing lists, source code control systems,
|
|
59
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
60
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
61
|
+
excluding communication that is conspicuously marked or otherwise
|
|
62
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
63
|
+
|
|
64
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
65
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
66
|
+
subsequently incorporated within the Work.
|
|
67
|
+
|
|
68
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
69
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
70
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
71
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
72
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
73
|
+
Work and such Derivative Works in Source or Object form.
|
|
74
|
+
|
|
75
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
76
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
77
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
78
|
+
(except as stated in this section) patent license to make, have made,
|
|
79
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
80
|
+
where such license applies only to those patent claims licensable
|
|
81
|
+
by such Contributor that are necessarily infringed by their
|
|
82
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
83
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
84
|
+
institute patent litigation against any entity (including a
|
|
85
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
86
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
87
|
+
or contributory patent infringement, then any patent licenses
|
|
88
|
+
granted to You under this License for that Work shall terminate
|
|
89
|
+
as of the date such litigation is filed.
|
|
90
|
+
|
|
91
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
92
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
93
|
+
modifications, and in Source or Object form, provided that You
|
|
94
|
+
meet the following conditions:
|
|
95
|
+
|
|
96
|
+
(a) You must give any other recipients of the Work or
|
|
97
|
+
Derivative Works a copy of this License; and
|
|
98
|
+
|
|
99
|
+
(b) You must cause any modified files to carry prominent notices
|
|
100
|
+
stating that You changed the files; and
|
|
101
|
+
|
|
102
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
103
|
+
that You distribute, all copyright, patent, trademark, and
|
|
104
|
+
attribution notices from the Source form of the Work,
|
|
105
|
+
excluding those notices that do not pertain to any part of
|
|
106
|
+
the Derivative Works; and
|
|
107
|
+
|
|
108
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
109
|
+
distribution, then any Derivative Works that You distribute must
|
|
110
|
+
include a readable copy of the attribution notices contained
|
|
111
|
+
within such NOTICE file, excluding those notices that do not
|
|
112
|
+
pertain to any part of the Derivative Works, in at least one
|
|
113
|
+
of the following places: within a NOTICE text file distributed
|
|
114
|
+
as part of the Derivative Works; within the Source form or
|
|
115
|
+
documentation, if provided along with the Derivative Works; or,
|
|
116
|
+
within a display generated by the Derivative Works, if and
|
|
117
|
+
wherever such third-party notices normally appear. The contents
|
|
118
|
+
of the NOTICE file are for informational purposes only and
|
|
119
|
+
do not modify the License. You may add Your own attribution
|
|
120
|
+
notices within Derivative Works that You distribute, alongside
|
|
121
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
122
|
+
that such additional attribution notices cannot be construed
|
|
123
|
+
as modifying the License.
|
|
124
|
+
|
|
125
|
+
You may add Your own copyright statement to Your modifications and
|
|
126
|
+
may provide additional or different license terms and conditions
|
|
127
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
128
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
129
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
130
|
+
the conditions stated in this License.
|
|
131
|
+
|
|
132
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
133
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
134
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
135
|
+
this License, without any additional terms or conditions.
|
|
136
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
137
|
+
the terms of any separate license agreement you may have executed
|
|
138
|
+
with Licensor regarding such Contributions.
|
|
139
|
+
|
|
140
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
141
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
142
|
+
except as required for reasonable and customary use in describing the
|
|
143
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
144
|
+
|
|
145
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
146
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
147
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
148
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
149
|
+
implied, including, without limitation, any warranties or conditions
|
|
150
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
151
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
152
|
+
appropriateness of using or redistributing the Work and assume any
|
|
153
|
+
risks associated with Your exercise of permissions under this License.
|
|
154
|
+
|
|
155
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
156
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
157
|
+
unless required by applicable law (such as deliberate and grossly
|
|
158
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
159
|
+
liable to You for damages, including any direct, indirect, special,
|
|
160
|
+
incidental, or consequential damages of any character arising as a
|
|
161
|
+
result of this License or out of the use or inability to use the
|
|
162
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
163
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
164
|
+
other commercial damages or losses), even if such Contributor
|
|
165
|
+
has been advised of the possibility of such damages.
|
|
166
|
+
|
|
167
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
168
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
169
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
170
|
+
or other liability obligations and/or rights consistent with this
|
|
171
|
+
License. However, in accepting such obligations, You may act only
|
|
172
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
173
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
174
|
+
defend, and hold each Contributor harmless for any liability
|
|
175
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
176
|
+
of your accepting any such warranty or additional liability.
|
|
177
|
+
|
|
178
|
+
END OF TERMS AND CONDITIONS
|
|
179
|
+
|
|
180
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
181
|
+
|
|
182
|
+
To apply the Apache License to your work, attach the following
|
|
183
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
184
|
+
replaced with your own identifying information. (Don't include
|
|
185
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
186
|
+
comment syntax for the file format. We also recommend that a
|
|
187
|
+
file or class name and description of purpose be included on the
|
|
188
|
+
same "printed page" as the copyright notice for easier
|
|
189
|
+
identification within third-party archives.
|
|
190
|
+
|
|
191
|
+
Copyright (c) 2026 Clix (https://clix.so/)
|
|
192
|
+
|
|
193
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
194
|
+
you may not use this file except in compliance with the License.
|
|
195
|
+
You may obtain a copy of the License at
|
|
196
|
+
|
|
197
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
198
|
+
|
|
199
|
+
Unless required by applicable law or agreed to in writing, software
|
|
200
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
201
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
202
|
+
See the License for the specific language governing permissions and
|
|
203
|
+
limitations under the License.
|
|
204
|
+
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: clix-skill-creator
|
|
3
|
+
display-name: Skill Creator
|
|
4
|
+
short-description: Generate new Clix agent skills
|
|
5
|
+
description: Helps authors create new Clix agent skills by first researching the latest Clix
|
|
6
|
+
SDK + docs via the Clix MCP Server, then generating a complete skill folder
|
|
7
|
+
(SKILL.md, references, scripts, examples) aligned with the conventions in this
|
|
8
|
+
repository. Use when the user asks to create/author a new Clix skill, extend
|
|
9
|
+
the skills library, or when the user types `clix-skill-creator`.
|
|
10
|
+
user-invocable: true
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Clix Skill Creator
|
|
14
|
+
|
|
15
|
+
Use this skill to **create a new Clix skill** that matches a user's need, while
|
|
16
|
+
avoiding duplicated scope and **preventing hallucinated API usage** by relying
|
|
17
|
+
on the Clix MCP server as the source of truth.
|
|
18
|
+
|
|
19
|
+
This is a “meta-skill”: it does not integrate an SDK directly; it guides you to
|
|
20
|
+
produce **another skill folder** (docs + deterministic scripts) that does.
|
|
21
|
+
|
|
22
|
+
## When to use this skill
|
|
23
|
+
|
|
24
|
+
- User says: “Create a new skill for Clix that helps with X”
|
|
25
|
+
- Internal request: “We need a new skill for feature X in Clix”
|
|
26
|
+
- User provides a workflow that is not well-covered by existing skills
|
|
27
|
+
- User types: `clix-skill-creator`
|
|
28
|
+
|
|
29
|
+
## Non-goals (important)
|
|
30
|
+
|
|
31
|
+
- Do **not** create a new skill if the request can be satisfied by combining
|
|
32
|
+
existing skills (integration + event tracking + personalization + user
|
|
33
|
+
management + API-triggered campaigns).
|
|
34
|
+
- Do **not** invent SDK methods, endpoints, or constraints. If you can’t confirm
|
|
35
|
+
via MCP, treat it as unknown and ask the user or add a TODO note.
|
|
36
|
+
- Do **not** embed secrets, project IDs, API keys, or customer data in the skill.
|
|
37
|
+
|
|
38
|
+
## MCP-first (mandatory source of truth)
|
|
39
|
+
|
|
40
|
+
Before writing any new “Clix API behavior” or “SDK signature” into a newly
|
|
41
|
+
generated skill:
|
|
42
|
+
|
|
43
|
+
- **MUST** use `clix-mcp-server:search_docs` to confirm conceptual behavior,
|
|
44
|
+
limits, and console semantics.
|
|
45
|
+
- **MUST** use `clix-mcp-server:search_sdk` to confirm exact method signatures
|
|
46
|
+
for each platform (iOS/Android/Flutter/React Native) that the new skill will
|
|
47
|
+
mention.
|
|
48
|
+
|
|
49
|
+
If `clix-mcp-server` tools are not available:
|
|
50
|
+
|
|
51
|
+
- Ask the user whether to install the MCP server (prefer using the existing
|
|
52
|
+
installer in `skills/integration/scripts/install-mcp.sh`).
|
|
53
|
+
- If the user declines, proceed with an explicit “static fallback may be
|
|
54
|
+
outdated” warning and minimize hard claims.
|
|
55
|
+
|
|
56
|
+
## Workflow (copy + check off)
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
Clix skill creation progress:
|
|
60
|
+
- [ ] 1) Intake: user need → crisp problem statement + acceptance criteria
|
|
61
|
+
- [ ] 2) Scope check: confirm this isn’t already covered by existing skills
|
|
62
|
+
- [ ] 3) MCP research: gather evidence (docs + SDK signatures) for the target scope
|
|
63
|
+
- [ ] 4) Draft a Skill Brief (name, trigger phrases, inputs/outputs, guardrails)
|
|
64
|
+
- [ ] 5) Generate scaffold (SKILL.md + references/ + scripts/ + examples/)
|
|
65
|
+
- [ ] 6) Validate scaffold (structure + frontmatter + MCP-first section)
|
|
66
|
+
- [ ] 7) Wire-in (README + llms index + tests if needed)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 1) Intake: minimum questions
|
|
70
|
+
|
|
71
|
+
Ask only what’s needed to define a stable skill boundary:
|
|
72
|
+
|
|
73
|
+
- **Goal**: what outcome should the skill reliably produce?
|
|
74
|
+
- **Audience**: app devs, backend devs, marketers/ops, or mixed?
|
|
75
|
+
- **Platform** (if SDK-related): iOS / Android / Flutter / React Native
|
|
76
|
+
- **Clix capability**: push / in-app / email / audiences / journeys / etc.
|
|
77
|
+
- **Constraints**: PII policy, compliance, performance limits, rate limits
|
|
78
|
+
- **Success criteria**: what does “done” look like?
|
|
79
|
+
|
|
80
|
+
## 2) Reference official skills (match repo style)
|
|
81
|
+
|
|
82
|
+
Before creating a new skill, use the existing **official Clix skills** in this
|
|
83
|
+
repo as your style guide so the generated skill matches the standards here
|
|
84
|
+
(format, tone, workflow, validators), while still being tailored to the user’s
|
|
85
|
+
need.
|
|
86
|
+
|
|
87
|
+
- Study how they are written:
|
|
88
|
+
- YAML frontmatter conventions
|
|
89
|
+
- MCP-first “source of truth” behavior
|
|
90
|
+
- Progressive disclosure (`references/`, `scripts/`, `examples/`)
|
|
91
|
+
- Plan artifacts + deterministic validators (bash scripts)
|
|
92
|
+
- Then generate the new skill based on the user’s need using the same patterns.
|
|
93
|
+
If the need is clearly a tiny addition to an existing skill, prefer adding a
|
|
94
|
+
`references/` doc or `examples/` file there instead of creating a new skill.
|
|
95
|
+
|
|
96
|
+
- `clix-integration`
|
|
97
|
+
- `clix-event-tracking`
|
|
98
|
+
- `clix-user-management`
|
|
99
|
+
- `clix-personalization`
|
|
100
|
+
- `clix-api-triggered-campaigns`
|
|
101
|
+
|
|
102
|
+
## 3) MCP research: build an “Evidence Pack”
|
|
103
|
+
|
|
104
|
+
Create a short evidence pack that you will cite while writing the new skill:
|
|
105
|
+
|
|
106
|
+
- **Docs evidence** (from `clix-mcp-server:search_docs`)
|
|
107
|
+
- behavior guarantees
|
|
108
|
+
- constraints/limits
|
|
109
|
+
- console terminology
|
|
110
|
+
- **SDK evidence** (from `clix-mcp-server:search_sdk`)
|
|
111
|
+
- exact signatures per platform
|
|
112
|
+
- initialization / required params
|
|
113
|
+
- error behavior (throws? returns promise?)
|
|
114
|
+
|
|
115
|
+
Store the evidence in your notes (or as a `references/` markdown file in the new
|
|
116
|
+
skill), with the search queries you used so future maintainers can refresh it.
|
|
117
|
+
|
|
118
|
+
## 4) Draft a Skill Brief (output format)
|
|
119
|
+
|
|
120
|
+
Produce this brief for approval _before_ generating files:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
skill:
|
|
124
|
+
folder_name: "<kebab-case>" # e.g. "push-troubleshooting"
|
|
125
|
+
name: "clix-<kebab-case>" # e.g. "clix-push-troubleshooting"
|
|
126
|
+
display_name: "<Title Case>"
|
|
127
|
+
short_description: "<short>"
|
|
128
|
+
description: "<2-3 lines>"
|
|
129
|
+
user_invocable: true
|
|
130
|
+
|
|
131
|
+
triggers:
|
|
132
|
+
- "phrases the user might say"
|
|
133
|
+
|
|
134
|
+
inputs:
|
|
135
|
+
- "minimal inputs the skill will ask for"
|
|
136
|
+
|
|
137
|
+
outputs:
|
|
138
|
+
- "artifacts the skill produces (plan JSON, code changes, checklists)"
|
|
139
|
+
|
|
140
|
+
guardrails:
|
|
141
|
+
- "MCP-first requirements"
|
|
142
|
+
- "security / PII constraints"
|
|
143
|
+
|
|
144
|
+
files_to_generate:
|
|
145
|
+
skill_md: true
|
|
146
|
+
references:
|
|
147
|
+
- "<doc>.md"
|
|
148
|
+
scripts:
|
|
149
|
+
- "<script>.sh"
|
|
150
|
+
examples:
|
|
151
|
+
- "<optional>"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## 5) Generate scaffold (repo conventions)
|
|
155
|
+
|
|
156
|
+
In this repository, a “complete” skill folder should include:
|
|
157
|
+
|
|
158
|
+
- `SKILL.md` (with YAML frontmatter; MCP-first; workflow; progressive disclosure)
|
|
159
|
+
- `LICENSE.txt`
|
|
160
|
+
- `references/` (markdown docs; not empty)
|
|
161
|
+
- `scripts/` (deterministic bash scripts; not empty)
|
|
162
|
+
- `examples/` (optional, but recommended when copy/paste code is useful)
|
|
163
|
+
|
|
164
|
+
## 6) Validate scaffold (fast feedback loop)
|
|
165
|
+
|
|
166
|
+
After generating a new skill folder, validate it:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
bash <skill-dir>/scripts/validate-same-scope.sh path/to/installed/skill-creator path/to/new-skill-folder
|
|
170
|
+
bash <skill-dir>/scripts/validate-skill-location.sh path/to/new-skill-folder --mode repo
|
|
171
|
+
bash <skill-dir>/scripts/validate-skill-scaffold.sh path/to/new-skill-folder
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
This should check:
|
|
175
|
+
|
|
176
|
+
- the new skill is installed at the **same scope** as `skill-creator` (project-level
|
|
177
|
+
vs user-level), i.e. the new skill folder lives next to the installed
|
|
178
|
+
`skill-creator` under the same `.../skills/` directory
|
|
179
|
+
- the skill folder is in the correct `skills/<name>/` location (for this repo)
|
|
180
|
+
- required files exist
|
|
181
|
+
- `references/` and `scripts/` are present and non-empty
|
|
182
|
+
- `SKILL.md` has valid frontmatter keys
|
|
183
|
+
- the skill includes an MCP-first section referencing `clix-mcp-server`
|
|
184
|
+
|
|
185
|
+
## Progressive Disclosure
|
|
186
|
+
|
|
187
|
+
- **Level 1**: This `SKILL.md` (always loaded)
|
|
188
|
+
- **Level 2**: `references/` (load when authoring the new skill)
|
|
189
|
+
- **Level 3**: `examples/` (load when copy/pasting scaffolds)
|
|
190
|
+
- **Level 4**: `scripts/` (execute directly; do not load into context)
|
|
191
|
+
|
|
192
|
+
## References
|
|
193
|
+
|
|
194
|
+
- `references/skill-template.md`
|
|
195
|
+
- `references/mcp-research-playbook.md`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
skill:
|
|
2
|
+
folder_name: 'push-troubleshooting'
|
|
3
|
+
name: 'clix-push-troubleshooting'
|
|
4
|
+
display_name: 'Push Troubleshooting'
|
|
5
|
+
short_description: 'Debug push delivery and rendering issues'
|
|
6
|
+
description: >
|
|
7
|
+
Helps developers diagnose push notification delivery, permissions, token
|
|
8
|
+
registration, and template rendering issues. Uses Clix MCP Server as the
|
|
9
|
+
source of truth for SDK signatures and docs behavior.
|
|
10
|
+
user_invocable: true
|
|
11
|
+
|
|
12
|
+
triggers:
|
|
13
|
+
- 'push notifications not arriving'
|
|
14
|
+
- 'APNs token not registered'
|
|
15
|
+
- 'FCM token changed'
|
|
16
|
+
- 'message logs show template error'
|
|
17
|
+
|
|
18
|
+
inputs:
|
|
19
|
+
- 'platform (iOS/Android/Flutter/React Native)'
|
|
20
|
+
- 'app state (fresh install vs update)'
|
|
21
|
+
- 'what you see in Clix Message Logs (if available)'
|
|
22
|
+
|
|
23
|
+
outputs:
|
|
24
|
+
- 'a step-by-step debug plan'
|
|
25
|
+
- 'a minimal repro checklist'
|
|
26
|
+
- 'code changes (if needed) to fix initialization/token registration'
|
|
27
|
+
|
|
28
|
+
guardrails:
|
|
29
|
+
- 'MCP-first: do not claim SDK signatures without clix-mcp-server:search_sdk'
|
|
30
|
+
- 'no secrets; redact tokens and IDs'
|
|
31
|
+
- 'avoid duplicated scope with clix-integration unless troubleshooting-specific'
|
|
32
|
+
|
|
33
|
+
files_to_generate:
|
|
34
|
+
skill_md: true
|
|
35
|
+
references:
|
|
36
|
+
- 'debugging-checklist.md'
|
|
37
|
+
- 'common-failure-modes.md'
|
|
38
|
+
scripts:
|
|
39
|
+
- 'validate-debug-plan.sh'
|
|
40
|
+
examples:
|
|
41
|
+
- 'sample-log-snippets.md'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# MCP Research Playbook (Clix)
|
|
2
|
+
|
|
3
|
+
This playbook helps you **research accurately** before authoring a new Clix
|
|
4
|
+
skill. The goal is to collect enough evidence so the skill can be maintained
|
|
5
|
+
without guessing.
|
|
6
|
+
|
|
7
|
+
## Golden rules
|
|
8
|
+
|
|
9
|
+
- **SDK signatures must come from** `clix-mcp-server:search_sdk` (not memory).
|
|
10
|
+
- **Behavior/limits must come from** `clix-mcp-server:search_docs`.
|
|
11
|
+
- When evidence is unclear, write that uncertainty into the skill and ask the
|
|
12
|
+
user for confirmation instead of asserting.
|
|
13
|
+
|
|
14
|
+
## Recommended research sequence
|
|
15
|
+
|
|
16
|
+
### 1) Identify the “feature nouns”
|
|
17
|
+
|
|
18
|
+
Extract the keywords from the user need:
|
|
19
|
+
|
|
20
|
+
- Channel: push / in-app / email / SMS / etc.
|
|
21
|
+
- Trigger type: event-triggered / API-triggered / scheduled
|
|
22
|
+
- Domain: journeys, segments, templates, attribution, deep links, etc.
|
|
23
|
+
- Platform: iOS / Android / Flutter / React Native (if SDK involved)
|
|
24
|
+
|
|
25
|
+
### 2) Search docs first (conceptual contracts)
|
|
26
|
+
|
|
27
|
+
Use `clix-mcp-server:search_docs` queries like:
|
|
28
|
+
|
|
29
|
+
- `"<feature> limits"`
|
|
30
|
+
- `"<feature> troubleshooting"`
|
|
31
|
+
- `"<feature> required fields"`
|
|
32
|
+
- `"<endpoint or concept> authentication headers"`
|
|
33
|
+
- `"Message Logs template rendering errors"`
|
|
34
|
+
|
|
35
|
+
Record:
|
|
36
|
+
|
|
37
|
+
- constraints/limits (e.g. maximum attributes, payload limits)
|
|
38
|
+
- required fields
|
|
39
|
+
- “this is how the console behaves” statements
|
|
40
|
+
|
|
41
|
+
### 3) Search SDK next (exact signatures)
|
|
42
|
+
|
|
43
|
+
Use `clix-mcp-server:search_sdk` queries like:
|
|
44
|
+
|
|
45
|
+
- `"initialize"`
|
|
46
|
+
- `"setUserId"`
|
|
47
|
+
- `"setUserProperty"`
|
|
48
|
+
- `"trackEvent"`
|
|
49
|
+
- `"push token"`
|
|
50
|
+
- `"<feature name>"` + platform filters
|
|
51
|
+
|
|
52
|
+
For each platform you care about, capture:
|
|
53
|
+
|
|
54
|
+
- method name + parameters (types if available)
|
|
55
|
+
- return type (sync vs async)
|
|
56
|
+
- error behavior (throws? returns error object?)
|
|
57
|
+
|
|
58
|
+
### 4) Convert evidence into a skill contract
|
|
59
|
+
|
|
60
|
+
In the new skill’s `SKILL.md`:
|
|
61
|
+
|
|
62
|
+
- include an MCP-first section
|
|
63
|
+
- include concrete “workflow” steps
|
|
64
|
+
- avoid large static API tables unless you can keep them synced (prefer “use MCP
|
|
65
|
+
to fetch the exact signature” instead)
|
|
66
|
+
|
|
67
|
+
## Suggested “Evidence Pack” format
|
|
68
|
+
|
|
69
|
+
In the new skill’s `references/`, create an `evidence.md` (or similar) containing:
|
|
70
|
+
|
|
71
|
+
- the **queries** you ran
|
|
72
|
+
- the **high-signal excerpts** (short)
|
|
73
|
+
- a short “what we conclude” paragraph per excerpt
|
|
74
|
+
|
|
75
|
+
This makes maintenance and debugging dramatically easier.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Skill Template (for new Clix skills)
|
|
2
|
+
|
|
3
|
+
This document is a **copy/paste scaffold** for creating a new skill in the style
|
|
4
|
+
of this repository.
|
|
5
|
+
|
|
6
|
+
## Folder structure
|
|
7
|
+
|
|
8
|
+
Create:
|
|
9
|
+
|
|
10
|
+
- `skills/<folder-name>/SKILL.md`
|
|
11
|
+
- `skills/<folder-name>/LICENSE.txt`
|
|
12
|
+
- `skills/<folder-name>/references/<docs>.md` (at least 1 file)
|
|
13
|
+
- `skills/<folder-name>/scripts/<script>.sh` (at least 1 file)
|
|
14
|
+
- `skills/<folder-name>/examples/` (optional but recommended)
|
|
15
|
+
|
|
16
|
+
## `SKILL.md` skeleton
|
|
17
|
+
|
|
18
|
+
```markdown
|
|
19
|
+
---
|
|
20
|
+
name: clix-<kebab-case>
|
|
21
|
+
display-name: <Title Case>
|
|
22
|
+
short-description: <short>
|
|
23
|
+
description: <2-3 lines. Include when to use. Mention MCP-first explicitly.>
|
|
24
|
+
user-invocable: true
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# <Title Case>
|
|
28
|
+
|
|
29
|
+
## What this skill does
|
|
30
|
+
|
|
31
|
+
- ...
|
|
32
|
+
|
|
33
|
+
## MCP-first (source of truth)
|
|
34
|
+
|
|
35
|
+
If Clix MCP tools are available, treat them as the **source of truth**:
|
|
36
|
+
|
|
37
|
+
- `clix-mcp-server:search_docs` for conceptual behavior + limits
|
|
38
|
+
- `clix-mcp-server:search_sdk` for platform signatures (when SDK calls are involved)
|
|
39
|
+
|
|
40
|
+
If MCP tools are not available:
|
|
41
|
+
|
|
42
|
+
- Ask to install MCP (preferred), otherwise use references/ and clearly warn that
|
|
43
|
+
static docs may be outdated.
|
|
44
|
+
|
|
45
|
+
## Workflow (copy + check off)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
<Skill> progress:
|
|
49
|
+
|
|
50
|
+
- [ ] 1. Confirm minimum inputs
|
|
51
|
+
- [ ] 2. Draft a plan artifact (JSON / checklist / table)
|
|
52
|
+
- [ ] 3. Validate plan (script)
|
|
53
|
+
- [ ] 4. Implement (code/config)
|
|
54
|
+
- [ ] 5. Verify (Clix console + runtime)
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Progressive Disclosure
|
|
59
|
+
|
|
60
|
+
- **Level 1**: This `SKILL.md`
|
|
61
|
+
- **Level 2**: `references/`
|
|
62
|
+
- **Level 3**: `examples/`
|
|
63
|
+
- **Level 4**: `scripts/` (execute; do not load)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Quality checklist (before publishing)
|
|
67
|
+
|
|
68
|
+
- **No hallucinations**: every SDK signature in the skill can be re-derived from
|
|
69
|
+
`clix-mcp-server:search_sdk` queries documented in references.
|
|
70
|
+
- **No secrets**: no project IDs / API keys / customer data in examples.
|
|
71
|
+
- **Scope crisp**: the skill does one job well; if it’s a grab bag, split it.
|
|
72
|
+
- **Backstops**: include a deterministic script for validating the “plan artifact”
|
|
73
|
+
(JSON schema or structure checks).
|
|
74
|
+
- **Good UX**: minimal intake questions; concrete outputs the user can approve.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Validate that a newly generated skill is installed at the same scope as this skill:
|
|
4
|
+
# it must live under the same parent "skills" directory as the installed `skill-creator`.
|
|
5
|
+
#
|
|
6
|
+
# Rationale:
|
|
7
|
+
# - If `skill-creator` is installed at project level (e.g. .cursor/skills/skill-creator),
|
|
8
|
+
# the generated skill should also be project level (e.g. .cursor/skills/<new-skill>).
|
|
9
|
+
# - If `skill-creator` is installed at user/global level (e.g. ~/.cursor/skills/skill-creator),
|
|
10
|
+
# the generated skill should also be user/global (e.g. ~/.cursor/skills/<new-skill>).
|
|
11
|
+
#
|
|
12
|
+
# Usage:
|
|
13
|
+
# bash skills/skill-creator/scripts/validate-same-scope.sh <skill-creator-dir> <new-skill-dir>
|
|
14
|
+
#
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
creator_dir="${1:-}"
|
|
18
|
+
new_skill_dir="${2:-}"
|
|
19
|
+
|
|
20
|
+
if [[ -z "$creator_dir" || -z "$new_skill_dir" ]]; then
|
|
21
|
+
echo "Usage: bash skills/skill-creator/scripts/validate-same-scope.sh <skill-creator-dir> <new-skill-dir>" >&2
|
|
22
|
+
exit 2
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
if [[ ! -d "$creator_dir" ]]; then
|
|
26
|
+
echo "Error: skill-creator directory not found: $creator_dir" >&2
|
|
27
|
+
exit 2
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
if [[ ! -d "$new_skill_dir" ]]; then
|
|
31
|
+
echo "Error: new skill directory not found: $new_skill_dir" >&2
|
|
32
|
+
exit 2
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
creator_parent="$(dirname "$creator_dir")"
|
|
36
|
+
new_parent="$(dirname "$new_skill_dir")"
|
|
37
|
+
|
|
38
|
+
creator_parent_base="$(basename "$creator_parent")"
|
|
39
|
+
new_parent_base="$(basename "$new_parent")"
|
|
40
|
+
|
|
41
|
+
if [[ "$creator_parent_base" != "skills" && "$creator_parent_base" != "skill" && "$creator_parent_base" != ".skills" ]]; then
|
|
42
|
+
echo "ERROR: skill-creator must live under a skills directory (skills/ or skill/ or .skills/)." >&2
|
|
43
|
+
echo " creator_dir: $creator_dir" >&2
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
if [[ "$new_parent_base" != "skills" && "$new_parent_base" != "skill" && "$new_parent_base" != ".skills" ]]; then
|
|
48
|
+
echo "ERROR: new skill must live under a skills directory (skills/ or skill/ or .skills/)." >&2
|
|
49
|
+
echo " new_skill_dir: $new_skill_dir" >&2
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
if [[ "$creator_parent" != "$new_parent" ]]; then
|
|
54
|
+
echo "ERROR: scope mismatch. Expected new skill to be installed next to skill-creator under the same skills directory." >&2
|
|
55
|
+
echo " skill_creator_parent: $creator_parent" >&2
|
|
56
|
+
echo " new_skill_parent: $new_parent" >&2
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
echo "OK: skill scope matches (same parent skills directory)"
|
|
61
|
+
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Validate that a generated skill folder is placed in the correct "skills" directory.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# bash skills/skill-creator/scripts/validate-skill-location.sh <skill-folder> [--mode repo|client] [--client <name>]
|
|
7
|
+
#
|
|
8
|
+
# Modes:
|
|
9
|
+
# - repo : expects the skill folder to live under: skills/<skill-folder-name>/
|
|
10
|
+
# - client: expects the skill folder to live under a client skills directory:
|
|
11
|
+
# (.*)/skills/<skill-folder-name>/ OR (.*)/skill/<skill-folder-name>/ (OpenCode)
|
|
12
|
+
#
|
|
13
|
+
# If --client is provided in client mode, this script will also check that the path
|
|
14
|
+
# contains the expected client directory segment (best-effort).
|
|
15
|
+
#
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
skill_dir="${1:-}"
|
|
19
|
+
mode="repo"
|
|
20
|
+
client=""
|
|
21
|
+
|
|
22
|
+
shift || true
|
|
23
|
+
while [[ "${1:-}" != "" ]]; do
|
|
24
|
+
case "$1" in
|
|
25
|
+
--mode)
|
|
26
|
+
if [[ -z "${2:-}" || "${2:-}" == "-"* ]]; then
|
|
27
|
+
echo "Error: --mode requires a value" >&2
|
|
28
|
+
exit 2
|
|
29
|
+
fi
|
|
30
|
+
mode="${2:-}"
|
|
31
|
+
shift 2
|
|
32
|
+
;;
|
|
33
|
+
--client)
|
|
34
|
+
if [[ -z "${2:-}" || "${2:-}" == "-"* ]]; then
|
|
35
|
+
echo "Error: --client requires a value" >&2
|
|
36
|
+
exit 2
|
|
37
|
+
fi
|
|
38
|
+
client="${2:-}"
|
|
39
|
+
shift 2
|
|
40
|
+
;;
|
|
41
|
+
-h|--help)
|
|
42
|
+
cat <<'EOF'
|
|
43
|
+
Validate skill folder location.
|
|
44
|
+
|
|
45
|
+
Usage:
|
|
46
|
+
bash skills/skill-creator/scripts/validate-skill-location.sh <skill-folder> [--mode repo|client] [--client <name>]
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
bash skills/skill-creator/scripts/validate-skill-location.sh skills/personalization --mode repo
|
|
50
|
+
bash skills/skill-creator/scripts/validate-skill-location.sh .cursor/skills/personalization --mode client --client cursor
|
|
51
|
+
EOF
|
|
52
|
+
exit 0
|
|
53
|
+
;;
|
|
54
|
+
*)
|
|
55
|
+
echo "Unknown arg: $1" >&2
|
|
56
|
+
exit 2
|
|
57
|
+
;;
|
|
58
|
+
esac
|
|
59
|
+
done
|
|
60
|
+
|
|
61
|
+
if [[ -z "$skill_dir" ]]; then
|
|
62
|
+
echo "Error: missing <skill-folder> argument" >&2
|
|
63
|
+
exit 2
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
if [[ ! -d "$skill_dir" ]]; then
|
|
67
|
+
echo "Error: directory not found: $skill_dir" >&2
|
|
68
|
+
exit 2
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
skills_parent="$(basename "$(dirname "$skill_dir")")"
|
|
72
|
+
|
|
73
|
+
case "$mode" in
|
|
74
|
+
repo)
|
|
75
|
+
if [[ "$skills_parent" != "skills" ]]; then
|
|
76
|
+
echo "ERROR: Invalid location: expected skill folder under 'skills/<name>/' but got parent '$skills_parent'." >&2
|
|
77
|
+
echo " Path: $skill_dir" >&2
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
;;
|
|
81
|
+
client)
|
|
82
|
+
# Client installs usually use "skills/" (most clients), "skill/" (OpenCode),
|
|
83
|
+
# or ".skills/" (Letta).
|
|
84
|
+
if [[ "$skills_parent" != "skills" && "$skills_parent" != "skill" && "$skills_parent" != ".skills" ]]; then
|
|
85
|
+
echo "ERROR: Invalid location: expected skill folder under '<client>/(skills|skill|.skills)/<name>/' but got parent '$skills_parent'." >&2
|
|
86
|
+
echo " Path: $skill_dir" >&2
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
if [[ -n "$client" ]]; then
|
|
91
|
+
# Best-effort path segment checks (not exhaustive, but catches common mistakes).
|
|
92
|
+
case "${client,,}" in
|
|
93
|
+
cursor)
|
|
94
|
+
[[ "$skill_dir" == *"/.cursor/skills/"* || "$skill_dir" == ".cursor/skills/"* ]] || {
|
|
95
|
+
echo "ERROR: Expected Cursor skill path to include '.cursor/skills/'" >&2
|
|
96
|
+
echo " Path: $skill_dir" >&2
|
|
97
|
+
exit 1
|
|
98
|
+
}
|
|
99
|
+
;;
|
|
100
|
+
claude|claude-code)
|
|
101
|
+
[[ "$skill_dir" == *"/.claude/skills/"* || "$skill_dir" == ".claude/skills/"* ]] || {
|
|
102
|
+
echo "ERROR: Expected Claude skill path to include '.claude/skills/'" >&2
|
|
103
|
+
echo " Path: $skill_dir" >&2
|
|
104
|
+
exit 1
|
|
105
|
+
}
|
|
106
|
+
;;
|
|
107
|
+
codex)
|
|
108
|
+
[[ "$skill_dir" == *"/.codex/skills/"* || "$skill_dir" == ".codex/skills/"* ]] || {
|
|
109
|
+
echo "ERROR: Expected Codex skill path to include '.codex/skills/'" >&2
|
|
110
|
+
echo " Path: $skill_dir" >&2
|
|
111
|
+
exit 1
|
|
112
|
+
}
|
|
113
|
+
;;
|
|
114
|
+
opencode)
|
|
115
|
+
[[ "$skill_dir" == *"/.opencode/skill/"* || "$skill_dir" == ".opencode/skill/"* ]] || {
|
|
116
|
+
echo "ERROR: Expected OpenCode skill path to include '.opencode/skill/'" >&2
|
|
117
|
+
echo " Path: $skill_dir" >&2
|
|
118
|
+
exit 1
|
|
119
|
+
}
|
|
120
|
+
# OpenCode uses singular "skill", reject "skills" for this client.
|
|
121
|
+
[[ "$skill_dir" != *"/.opencode/skills/"* && "$skill_dir" != ".opencode/skills/"* ]] || {
|
|
122
|
+
echo "ERROR: Expected OpenCode skill path to include '.opencode/skill/' (singular), not '.opencode/skills/'" >&2
|
|
123
|
+
echo " Path: $skill_dir" >&2
|
|
124
|
+
exit 1
|
|
125
|
+
}
|
|
126
|
+
;;
|
|
127
|
+
vscode)
|
|
128
|
+
[[ "$skill_dir" == *"/.vscode/skills/"* || "$skill_dir" == ".vscode/skills/"* ]] || {
|
|
129
|
+
echo "ERROR: Expected VS Code skill path to include '.vscode/skills/'" >&2
|
|
130
|
+
echo " Path: $skill_dir" >&2
|
|
131
|
+
exit 1
|
|
132
|
+
}
|
|
133
|
+
;;
|
|
134
|
+
amp)
|
|
135
|
+
# Amp uses `.agents/skills/` in a workspace and `~/.config/agents/skills/` globally.
|
|
136
|
+
[[ "$skill_dir" == *"/.agents/skills/"* || "$skill_dir" == ".agents/skills/"* ]] || {
|
|
137
|
+
echo "ERROR: Expected Amp skill path to include '.agents/skills/'" >&2
|
|
138
|
+
echo " Path: $skill_dir" >&2
|
|
139
|
+
exit 1
|
|
140
|
+
}
|
|
141
|
+
;;
|
|
142
|
+
goose)
|
|
143
|
+
# Goose supports both goose-specific and portable skill locations.
|
|
144
|
+
[[
|
|
145
|
+
"$skill_dir" == *"/.goose/skills/"* ||
|
|
146
|
+
"$skill_dir" == ".goose/skills/"* ||
|
|
147
|
+
"$skill_dir" == *"/.agents/skills/"* ||
|
|
148
|
+
"$skill_dir" == ".agents/skills/"*
|
|
149
|
+
]] || {
|
|
150
|
+
echo "ERROR: Expected Goose skill path to include '.goose/skills/' or '.agents/skills/'" >&2
|
|
151
|
+
echo " Path: $skill_dir" >&2
|
|
152
|
+
exit 1
|
|
153
|
+
}
|
|
154
|
+
;;
|
|
155
|
+
github|copilot)
|
|
156
|
+
[[ "$skill_dir" == *"/.github/skills/"* || "$skill_dir" == ".github/skills/"* ]] || {
|
|
157
|
+
echo "ERROR: Expected GitHub Copilot skill path to include '.github/skills/'" >&2
|
|
158
|
+
echo " Path: $skill_dir" >&2
|
|
159
|
+
exit 1
|
|
160
|
+
}
|
|
161
|
+
;;
|
|
162
|
+
gemini)
|
|
163
|
+
[[ "$skill_dir" == *"/.gemini/skills/"* || "$skill_dir" == ".gemini/skills/"* ]] || {
|
|
164
|
+
echo "ERROR: Expected Gemini skill path to include '.gemini/skills/'" >&2
|
|
165
|
+
echo " Path: $skill_dir" >&2
|
|
166
|
+
exit 1
|
|
167
|
+
}
|
|
168
|
+
;;
|
|
169
|
+
kiro)
|
|
170
|
+
[[ "$skill_dir" == *"/.kiro/skills/"* || "$skill_dir" == ".kiro/skills/"* ]] || {
|
|
171
|
+
echo "ERROR: Expected Kiro skill path to include '.kiro/skills/'" >&2
|
|
172
|
+
echo " Path: $skill_dir" >&2
|
|
173
|
+
exit 1
|
|
174
|
+
}
|
|
175
|
+
;;
|
|
176
|
+
amazonq)
|
|
177
|
+
[[ "$skill_dir" == *"/.amazonq/skills/"* || "$skill_dir" == ".amazonq/skills/"* ]] || {
|
|
178
|
+
echo "ERROR: Expected AmazonQ skill path to include '.amazonq/skills/'" >&2
|
|
179
|
+
echo " Path: $skill_dir" >&2
|
|
180
|
+
exit 1
|
|
181
|
+
}
|
|
182
|
+
;;
|
|
183
|
+
letta)
|
|
184
|
+
# Letta uses a root-level `.skills/` directory.
|
|
185
|
+
[[ "$skill_dir" == *"/.skills/"* || "$skill_dir" == ".skills/"* ]] || {
|
|
186
|
+
echo "ERROR: Expected Letta skill path to include '.skills/'" >&2
|
|
187
|
+
echo " Path: $skill_dir" >&2
|
|
188
|
+
exit 1
|
|
189
|
+
}
|
|
190
|
+
;;
|
|
191
|
+
*)
|
|
192
|
+
# Unknown client; skip strict segment check.
|
|
193
|
+
;;
|
|
194
|
+
esac
|
|
195
|
+
fi
|
|
196
|
+
;;
|
|
197
|
+
*)
|
|
198
|
+
echo "Error: --mode must be 'repo' or 'client' (got '$mode')" >&2
|
|
199
|
+
exit 2
|
|
200
|
+
;;
|
|
201
|
+
esac
|
|
202
|
+
|
|
203
|
+
echo "OK: skill location looks OK ($mode)"
|
|
204
|
+
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Validate a Clix Agent Skill scaffold (folder structure + frontmatter).
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# bash skills/skill-creator/scripts/validate-skill-scaffold.sh path/to/skill-folder
|
|
7
|
+
#
|
|
8
|
+
# Validates:
|
|
9
|
+
# - SKILL.md and LICENSE.txt exist
|
|
10
|
+
# - references/ and scripts/ exist and are non-empty
|
|
11
|
+
# - SKILL.md has YAML frontmatter with required keys
|
|
12
|
+
# - SKILL.md contains an MCP-first section that references `clix-mcp-server`
|
|
13
|
+
#
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
skill_dir="${1:-}"
|
|
17
|
+
if [[ -z "$skill_dir" ]]; then
|
|
18
|
+
echo "Usage: bash skills/skill-creator/scripts/validate-skill-scaffold.sh path/to/skill-folder" >&2
|
|
19
|
+
exit 2
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
if [[ ! -d "$skill_dir" ]]; then
|
|
23
|
+
echo "Error: directory not found: $skill_dir" >&2
|
|
24
|
+
exit 2
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
validate_with_python() {
|
|
28
|
+
python3 - "$skill_dir" <<'PY'
|
|
29
|
+
import os
|
|
30
|
+
import re
|
|
31
|
+
import sys
|
|
32
|
+
|
|
33
|
+
skill_dir = sys.argv[1]
|
|
34
|
+
|
|
35
|
+
errors = []
|
|
36
|
+
|
|
37
|
+
def require_file(name: str):
|
|
38
|
+
p = os.path.join(skill_dir, name)
|
|
39
|
+
if not os.path.isfile(p):
|
|
40
|
+
errors.append(f"missing required file: {name}")
|
|
41
|
+
return p
|
|
42
|
+
|
|
43
|
+
def require_non_empty_dir(name: str):
|
|
44
|
+
p = os.path.join(skill_dir, name)
|
|
45
|
+
if not os.path.isdir(p):
|
|
46
|
+
errors.append(f"missing required directory: {name}/")
|
|
47
|
+
return
|
|
48
|
+
entries = [e for e in os.listdir(p) if not e.startswith(".")]
|
|
49
|
+
if len(entries) == 0:
|
|
50
|
+
errors.append(f"required directory is empty: {name}/")
|
|
51
|
+
|
|
52
|
+
skill_md_path = require_file("SKILL.md")
|
|
53
|
+
require_file("LICENSE.txt")
|
|
54
|
+
require_non_empty_dir("references")
|
|
55
|
+
require_non_empty_dir("scripts")
|
|
56
|
+
|
|
57
|
+
frontmatter = None
|
|
58
|
+
try:
|
|
59
|
+
with open(skill_md_path, "r", encoding="utf-8") as f:
|
|
60
|
+
content = f.read()
|
|
61
|
+
except Exception as e:
|
|
62
|
+
errors.append(f"failed to read SKILL.md: {e}")
|
|
63
|
+
content = ""
|
|
64
|
+
|
|
65
|
+
m = re.match(r"^---\n([\s\S]*?)\n---\n", content)
|
|
66
|
+
if not m:
|
|
67
|
+
errors.append("SKILL.md must start with YAML frontmatter delimited by ---")
|
|
68
|
+
else:
|
|
69
|
+
frontmatter = m.group(1)
|
|
70
|
+
# IMPORTANT: avoid substring false-positives:
|
|
71
|
+
# - "display-name:" contains "name:"
|
|
72
|
+
# - "short-description:" contains "description:"
|
|
73
|
+
# So we must match keys at beginning-of-line only.
|
|
74
|
+
def has_key(key: str) -> bool:
|
|
75
|
+
return re.search(rf"^{re.escape(key)}\s*", frontmatter, re.M) is not None
|
|
76
|
+
|
|
77
|
+
required_keys = [
|
|
78
|
+
"name:",
|
|
79
|
+
"display-name:",
|
|
80
|
+
"short-description:",
|
|
81
|
+
"description:",
|
|
82
|
+
"user-invocable:",
|
|
83
|
+
]
|
|
84
|
+
for k in required_keys:
|
|
85
|
+
if not has_key(k):
|
|
86
|
+
errors.append(f"frontmatter missing key: {k.rstrip(':')}")
|
|
87
|
+
|
|
88
|
+
name_match = re.search(r"^name:\s*(.+)$", frontmatter, re.M)
|
|
89
|
+
if name_match:
|
|
90
|
+
name = name_match.group(1).strip()
|
|
91
|
+
if not name.startswith("clix-"):
|
|
92
|
+
errors.append("frontmatter name should start with 'clix-'")
|
|
93
|
+
|
|
94
|
+
inv_match = re.search(r"^user-invocable:\s*(.+)$", frontmatter, re.M)
|
|
95
|
+
if inv_match:
|
|
96
|
+
val = inv_match.group(1).strip().lower()
|
|
97
|
+
if val not in ("true", "false"):
|
|
98
|
+
errors.append("frontmatter user-invocable must be true or false")
|
|
99
|
+
|
|
100
|
+
if "clix-mcp-server" not in content:
|
|
101
|
+
errors.append("SKILL.md must reference 'clix-mcp-server' (MCP-first requirement)")
|
|
102
|
+
|
|
103
|
+
if errors:
|
|
104
|
+
print("ERROR: skill scaffold validation failed:")
|
|
105
|
+
for e in errors:
|
|
106
|
+
print(f"- {e}")
|
|
107
|
+
sys.exit(1)
|
|
108
|
+
|
|
109
|
+
print("OK: skill scaffold validation passed")
|
|
110
|
+
PY
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
114
|
+
validate_with_python
|
|
115
|
+
exit 0
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
echo "Warning: python3 not found; falling back to basic checks with node if available." >&2
|
|
119
|
+
if command -v node >/dev/null 2>&1; then
|
|
120
|
+
node - "$skill_dir" <<'NODE'
|
|
121
|
+
const fs = require("fs");
|
|
122
|
+
const path = require("path");
|
|
123
|
+
|
|
124
|
+
const skillDir = process.argv[1];
|
|
125
|
+
const errors = [];
|
|
126
|
+
|
|
127
|
+
function hasFrontmatterKey(frontmatter, key) {
|
|
128
|
+
// Match key at beginning of line only (avoid substring collisions):
|
|
129
|
+
// - "display-name:" contains "name:"
|
|
130
|
+
// - "short-description:" contains "description:"
|
|
131
|
+
const re = new RegExp(`^${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*`, "m");
|
|
132
|
+
return re.test(frontmatter);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function requireFile(name) {
|
|
136
|
+
const p = path.join(skillDir, name);
|
|
137
|
+
if (!fs.existsSync(p) || !fs.statSync(p).isFile()) errors.push(`missing required file: ${name}`);
|
|
138
|
+
return p;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function requireNonEmptyDir(name) {
|
|
142
|
+
const p = path.join(skillDir, name);
|
|
143
|
+
if (!fs.existsSync(p) || !fs.statSync(p).isDirectory()) {
|
|
144
|
+
errors.push(`missing required directory: ${name}/`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const entries = fs.readdirSync(p).filter((e) => !e.startsWith("."));
|
|
148
|
+
if (entries.length === 0) errors.push(`required directory is empty: ${name}/`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const skillMd = requireFile("SKILL.md");
|
|
152
|
+
requireFile("LICENSE.txt");
|
|
153
|
+
requireNonEmptyDir("references");
|
|
154
|
+
requireNonEmptyDir("scripts");
|
|
155
|
+
|
|
156
|
+
let content = "";
|
|
157
|
+
try {
|
|
158
|
+
content = fs.readFileSync(skillMd, "utf8");
|
|
159
|
+
} catch (e) {
|
|
160
|
+
errors.push(`failed to read SKILL.md: ${String(e)}`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Frontmatter validation (best-effort; mirrors Python validator behavior).
|
|
164
|
+
if (!content.startsWith("---\n")) {
|
|
165
|
+
errors.push("SKILL.md must start with YAML frontmatter (---)");
|
|
166
|
+
} else {
|
|
167
|
+
const m = content.match(/^---\n([\s\S]*?)\n---\n/);
|
|
168
|
+
if (!m) {
|
|
169
|
+
errors.push("SKILL.md must start with YAML frontmatter delimited by ---");
|
|
170
|
+
} else {
|
|
171
|
+
const frontmatter = m[1];
|
|
172
|
+
const required = ["name:", "display-name:", "short-description:", "description:", "user-invocable:"];
|
|
173
|
+
for (const k of required) {
|
|
174
|
+
if (!hasFrontmatterKey(frontmatter, k)) {
|
|
175
|
+
errors.push(`frontmatter missing key: ${k.replace(/:$/, "")}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
|
|
180
|
+
if (nameMatch) {
|
|
181
|
+
const name = (nameMatch[1] || "").trim();
|
|
182
|
+
if (!name.startsWith("clix-")) errors.push("frontmatter name should start with 'clix-'");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const invMatch = frontmatter.match(/^user-invocable:\s*(.+)$/m);
|
|
186
|
+
if (invMatch) {
|
|
187
|
+
const val = (invMatch[1] || "").trim().toLowerCase();
|
|
188
|
+
if (!["true", "false"].includes(val)) errors.push("frontmatter user-invocable must be true or false");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (!content.includes("clix-mcp-server")) errors.push("SKILL.md must reference 'clix-mcp-server'");
|
|
193
|
+
|
|
194
|
+
if (errors.length) {
|
|
195
|
+
console.error("ERROR: skill scaffold validation failed:");
|
|
196
|
+
for (const e of errors) console.error(`- ${e}`);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
console.log("OK: skill scaffold validation passed");
|
|
201
|
+
NODE
|
|
202
|
+
exit 0
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
echo "Error: neither python3 nor node found; cannot validate." >&2
|
|
206
|
+
exit 2
|
|
207
|
+
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
name: clix-user-management
|
|
3
3
|
display-name: User Management
|
|
4
4
|
short-description: User management setup
|
|
5
|
-
description:
|
|
6
|
-
Implements Clix user identification and user properties (setUserId,
|
|
5
|
+
description: Implements Clix user identification and user properties (setUserId,
|
|
7
6
|
removeUserId, setUserProperty/setUserProperties,
|
|
8
7
|
removeUserProperty/removeUserProperties) with safe schemas, logout best
|
|
9
8
|
practices, and campaign-ready personalization/audience usage. Use when the
|