@cregis-dev/cckit 0.6.5 → 0.6.7

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.
Files changed (52) hide show
  1. package/README.md +221 -221
  2. package/package.json +1 -1
  3. package/registry.json +145 -128
  4. package/src/cli.js +79 -79
  5. package/src/commands/init.js +174 -161
  6. package/src/commands/status.js +125 -85
  7. package/src/commands/update.js +192 -151
  8. package/src/core/config.js +82 -74
  9. package/src/core/orchestrator.js +79 -79
  10. package/src/core/registry.js +60 -60
  11. package/src/steps/add-plugin.js +148 -0
  12. package/src/steps/configure-user.js +181 -181
  13. package/src/steps/enable-plugins.js +97 -97
  14. package/src/steps/install-bmad.js +85 -85
  15. package/src/steps/install-mcp.js +70 -70
  16. package/src/steps/install-rules.js +69 -69
  17. package/src/steps/install-skills.js +56 -56
  18. package/src/utils/compare-versions.js +106 -0
  19. package/src/utils/fs.js +33 -33
  20. package/src/utils/manifest.js +101 -99
  21. package/src/utils/prompt.js +41 -41
  22. package/templates/mcp/claude-code/.mcp.json +40 -40
  23. package/templates/rules/README.md +103 -103
  24. package/templates/rules/common/agents.md +49 -49
  25. package/templates/rules/common/coding-style.md +48 -48
  26. package/templates/rules/common/development-workflow.md +37 -37
  27. package/templates/rules/common/git-workflow.md +24 -24
  28. package/templates/rules/common/hooks.md +30 -30
  29. package/templates/rules/common/patterns.md +31 -31
  30. package/templates/rules/common/performance.md +55 -55
  31. package/templates/rules/common/security.md +29 -29
  32. package/templates/rules/common/testing.md +29 -29
  33. package/templates/rules/golang/coding-style.md +32 -32
  34. package/templates/rules/golang/hooks.md +17 -17
  35. package/templates/rules/golang/patterns.md +45 -45
  36. package/templates/rules/golang/security.md +34 -34
  37. package/templates/rules/golang/testing.md +31 -31
  38. package/templates/rules/python/coding-style.md +42 -42
  39. package/templates/rules/python/hooks.md +19 -19
  40. package/templates/rules/python/patterns.md +39 -39
  41. package/templates/rules/python/security.md +30 -30
  42. package/templates/rules/python/testing.md +38 -38
  43. package/templates/rules/swift/coding-style.md +47 -47
  44. package/templates/rules/swift/hooks.md +20 -20
  45. package/templates/rules/swift/patterns.md +66 -66
  46. package/templates/rules/swift/security.md +33 -33
  47. package/templates/rules/swift/testing.md +45 -45
  48. package/templates/rules/typescript/coding-style.md +65 -65
  49. package/templates/rules/typescript/hooks.md +22 -22
  50. package/templates/rules/typescript/patterns.md +52 -52
  51. package/templates/rules/typescript/security.md +28 -28
  52. package/templates/rules/typescript/testing.md +18 -18
