@trendai-crem/claude-skills 1.4.0 → 1.5.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 +26 -3
- package/cli.js +3 -1
- package/lib/handlers/index.js +2 -0
- package/lib/handlers/rules-dir.js +70 -0
- package/package.json +3 -2
- package/rules/confluence-editing.md +20 -0
- package/sources.json +5 -0
package/README.md
CHANGED
|
@@ -8,13 +8,14 @@ One-command Claude Code skill installer for the team. Installs curated AI agent
|
|
|
8
8
|
npx @trendai-crem/claude-skills
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
That's it. The command installs all
|
|
11
|
+
That's it. The command installs all four source types declared in `sources.json`:
|
|
12
12
|
|
|
13
13
|
| Source type | What it installs | How to change |
|
|
14
14
|
|-------------|-----------------|---------------|
|
|
15
|
+
| **rules-dir** | Team-shared rules to `~/.claude/rules/team/` (loaded in every session) | Add/remove `rules/<name>.md`, bump version, PR |
|
|
15
16
|
| **skills-repo** | [superpowers](https://github.com/obra/superpowers) — brainstorming, debugging, TDD, and more | Edit `sources.json`, bump version, PR |
|
|
16
17
|
| **skills-dir** | Team skills in this repo's `skills/` directory | Add/remove `skills/<name>/`, bump version, PR |
|
|
17
|
-
| **marketplace** | Plugins from `ai-skill-marketplace`, `claude-plugins-official`,
|
|
18
|
+
| **marketplace** | Plugins from `ai-skill-marketplace`, `claude-plugins-official`, `openai-codex`, and `everything-claude-code` | Edit `plugins` list in `sources.json`, bump version, PR |
|
|
18
19
|
|
|
19
20
|
Re-run to update everything:
|
|
20
21
|
|
|
@@ -24,6 +25,14 @@ npx @trendai-crem/claude-skills@latest
|
|
|
24
25
|
|
|
25
26
|
Auto-update runs at session start — you'll be notified when a new version is available and it installs automatically.
|
|
26
27
|
|
|
28
|
+
## Team Rules (`rules/`)
|
|
29
|
+
|
|
30
|
+
Rules are `.md` files installed to `~/.claude/rules/team/` and automatically loaded in every Claude session across all projects. Use rules for team-wide conventions that should always apply.
|
|
31
|
+
|
|
32
|
+
| Rule | Description |
|
|
33
|
+
|------|-------------|
|
|
34
|
+
| **confluence-editing** | Use `atlassian-tools` skill for Confluence edits — never use raw MCP update tools |
|
|
35
|
+
|
|
27
36
|
## Team Skills (`skills/`)
|
|
28
37
|
|
|
29
38
|
| Skill | Trigger | Description |
|
|
@@ -49,6 +58,16 @@ Installed from [ai-skill-marketplace](https://github.com/trend-ai-taskforce/ai-s
|
|
|
49
58
|
|
|
50
59
|
## For Maintainers
|
|
51
60
|
|
|
61
|
+
### Adding a team rule
|
|
62
|
+
|
|
63
|
+
1. Create a branch: `git checkout -b feat/add-<rule-name>`
|
|
64
|
+
2. Add `rules/<rule-name>.md` (plain markdown, no frontmatter needed)
|
|
65
|
+
3. Keep rules short (<50 lines) — they consume context window in every session
|
|
66
|
+
4. Bump version: `npm version patch`
|
|
67
|
+
5. Commit, push, open a PR, merge — CI publishes automatically
|
|
68
|
+
|
|
69
|
+
Rules are always overwritten on install (not no-clobber) to stay in sync with the repo.
|
|
70
|
+
|
|
52
71
|
### Adding a team skill
|
|
53
72
|
|
|
54
73
|
1. Create a branch: `git checkout -b feat/add-<skill-name>`
|
|
@@ -178,9 +197,13 @@ sources.json
|
|
|
178
197
|
↓
|
|
179
198
|
cli.js (thin orchestrator)
|
|
180
199
|
↓
|
|
181
|
-
lib/handlers/{skills-dir, skills-repo, marketplace}.js
|
|
200
|
+
lib/handlers/{rules-dir, skills-dir, skills-repo, marketplace}.js
|
|
182
201
|
↓
|
|
183
202
|
~/.claude/claude-skills-manifest.json (tracks what's installed)
|
|
203
|
+
↓
|
|
204
|
+
~/.claude/rules/team/ ← rules-dir handler
|
|
205
|
+
~/.claude/skills/ ← skills-dir, skills-repo handlers
|
|
206
|
+
~/.claude/plugins/ ← marketplace handler
|
|
184
207
|
```
|
|
185
208
|
|
|
186
209
|
Removals propagate automatically: remove an entry from `sources.json`, bump version, and the next auto-update uninstalls it for all team members.
|
package/cli.js
CHANGED
|
@@ -92,9 +92,11 @@ function installEccRules() {
|
|
|
92
92
|
const eccRulesDir = join(eccMarketplace, 'rules');
|
|
93
93
|
if (!existsSync(eccRulesDir)) return;
|
|
94
94
|
|
|
95
|
+
const ALLOWED_LANGS = new Set(['common', 'typescript', 'java', 'golang', 'python', 'swift']);
|
|
96
|
+
|
|
95
97
|
const destDir = join(homedir(), '.claude', 'rules');
|
|
96
98
|
const languages = readdirSync(eccRulesDir, { withFileTypes: true })
|
|
97
|
-
.filter(d => d.isDirectory())
|
|
99
|
+
.filter(d => d.isDirectory() && ALLOWED_LANGS.has(d.name))
|
|
98
100
|
.map(d => d.name);
|
|
99
101
|
|
|
100
102
|
let copied = 0;
|
package/lib/handlers/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { skillsDirHandler } from './skills-dir.js';
|
|
2
2
|
import { skillsRepoHandler } from './skills-repo.js';
|
|
3
3
|
import { marketplaceHandler } from './marketplace.js';
|
|
4
|
+
import { rulesDirHandler } from './rules-dir.js';
|
|
4
5
|
|
|
5
6
|
// Use Object.create(null) to prevent prototype chain traversal on adversarial type values.
|
|
6
7
|
export const HANDLERS = Object.create(null);
|
|
7
8
|
HANDLERS['skills-dir'] = skillsDirHandler;
|
|
8
9
|
HANDLERS['skills-repo'] = skillsRepoHandler;
|
|
9
10
|
HANDLERS['marketplace'] = marketplaceHandler;
|
|
11
|
+
HANDLERS['rules-dir'] = rulesDirHandler;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { readdirSync, copyFileSync, mkdirSync, existsSync, unlinkSync, rmdirSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
|
|
5
|
+
const DEST_DIR = join(homedir(), '.claude', 'rules', 'team');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Handler for team-shared rules (type: "rules-dir").
|
|
9
|
+
* Copies .md files from <repo>/rules/ to ~/.claude/rules/team/.
|
|
10
|
+
*/
|
|
11
|
+
export const rulesDirHandler = {
|
|
12
|
+
/**
|
|
13
|
+
* Returns the set of rule file names in the source directory.
|
|
14
|
+
* @param {object} entry - Source entry (uses convention: <baseDir>/rules/).
|
|
15
|
+
* @param {string} baseDir - Repository base directory.
|
|
16
|
+
* @returns {Set<string>|null}
|
|
17
|
+
*/
|
|
18
|
+
getDesired(entry, baseDir) {
|
|
19
|
+
const srcDir = join(baseDir, entry.path ?? 'rules');
|
|
20
|
+
try {
|
|
21
|
+
const names = readdirSync(srcDir)
|
|
22
|
+
.filter(f => f.endsWith('.md'))
|
|
23
|
+
.sort();
|
|
24
|
+
return new Set(names);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
console.warn(`\nWARN: Cannot read rules directory "${srcDir}": ${err.message}`);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Copies rule .md files to ~/.claude/rules/team/.
|
|
33
|
+
* Always overwrites to keep rules in sync with the repo.
|
|
34
|
+
* @returns {Array<{label, action, ok}>}
|
|
35
|
+
*/
|
|
36
|
+
install(entry, baseDir) {
|
|
37
|
+
const srcDir = join(baseDir, entry.path ?? 'rules');
|
|
38
|
+
mkdirSync(DEST_DIR, { recursive: true });
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const files = readdirSync(srcDir).filter(f => f.endsWith('.md'));
|
|
42
|
+
for (const file of files) {
|
|
43
|
+
copyFileSync(join(srcDir, file), join(DEST_DIR, file));
|
|
44
|
+
}
|
|
45
|
+
console.log(`\n Rules installed to ${DEST_DIR}/ (${files.length} files)`);
|
|
46
|
+
return [{ label: entry.label, action: 'install-group', ok: true }];
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.error(`\nFailed: ${entry.label} (${err.message})`);
|
|
49
|
+
return [{ label: entry.label, action: 'install-group', ok: false }];
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Removes stale rule files from ~/.claude/rules/team/.
|
|
55
|
+
* @param {string[]} staleItems - File names to remove.
|
|
56
|
+
* @returns {Array<{label, action, ok}>}
|
|
57
|
+
*/
|
|
58
|
+
uninstall(staleItems) {
|
|
59
|
+
return staleItems.map(file => {
|
|
60
|
+
const dest = join(DEST_DIR, file);
|
|
61
|
+
try {
|
|
62
|
+
if (existsSync(dest)) unlinkSync(dest);
|
|
63
|
+
return { label: file, action: 'uninstall', ok: true };
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.error(`\nFailed to remove rule ${file}: ${err.message}`);
|
|
66
|
+
return { label: file, action: 'uninstall', ok: false };
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trendai-crem/claude-skills",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Claude Code skills installer for the trendai-crem team",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"sources.json",
|
|
16
16
|
"marketplace.json",
|
|
17
17
|
"lib/",
|
|
18
|
-
"skills/"
|
|
18
|
+
"skills/",
|
|
19
|
+
"rules/"
|
|
19
20
|
],
|
|
20
21
|
"type": "module",
|
|
21
22
|
"engines": {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Confluence Editing
|
|
2
|
+
|
|
3
|
+
When editing Confluence pages, ALWAYS use the `atlassian-tools` skill
|
|
4
|
+
(confluence_cli.py retrieve → edit local .md → update --file).
|
|
5
|
+
|
|
6
|
+
NEVER use `mcp__atlassian__updateConfluencePage` with markdown contentFormat — it loses
|
|
7
|
+
diagrams, macros, panels, and other ADF elements.
|
|
8
|
+
|
|
9
|
+
NEVER use `mcp__atlassian__updateConfluencePage` with ADF contentFormat for large pages —
|
|
10
|
+
the body parameter has a size limit that truncates content.
|
|
11
|
+
|
|
12
|
+
Correct workflow:
|
|
13
|
+
1. `confluence_cli.py -o <project>/.atlassian retrieve <pageId>`
|
|
14
|
+
2. Edit the local `.md` file (Mermaid = ```mermaid blocks, macros = <!-- confluence-macro --> comments)
|
|
15
|
+
3. `confluence_cli.py -o <project>/.atlassian update <pageId> --file <path>.md`
|
|
16
|
+
|
|
17
|
+
The atlassian-tools skill handles:
|
|
18
|
+
- Bidirectional HTML↔Markdown conversion preserving all Confluence elements
|
|
19
|
+
- Version conflict detection with auto patch-merge
|
|
20
|
+
- Local caching for offline editing
|