@cregis-dev/cckit 0.6.3 → 0.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cregis-dev/cckit",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "description": "Enterprise-grade Claude Code configuration toolkit — orchestrates external tools to set up unified rules, skills, MCP and methodology for teams",
5
5
  "type": "module",
6
6
  "bin": {
package/registry.json CHANGED
@@ -46,6 +46,18 @@
46
46
  "marketplace": "claude-plugins-official",
47
47
  "default": true,
48
48
  "description": "Web scraping, search, and skill generation using Firecrawl"
49
+ },
50
+ "typescript-lsp": {
51
+ "name": "TypeScript LSP",
52
+ "marketplace": "claude-plugins-official",
53
+ "default": true,
54
+ "description": "TypeScript language server protocol integration for enhanced TypeScript development"
55
+ },
56
+ "pr-review-toolkit": {
57
+ "name": "PR Review Toolkit",
58
+ "marketplace": "claude-plugins-official",
59
+ "default": true,
60
+ "description": "Comprehensive PR review using specialized agents"
49
61
  }
50
62
  },
51
63
  "rules": {
@@ -69,7 +81,7 @@
69
81
  "id": "skill-vetter",
70
82
  "repo": "https://github.com/useai-pro/openclaw-skills-security",
71
83
  "skill": "skill-vetter",
72
- "installCommand": "npx skills add https://github.com/useai-pro/openclaw-skills-security@skill-vetter -y -a claude-code"
84
+ "installCommand": "npx skills add https://github.com/useai-pro/openclaw-skills-security --skill skill-vetter -y -a claude-code"
73
85
  }
74
86
  ],