@@ -1,151 +1,192 @@
1
- /**
2
- * update command — re-run orchestration to update installed components.
3
- *
4
- * Default behavior: apply mode (re-run all steps).
5
- * --dry-run: show current manifest state only.
6
- * --no-apply: check-only, update lastUpdated timestamp.
7
- */
8
-
9
- import path from 'node:path'
10
- import fse from 'fs-extra'
11
- import { loadRegistry, resolvePlugins, resolveModelId } from '../core/registry.js'
12
- import { DEFAULT_API_URL } from '../core/config.js'
13
- import { orchestrate } from '../core/orchestrator.js'
14
- import { readManifest, writeManifest, isLegacyManifest, serializeSteps } from '../utils/manifest.js'
15
- import { createLogger } from '../utils/logger.js'
16
- import { enablePlugins } from '../steps/enable-plugins.js'
17
- import { installBmad } from '../steps/install-bmad.js'
18
- import { installRules } from '../steps/install-rules.js'
19
- import { installSkills } from '../steps/install-skills.js'
20
- import { installMcp } from '../steps/install-mcp.js'
21
- import { configureUser } from '../steps/configure-user.js'
22
-
23
- /**
24
- * @param {object} opts
25
- * @param {string} [opts.dir] - Target directory
26
- * @param {boolean} [opts.dryRun] - Preview only
27
- * @param {boolean} [opts.apply] - Apply updates (default: true)
28
- * @param {boolean} [opts.force] - Force overwrite
29
- * @param {boolean} [opts.debug] - Debug output
30
- * @param {object} [_deps] - Injectable dependencies
31
- * @returns {Promise<object>}
32
- */
33
- export async function runUpdate(opts = {}, _deps = {}) {
34
- const logger = _deps.logger || createLogger({ debug: opts.debug })
35
- const targetDir = path.resolve(opts.dir || process.cwd())
36
-
37
- const manifest = await readManifest(targetDir)
38
-
39
- if (isLegacyManifest(manifest)) {
40
- throw new Error(
41
- 'Legacy manifest detected (v1 module-based format). ' +
42
- 'Please run `cckit init` to reinstall with the new orchestration format.'
43
- )
44
- }
45
-
46
- logger.banner('cckit update')
47
-
48
- // Show current step status
49
- const steps = manifest.cckit?.steps || []
50
- for (const step of steps) {
51
- const status = step.skipped ? 'skipped' : step.success ? 'ok' : 'FAILED'
52
- logger.info(` ${step.stepId}: ${status}`)
53
- }
54
-
55
- if (opts.dryRun) {
56
- logger.info('\n (dry run - no changes made)')
57
- return { dryRun: true, steps }
58
- }
59
-
60
- if (opts.apply === false) {
61
- // Check-only: update timestamp
62
- manifest.cckit.lastUpdated = new Date().toISOString()
63
- await writeManifest(targetDir, manifest)
64
- logger.success('Check complete.')
65
- return { checked: true, steps }
66
- }
67
-
68
- // Apply mode: re-run orchestrator
69
- const registry = _deps.registry || await loadRegistry()
70
- const config = manifest.cckit?.config || {}
71
- const plugins = resolvePlugins(registry, { plugins: config.plugins || 'default' })
72
-
73
- // Resolve model for user settings
74
- const userSettings = registry.userSettings || {}
75
- const modelId = resolveModelId(userSettings, opts.model || config.model)
76
-
77
- const stepSpecs = [
78
- {
79
- id: 'configure-user',
80
- fn: _deps.configureUser || configureUser,
81
- opts: {
82
- apiUrl: opts.apiUrl || config.apiUrl || userSettings.apiUrl || DEFAULT_API_URL,
83
- apiKey: opts.apiKey,
84
- forceApiKey: opts.forceApiKey,
85
- modelId,
86
- modelEnvKeys: userSettings.modelEnvKeys || [],
87
- yes: true, // update mode is non-interactive by default
88
- skip: false,
89
- },
90
- },
91
- {
92
- id: 'enable-plugins',
93
- fn: _deps.enablePlugins || enablePlugins,
94
- opts: { targetDir, plugins, skip: false },
95
- },
96
- {
97
- id: 'install-bmad',
98
- fn: _deps.installBmad || installBmad,
99
- opts: {
100
- targetDir,
101
- bmadConfig: registry.bmad,
102
- // Pass saved config values only if they differ from BMAD defaults (Chinese)
103
- config: {
104
- communication_language: config.communication_language !== 'Chinese' ? config.communication_language : undefined,
105
- document_output_language: config.document_output_language !== 'Chinese' ? config.document_output_language : undefined,
106
- },
107
- skip: false,
108
- },
109
- },
110
- {
111
- id: 'install-rules',
112
- fn: _deps.installRules || installRules,
113
- opts: {
114
- targetDir,
115
- rulesConfig: registry.rules,
116
- skip: false,
117
- forceRefresh: true,
118
- },
119
- },
120
- {
121
- id: 'install-skills',
122
- fn: _deps.installSkills || installSkills,
123
- opts: { targetDir, skills: registry.skills || [], skip: false },
124
- },
125
- {
126
- id: 'install-mcp',
127
- fn: _deps.installMcp || installMcp,
128
- opts: {
129
- targetDir,
130
- mcpConfig: registry.mcp,
131
- skip: false,
132
- forceOverwrite: opts.force || false,
133
- },
134
- },
135
- ]
136
-
137
- const report = await orchestrate(stepSpecs, logger)
138
-
139
- // Update manifest
140
- manifest.cckit.steps = serializeSteps(report.steps)
141
- manifest.cckit.fileRegistry = {
142
- ...(manifest.cckit.fileRegistry || {}),
143
- ...report.fileRegistry,
144
- }
145
- manifest.cckit.lastUpdated = new Date().toISOString()
146
-
147
- await writeManifest(targetDir, manifest)
148
- logger.success('Update complete.')
149
-
150
- return { applied: true, report }
151
- }
1
+ /**
2
+ * update command — re-run orchestration to update installed components.
3
+ *
4
+ * Default behavior: apply mode (re-run all steps).
5
+ * --dry-run: show current manifest state only.
6
+ * --no-apply: check-only, update lastUpdated timestamp.
7
+ */
8
+
9
+ import path from 'node:path'
10
+ import chalk from 'chalk'
11
+ import { loadRegistry, resolvePlugins, resolveModelId } from '../core/registry.js'
12
+ import { DEFAULT_API_URL } from '../core/config.js'
13
+ import { orchestrate } from '../core/orchestrator.js'
14
+ import { readManifest, writeManifest, isLegacyManifest, serializeSteps } from '../utils/manifest.js'
15
+ import { compareVersions } from '../utils/compare-versions.js'
16
+ import { createLogger } from '../utils/logger.js'
17
+ import { enablePlugins } from '../steps/enable-plugins.js'
18
+ import { installBmad } from '../steps/install-bmad.js'
19
+ import { installRules } from '../steps/install-rules.js'
20
+ import { installSkills } from '../steps/install-skills.js'
21
+ import { installMcp } from '../steps/install-mcp.js'
22
+ import { configureUser } from '../steps/configure-user.js'
23
+
24
+ /**
25
+ * @param {object} opts
26
+ * @param {string} [opts.dir] - Target directory
27
+ * @param {boolean} [opts.dryRun] - Preview only
28
+ * @param {boolean} [opts.apply] - Apply updates (default: true)
29
+ * @param {boolean} [opts.force] - Force overwrite
30
+ * @param {boolean} [opts.debug] - Debug output
31
+ * @param {object} [_deps] - Injectable dependencies
32
+ * @returns {Promise<object>}
33
+ */
34
+ export async function runUpdate(opts = {}, _deps = {}) {
35
+ const logger = _deps.logger || createLogger({ debug: opts.debug })
36
+ const targetDir = path.resolve(opts.dir || process.cwd())
37
+ const registry = _deps.registry || await loadRegistry()
38
+
39
+ const manifest = await readManifest(targetDir)
40
+
41
+ if (isLegacyManifest(manifest)) {
42
+ throw new Error(
43
+ 'Legacy manifest detected (v1 module-based format). ' +
44
+ 'Please run `cckit init` to reinstall with the new orchestration format.'
45
+ )
46
+ }
47
+
48
+ logger.banner('cckit update')
49
+
50
+ // Compare versions
51
+ const { needsUpdate, components } = compareVersions(manifest, registry)
52
+
53
+ // Show current step status with version info
54
+ const steps = manifest.cckit?.steps || []
55
+ const installedVersions = manifest.cckit?.config?.versions || {}
56
+
57
+ logger.info('')
58
+ logger.info(chalk.bold('Component Versions:'))
59
+ logger.info('')
60
+
61
+ for (const [stepId, info] of Object.entries(components)) {
62
+ const current = installedVersions[info.versionKey] || 'none'
63
+ const latest = info.latest
64
+ const needsUpdate = current !== latest
65
+
66
+ const status = needsUpdate
67
+ ? chalk.yellow(`update available (${current} -> ${latest})`)
68
+ : chalk.green('up to date')
69
+
70
+ logger.info(` ${stepId}: ${status}`)
71
+ }
72
+
73
+ if (needsUpdate) {
74
+ logger.info('')
75
+ logger.info(chalk.yellow(' Some components have updates available.'))
76
+ logger.info(chalk.gray(' Run "cckit update" to apply updates.'))
77
+ }
78
+
79
+ if (opts.dryRun) {
80
+ logger.info('\n (dry run - no changes made)')
81
+ return { dryRun: true, steps, needsUpdate, components }
82
+ }
83
+
84
+ if (opts.apply === false) {
85
+ // Check-only: update timestamp
86
+ manifest.cckit.lastUpdated = new Date().toISOString()
87
+ await writeManifest(targetDir, manifest)
88
+ logger.success('Check complete.')
89
+ return { checked: true, steps, needsUpdate, components }
90
+ }
91
+
92
+ // Show step status
93
+ logger.info('')
94
+ logger.info(chalk.bold('Step Status:'))
95
+ for (const step of steps) {
96
+ const status = step.skipped ? 'skipped' : step.success ? 'ok' : 'FAILED'
97
+ logger.info(` ${step.stepId}: ${status}`)
98
+ }
99
+
100
+ if (!needsUpdate) {
101
+ logger.info('')
102
+ logger.success('All components are up to date. No update needed.')
103
+ return { applied: false, reason: 'already_up_to_date', needsUpdate: false }
104
+ }
105
+
106
+ // Apply mode: re-run orchestrator
107
+ const config = manifest.cckit?.config || {}
108
+ const plugins = resolvePlugins(registry, { plugins: config.plugins || 'default' })
109
+
110
+ // Resolve model for user settings
111
+ const userSettings = registry.userSettings || {}
112
+ const modelId = resolveModelId(userSettings, opts.model || config.model)
113
+
114
+ const stepSpecs = [
115
+ {
116
+ id: 'configure-user',
117
+ fn: _deps.configureUser || configureUser,
118
+ opts: {
119
+ apiUrl: opts.apiUrl || config.apiUrl || userSettings.apiUrl || DEFAULT_API_URL,
120
+ apiKey: opts.apiKey,
121
+ forceApiKey: opts.forceApiKey,
122
+ modelId,
123
+ modelEnvKeys: userSettings.modelEnvKeys || [],
124
+ yes: true, // update mode is non-interactive by default
125
+ skip: false,
126
+ },
127
+ },
128
+ {
129
+ id: 'enable-plugins',
130
+ fn: _deps.enablePlugins || enablePlugins,
131
+ opts: { targetDir, plugins, skip: false },
132
+ },
133
+ {
134
+ id: 'install-bmad',
135
+ fn: _deps.installBmad || installBmad,
136
+ opts: {
137
+ targetDir,
138
+ bmadConfig: registry.bmad,
139
+ // Pass saved config values only if they differ from BMAD defaults (Chinese)
140
+ config: {
141
+ communication_language: config.communication_language !== 'Chinese' ? config.communication_language : undefined,
142
+ document_output_language: config.document_output_language !== 'Chinese' ? config.document_output_language : undefined,
143
+ },
144
+ skip: false,
145
+ },
146
+ },
147
+ {
148
+ id: 'install-rules',
149
+ fn: _deps.installRules || installRules,
150
+ opts: {
151
+ targetDir,
152
+ rulesConfig: registry.rules,
153
+ skip: false,
154
+ forceRefresh: true,
155
+ },
156
+ },
157
+ {
158
+ id: 'install-skills',
159
+ fn: _deps.installSkills || installSkills,
160
+ opts: { targetDir, skills: registry.skills || [], skip: false },
161
+ },
162
+ {
163
+ id: 'install-mcp',
164
+ fn: _deps.installMcp || installMcp,
165
+ opts: {
166
+ targetDir,
167
+ mcpConfig: registry.mcp,
168
+ skip: false,
169
+ forceOverwrite: opts.force || false,
170
+ },
171
+ },
172
+ ]
173
+
174
+ const report = await orchestrate(stepSpecs, logger)
175
+
176
+ // Update manifest with new versions
177
+ manifest.cckit.config.versions = {
178
+ ...(manifest.cckit.config.versions || {}),
179
+ ...registry.versions,
180
+ }
181
+ manifest.cckit.steps = serializeSteps(report.steps)
182
+ manifest.cckit.fileRegistry = {
183
+ ...(manifest.cckit.fileRegistry || {}),
184
+ ...report.fileRegistry,
185
+ }
186
+ manifest.cckit.lastUpdated = new Date().toISOString()
187
+
188
+ await writeManifest(targetDir, manifest)
189
+ logger.success('Update complete.')
190
+
191
+ return { applied: true, report }
192
+ }
@@ -1,74 +1,82 @@
1
- const LANG_MAP = {
2
- ts: 'typescript', typescript: 'typescript',
3
- py: 'python', python: 'python',
4
- go: 'golang', golang: 'golang'
5
- }
6
-
7
- export const VERSION = '0.5.0'
8
-
9
- export const DEFAULT_API_URL = 'https://gateway.cregis.ai'
10
-
11
- export const DEFAULT_CONFIG = {
12
- user_name: 'User',
13
- communication_language: 'Chinese',
14
- document_output_language: 'Chinese',
15
- languages: ['typescript', 'python', 'golang'],
16
- plugins: 'default',
17
- excludeGroups: []
18
- }
19
-
20
- /**
21
- * Merge CLI flags into a config object, falling back to DEFAULT_CONFIG.
22
- *
23
- * Supported flags:
24
- * userName - Override user_name
25
- * communicationLanguage - Override communication_language
26
- * docLanguage - Override document_output_language
27
- * lang - Comma-separated language aliases (ts,py,go)
28
- * bmad - Set to false to add "bmad" to excludeGroups
29
- * ecc - Set to false to add "ecc" to excludeGroups
30
- * mcp - Set to false to add "mcp" to excludeGroups
31
- * plugins - "default", "none", or comma-separated plugin IDs
32
- * skills - Set to false to skip skill installation
33
- *
34
- * @param {object} [flags={}] - CLI flags parsed by commander
35
- * @returns {object} Merged config
36
- */
37
- export function mergeConfig(flags = {}) {
38
- const config = { ...DEFAULT_CONFIG, excludeGroups: [] }
39
-
40
- if (flags.userName) config.user_name = flags.userName
41
- if (flags.communicationLanguage) config.communication_language = flags.communicationLanguage
42
- if (flags.docLanguage) config.document_output_language = flags.docLanguage
43
-
44
- if (flags.lang) {
45
- config.languages = flags.lang
46
- .split(',')
47
- .map(l => LANG_MAP[l.trim().toLowerCase()])
48
- .filter(Boolean)
49
- }
50
-
51
- if (flags.bmad === false) config.excludeGroups.push('bmad')
52
- if (flags.ecc === false) config.excludeGroups.push('ecc')
53
- if (flags.mcp === false) config.excludeGroups.push('mcp')
54
-
55
- if (flags.plugins === false) {
56
- config.plugins = 'none'
57
- } else if (typeof flags.plugins === 'string') {
58
- config.plugins = flags.plugins === 'default' || flags.plugins === 'none'
59
- ? flags.plugins
60
- : flags.plugins.split(',').map(p => p.trim())
61
- }
62
-
63
- if (flags.skills === false) {
64
- config.skipSkills = true
65
- }
66
-
67
- // User-level settings
68
- if (flags.apiUrl) config.apiUrl = flags.apiUrl
69
- if (flags.apiKey) config.apiKey = flags.apiKey
70
- if (flags.forceApiKey) config.forceApiKey = true
71
- if (flags.model) config.model = flags.model
72
-
73
- return config
74
- }
1
+ import { readFileSync } from 'node:fs'
2
+ import { fileURLToPath } from 'node:url'
3
+ import { dirname, resolve } from 'node:path'
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url))
6
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, '../../package.json'), 'utf-8'))
7
+
8
+ const LANG_MAP = {
9
+ ts: 'typescript', typescript: 'typescript',
10
+ py: 'python', python: 'python',
11
+ go: 'golang', golang: 'golang'
12
+ }
13
+
14
+ export const VERSION = pkg.version
15
+
16
+ export const DEFAULT_API_URL = 'https://gateway.cregis.ai'
17
+
18
+ export const DEFAULT_CONFIG = {
19
+ user_name: 'User',
20
+ communication_language: 'Chinese',
21
+ document_output_language: 'Chinese',
22
+ languages: ['typescript', 'python', 'golang'],
23
+ plugins: 'default',
24
+ cliPlugins: true, // Use Claude CLI for project-scoped plugins
25
+ excludeGroups: []
26
+ }
27
+
28
+ /**
29
+ * Merge CLI flags into a config object, falling back to DEFAULT_CONFIG.
30
+ *
31
+ * Supported flags:
32
+ * userName - Override user_name
33
+ * communicationLanguage - Override communication_language
34
+ * docLanguage - Override document_output_language
35
+ * lang - Comma-separated language aliases (ts,py,go)
36
+ * bmad - Set to false to add "bmad" to excludeGroups
37
+ * ecc - Set to false to add "ecc" to excludeGroups
38
+ * mcp - Set to false to add "mcp" to excludeGroups
39
+ * plugins - "default", "none", or comma-separated plugin IDs
40
+ * skills - Set to false to skip skill installation
41
+ *
42
+ * @param {object} [flags={}] - CLI flags parsed by commander
43
+ * @returns {object} Merged config
44
+ */
45
+ export function mergeConfig(flags = {}) {
46
+ const config = { ...DEFAULT_CONFIG, excludeGroups: [] }
47
+
48
+ if (flags.userName) config.user_name = flags.userName
49
+ if (flags.communicationLanguage) config.communication_language = flags.communicationLanguage
50
+ if (flags.docLanguage) config.document_output_language = flags.docLanguage
51
+
52
+ if (flags.lang) {
53
+ config.languages = flags.lang
54
+ .split(',')
55
+ .map(l => LANG_MAP[l.trim().toLowerCase()])
56
+ .filter(Boolean)
57
+ }
58
+
59
+ if (flags.bmad === false) config.excludeGroups.push('bmad')
60
+ if (flags.ecc === false) config.excludeGroups.push('ecc')
61
+ if (flags.mcp === false) config.excludeGroups.push('mcp')
62
+
63
+ if (flags.plugins === false) {
64
+ config.plugins = 'none'
65
+ } else if (typeof flags.plugins === 'string') {
66
+ config.plugins = flags.plugins === 'default' || flags.plugins === 'none'
67
+ ? flags.plugins
68
+ : flags.plugins.split(',').map(p => p.trim())
69
+ }
70
+
71
+ if (flags.skills === false) {
72
+ config.skipSkills = true
73
+ }
74
+
75
+ // User-level settings
76
+ if (flags.apiUrl) config.apiUrl = flags.apiUrl
77
+ if (flags.apiKey) config.apiKey = flags.apiKey
78
+ if (flags.forceApiKey) config.forceApiKey = true
79
+ if (flags.model) config.model = flags.model
80
+
81
+ return config
82
+ }