claudient 0.1.0 → 0.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudient",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "The definitive Claude Code knowledge system — skills, agents, hooks, rules, and workflows.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -34,12 +34,14 @@
34
34
  "guides/",
35
35
  ".claude-plugin/",
36
36
  "CONTEXT.md",
37
- "README.md"
37
+ "README.md",
38
+ "index.json"
38
39
  ],
39
40
  "engines": {
40
41
  "node": ">=18"
41
42
  },
42
43
  "scripts": {
43
- "list": "node scripts/cli.js list"
44
+ "list": "node scripts/cli.js list",
45
+ "build-index": "node scripts/build-index.js"
44
46
  }
45
47
  }
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ // build-index.js — generates index.json, a machine-readable manifest of all content
3
+
4
+ const fs = require('fs')
5
+ const path = require('path')
6
+
7
+ const ROOT = path.resolve(__dirname, '..')
8
+ const LANGS = ['fr', 'de', 'nl', 'es']
9
+ const SKILL_CATEGORIES = ['backend', 'devops-infra', 'data-ml', 'database', 'finance-payments', 'ai-engineering', 'productivity']
10
+
11
+ function getFiles(dir, ext = '.md') {
12
+ const results = []
13
+ if (!fs.existsSync(dir)) return results
14
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
15
+ const full = path.join(dir, entry.name)
16
+ if (entry.isDirectory()) results.push(...getFiles(full, ext))
17
+ else if (entry.name.endsWith(ext)) results.push(full)
18
+ }
19
+ return results
20
+ }
21
+
22
+ function relPath(full) {
23
+ return full.replace(ROOT + '/', '')
24
+ }
25
+
26
+ function isTranslation(filepath) {
27
+ return LANGS.some(l => filepath.includes(`/${l}/`))
28
+ }
29
+
30
+ function getLang(filepath) {
31
+ for (const l of LANGS) {
32
+ if (filepath.includes(`/${l}/`)) return l
33
+ }
34
+ return 'en'
35
+ }
36
+
37
+ function readTitle(filepath) {
38
+ try {
39
+ const first = fs.readFileSync(filepath, 'utf-8').split('\n').find(l => l.startsWith('# '))
40
+ return first ? first.replace(/^# /, '').trim() : path.basename(filepath, '.md')
41
+ } catch {
42
+ return path.basename(filepath, '.md')
43
+ }
44
+ }
45
+
46
+ const index = {
47
+ version: require(path.join(ROOT, 'package.json')).version,
48
+ generated: new Date().toISOString(),
49
+ skills: [],
50
+ agents: [],
51
+ hooks: [],
52
+ rules: [],
53
+ workflows: [],
54
+ prompts: [],
55
+ guides: [],
56
+ }
57
+
58
+ // Skills
59
+ for (const cat of SKILL_CATEGORIES) {
60
+ const catDir = path.join(ROOT, 'skills', cat)
61
+ for (const file of getFiles(catDir)) {
62
+ const rel = relPath(file)
63
+ const lang = getLang(rel)
64
+ const slug = rel.replace(/^skills\//, '').replace(/\.md$/, '').replace(/\/(fr|de|nl|es)\//, '/')
65
+ index.skills.push({
66
+ id: slug,
67
+ category: cat,
68
+ lang,
69
+ title: readTitle(file),
70
+ file: rel,
71
+ })
72
+ }
73
+ }
74
+
75
+ // Agents
76
+ for (const file of getFiles(path.join(ROOT, 'agents'))) {
77
+ const rel = relPath(file)
78
+ const lang = getLang(rel)
79
+ const slug = rel.replace(/^agents\//, '').replace(/\.md$/, '').replace(/\/(fr|de|nl|es)\//, '/')
80
+ index.agents.push({ id: slug, lang, title: readTitle(file), file: rel })
81
+ }
82
+
83
+ // Hooks (md docs)
84
+ for (const file of getFiles(path.join(ROOT, 'hooks'))) {
85
+ const rel = relPath(file)
86
+ const cat = rel.split('/')[1]
87
+ const slug = path.basename(file, '.md')
88
+ index.hooks.push({ id: `${cat}/${slug}`, category: cat, title: readTitle(file), file: rel })
89
+ }
90
+
91
+ // Rules
92
+ for (const file of getFiles(path.join(ROOT, 'rules'))) {
93
+ const rel = relPath(file)
94
+ const lang = getLang(rel)
95
+ const slug = rel.replace(/^rules\//, '').replace(/\.md$/, '').replace(/\/(fr|de|nl|es)\//, '/')
96
+ index.rules.push({ id: slug, lang, title: readTitle(file), file: rel })
97
+ }
98
+
99
+ // Workflows
100
+ for (const file of getFiles(path.join(ROOT, 'workflows'))) {
101
+ const rel = relPath(file)
102
+ const lang = getLang(rel)
103
+ const slug = path.basename(file, '.md')
104
+ index.workflows.push({ id: slug, lang, title: readTitle(file), file: rel })
105
+ }
106
+
107
+ // Prompts
108
+ for (const file of getFiles(path.join(ROOT, 'prompts'))) {
109
+ const rel = relPath(file)
110
+ const lang = getLang(rel)
111
+ const cat = rel.split('/')[1]
112
+ const slug = `${cat}/${path.basename(file, '.md')}`
113
+ index.prompts.push({ id: slug.replace(/\/(fr|de|nl|es)\//, '/'), category: cat, lang, title: readTitle(file), file: rel })
114
+ }
115
+
116
+ // Guides
117
+ for (const file of getFiles(path.join(ROOT, 'guides'))) {
118
+ const rel = relPath(file)
119
+ const lang = getLang(rel)
120
+ const slug = path.basename(file, '.md')
121
+ index.guides.push({ id: slug, lang, title: readTitle(file), file: rel })
122
+ }
123
+
124
+ // Summary counts (English only)
125
+ const en = (arr) => arr.filter(i => i.lang === 'en' || !i.lang)
126
+ index.summary = {
127
+ skills: en(index.skills).length,
128
+ agents: en(index.agents).length,
129
+ hooks: index.hooks.length,
130
+ rules: en(index.rules).length,
131
+ workflows: en(index.workflows).length,
132
+ prompts: en(index.prompts).length,
133
+ guides: en(index.guides).length,
134
+ languages: ['en', ...LANGS],
135
+ }
136
+
137
+ const outPath = path.join(ROOT, 'index.json')
138
+ fs.writeFileSync(outPath, JSON.stringify(index, null, 2) + '\n')
139
+ console.log(`Generated index.json — ${index.summary.skills} skills, ${index.summary.agents} agents, ${index.summary.hooks} hooks`)