75
87
  "bmad": {
@@ -71,7 +71,8 @@ export async function runInit(opts = {}, _deps = {}) {
71
71
  apiUrl: config.apiUrl || userSettings.apiUrl || DEFAULT_API_URL,
72
72
  apiKey: config.apiKey,
73
73
  forceApiKey: config.forceApiKey,
74
- modelId,
74
+ model: config.model, // CLI alias (e.g. 'kimi'), used for prompting
75
+ modelId, // Resolved ID (e.g. 'Kimi-K2.5'), used for env vars
75
76
  modelEnvKeys: userSettings.modelEnvKeys || [],
76
77
  yes: opts.yes,
77
78
  skip: false,
@@ -30,6 +30,7 @@ export async function configureUser(opts, logger, _deps = {}) {
30
30
 
31
31
  const { askFn = askQuestion } = _deps
32
32
  const settingsPath = _deps.settingsPath || path.join(os.homedir(), '.claude', 'settings.json')
33
+ const claudeJsonPath = _deps.claudeJsonPath || path.join(os.homedir(), '.claude.json')
33
34
 
34
35
  // Read existing user settings
35
36
  let existing = {}
@@ -47,25 +48,24 @@ export async function configureUser(opts, logger, _deps = {}) {
47
48
 
48
49
  const existingEnv = existing.env || {}
49
50
 
50
- // 1. API URL — prompt for confirmation if not provided via CLI
51
+ // 1. API URL — always prompt for confirmation when not in --yes mode
51
52
  let apiUrl = opts.apiUrl
52
- if (!opts.yes && !opts.apiUrl) {
53
+ if (!opts.yes) {
53
54
  const input = await askFn(' Enter API URL (default: ' + opts.apiUrl + '): ')
54
55
  if (input && input.trim()) {
55
56
  apiUrl = input.trim()
56
57
  }
57
58
  }
58
59
 
59
- // 2. API Key — resolve from CLI flag, readline, or existing
60
+ // 2. API Key — prompt when not in --yes mode
60
61
  let apiKey = existingEnv.ANTHROPIC_AUTH_TOKEN || ''
61
62
  const hasExistingKey = Boolean(apiKey)
62
63
 
63
- if (opts.apiKey) {
64
- // CLI flag provided use it (force or new)
65
- apiKey = opts.apiKey
66
- } else if (!hasExistingKey || opts.forceApiKey) {
67
- // No existing key, or force update — prompt via readline
68
- if (!opts.yes) {
64
+ if (!opts.yes) {
65
+ // Use CLI value if provided, otherwise prompt
66
+ if (opts.apiKey) {
67
+ apiKey = opts.apiKey
68
+ } else {
69
69
  const prompt = hasExistingKey
70
70
  ? ' API Key already exists. Enter new key to replace (empty to keep): '
71
71
  : ' Enter your API Key (empty to skip): '
@@ -76,12 +76,15 @@ export async function configureUser(opts, logger, _deps = {}) {
76
76
  logger.warn('No API Key provided. You can set it later with `cckit install --api-key <key>`')
77
77
  }
78
78
  }
79
- // --yes mode without --api-key: skip prompt, keep existing
79
+ } else if (opts.apiKey) {
80
+ // --yes mode: use CLI flag if provided
81
+ apiKey = opts.apiKey
80
82
  }
83
+ // --yes mode without --api-key: keep existing
81
84
 
82
- // 3. Model — prompt for confirmation
85
+ // 3. Model — always prompt for confirmation when not in --yes mode
83
86
  let modelId = opts.modelId
84
- if (!opts.yes && !opts.model) {
87
+ if (!opts.yes) {
85
88
  const input = await askFn(' Enter model (default: ' + opts.modelId + '): ')
86
89
  if (input && input.trim()) {
87
90
  modelId = input.trim()
@@ -94,7 +97,7 @@ export async function configureUser(opts, logger, _deps = {}) {
94
97
  modelEnvEntries[key] = modelId
95
98
  }
96
99
 
97
- // 5. Merge and write
100
+ // 5. Merge and write settings.json
98
101
  const merged = {
99
102
  ...existing,
100
103
  env: {
@@ -108,6 +111,11 @@ export async function configureUser(opts, logger, _deps = {}) {
108
111
  await fse.ensureDir(path.dirname(settingsPath))
109
112
  await fse.writeFile(settingsPath, JSON.stringify(merged, null, 2) + '\n', 'utf8')
110
113
 
114
+ // 6. Check and prompt for hasCompletedOnboarding in ~/.claude.json
115
+ if (!opts.yes) {
116
+ await checkAndPromptOnboarding(claudeJsonPath, logger, askFn)
117
+ }
118
+
111
119
  const maskedKey = apiKey ? `${apiKey.slice(0, 4)}...${apiKey.slice(-4)}` : '(not set)'
112
120
 
113
121
  logger.info(` API URL: ${apiUrl}`)
@@ -128,3 +136,46 @@ export async function configureUser(opts, logger, _deps = {}) {
128
136
  },
129
137
  }
130
138
  }
139
+
140
+ /**
141
+ * Check if ~/.claude.json has hasCompletedOnboarding and prompt if missing.
142
+ *
143
+ * @param {string} claudeJsonPath - Path to ~/.claude.json
144
+ * @param {object} logger
145
+ * @param {function} askFn
146
+ * @returns {Promise<void>}
147
+ */
148
+ async function checkAndPromptOnboarding(claudeJsonPath, logger, askFn) {
149
+ let claudeJson = {}
150
+ let fileExisted = false
151
+
152
+ try {
153
+ const raw = await fse.readFile(claudeJsonPath, 'utf8')
154
+ claudeJson = JSON.parse(raw)
155
+ fileExisted = true
156
+ } catch (err) {
157
+ if (err.code !== 'ENOENT') {
158
+ logger.warn(`Failed to read ${claudeJsonPath}: ${err.message}`)
159
+ return
160
+ }
161
+ // File doesn't exist - will create new
162
+ }
163
+
164
+ // Check if hasCompletedOnboarding already exists
165
+ if ('hasCompletedOnboarding' in claudeJson) {
166
+ return
167
+ }
168
+
169
+ // Prompt user
170
+ const input = await askFn(' Add hasCompletedOnboarding: true to ~/.claude.json? (Y/n): ')
171
+ const answer = (input || '').trim().toLowerCase()
172
+
173
+ // Default to yes if empty input
174
+ if (answer === '' || answer === 'y' || answer === 'yes') {
175
+ claudeJson.hasCompletedOnboarding = true
176
+ await fse.writeFile(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + '\n', 'utf8')
177
+ logger.info(` Added hasCompletedOnboarding: true to ~/.claude.json`)
178
+ } else {
179
+ logger.info(` Skipped adding hasCompletedOnboarding`)
180
+ }
181
+ }