@miphamai/cli 0.11.0 → 0.13.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 +1 -1
- package/src/agent/background-registry.ts +11 -0
- package/src/agent-view/agent-view-manager.ts +10 -0
- package/src/artifacts/server.ts +39 -0
- package/src/config/defaults.ts +35 -1
- package/src/config/loader.ts +122 -2
- package/src/core/credential-masker.ts +203 -0
- package/src/core/engine.ts +56 -1
- package/src/core/hooks.ts +23 -0
- package/src/core/inference-hook.ts +224 -0
- package/src/core/metrics.ts +364 -0
- package/src/core/permission.ts +62 -8
- package/src/index.tsx +16 -1
- package/src/plugin/plugin-manager.ts +39 -2
- package/src/shared/types.ts +100 -0
- package/src/tools/exec/bash.ts +29 -3
- package/src/tools/file/read.ts +30 -1
- package/src/ui/app.tsx +6 -1
- package/src/ui/chat.tsx +50 -17
- package/src/ui/commands.ts +348 -4
- package/dist/mipham +0 -0
package/src/ui/commands.ts
CHANGED
|
@@ -3052,6 +3052,223 @@ Permission level is controlled by /config permission <level>.`,
|
|
|
3052
3052
|
// Security / Audit — security review checklist
|
|
3053
3053
|
// ═══════════════════════════════════════════════════════════════
|
|
3054
3054
|
|
|
3055
|
+
const promptAuditCmd: CommandHandler = async () => {
|
|
3056
|
+
const { existsSync, readFileSync, readdirSync, statSync } = await import('node:fs')
|
|
3057
|
+
const { join, extname, basename } = await import('node:path')
|
|
3058
|
+
const cwd = process.cwd()
|
|
3059
|
+
|
|
3060
|
+
// Patterns that suggest prompts written for older/less-capable models
|
|
3061
|
+
const AUDIT_RULES: Array<{
|
|
3062
|
+
id: string
|
|
3063
|
+
pattern: RegExp
|
|
3064
|
+
severity: 'low' | 'medium' | 'high'
|
|
3065
|
+
message: string
|
|
3066
|
+
suggestion: string
|
|
3067
|
+
}> = [
|
|
3068
|
+
{
|
|
3069
|
+
id: 'over-explaining',
|
|
3070
|
+
pattern:
|
|
3071
|
+
/you are (a|an) (helpful |friendly |knowledgeable )?(AI |language model |assistant)/i,
|
|
3072
|
+
severity: 'low',
|
|
3073
|
+
message: 'Self-identification preamble ("You are a...")',
|
|
3074
|
+
suggestion: "Modern models don't need role preamble. Remove or shorten to 1 line.",
|
|
3075
|
+
},
|
|
3076
|
+
{
|
|
3077
|
+
id: 'step-by-step',
|
|
3078
|
+
pattern: /(think|reason|work) (step[ -]?by[ -]?step|through this|carefully about this)/i,
|
|
3079
|
+
severity: 'low',
|
|
3080
|
+
message: 'Step-by-step reasoning prompt',
|
|
3081
|
+
suggestion: 'Reasoning models handle this natively. Remove for token savings.',
|
|
3082
|
+
},
|
|
3083
|
+
{
|
|
3084
|
+
id: 'do-not-list',
|
|
3085
|
+
pattern:
|
|
3086
|
+
/(do not|never|you must not|don't|under no circumstances).*\n.*(do not|never|you must not|don't)/i,
|
|
3087
|
+
severity: 'medium',
|
|
3088
|
+
message: 'Multiple "do not" constraints',
|
|
3089
|
+
suggestion: 'Modern models need fewer prohibitions. Consolidate to 1-2 key constraints.',
|
|
3090
|
+
},
|
|
3091
|
+
{
|
|
3092
|
+
id: 'token-waste',
|
|
3093
|
+
pattern:
|
|
3094
|
+
/(remember|keep in mind|it is important to note|please note that|i want to emphasize)/i,
|
|
3095
|
+
severity: 'low',
|
|
3096
|
+
message: 'Filler emphasis phrases ("remember", "please note")',
|
|
3097
|
+
suggestion: 'Remove filler. State the instruction directly.',
|
|
3098
|
+
},
|
|
3099
|
+
{
|
|
3100
|
+
id: 'format-over-spec',
|
|
3101
|
+
pattern: /(you must (always |only )?respond (in|with|using) (JSON|XML|YAML|markdown|HTML))/i,
|
|
3102
|
+
severity: 'low',
|
|
3103
|
+
message: 'Over-specified output format',
|
|
3104
|
+
suggestion: 'Modern models follow format instructions with fewer words. Shorten.',
|
|
3105
|
+
},
|
|
3106
|
+
{
|
|
3107
|
+
id: 'example-overload',
|
|
3108
|
+
pattern: /((?:example|for instance|e\.g\.,).*\n){3,}/i,
|
|
3109
|
+
severity: 'low',
|
|
3110
|
+
message: 'Three or more examples in sequence',
|
|
3111
|
+
suggestion: '1-2 examples suffice for modern models. Remove redundant ones.',
|
|
3112
|
+
},
|
|
3113
|
+
{
|
|
3114
|
+
id: 'old-model-ref',
|
|
3115
|
+
pattern: /(GPT-3|GPT-3\.5|Claude\s*[12][^3]|text-davinci|command-r|llama\s*2)/i,
|
|
3116
|
+
severity: 'high',
|
|
3117
|
+
message: 'Reference to older model',
|
|
3118
|
+
suggestion: 'Update model references to current generation (Sonnet 5, Opus 5, GPT-5, etc.).',
|
|
3119
|
+
},
|
|
3120
|
+
{
|
|
3121
|
+
id: 'long-preamble',
|
|
3122
|
+
pattern: /^.{200,}$/m,
|
|
3123
|
+
severity: 'medium',
|
|
3124
|
+
message: 'Very long single-line instructions (200+ chars)',
|
|
3125
|
+
suggestion: 'Break into bullet points. Modern models parse structured prompts better.',
|
|
3126
|
+
},
|
|
3127
|
+
{
|
|
3128
|
+
id: 'verbose-constraint',
|
|
3129
|
+
pattern:
|
|
3130
|
+
/you (must|should|shall) (always |only |never )?(ensure|guarantee|verify|validate|confirm|cross-check|double-check)/i,
|
|
3131
|
+
severity: 'medium',
|
|
3132
|
+
message: 'Overly verbose constraint language',
|
|
3133
|
+
suggestion: 'Replace "you must ensure that" with imperative: "Ensure".',
|
|
3134
|
+
},
|
|
3135
|
+
]
|
|
3136
|
+
|
|
3137
|
+
// Files to scan
|
|
3138
|
+
const scanDirs = [
|
|
3139
|
+
join(cwd, '.mipham', 'skills'),
|
|
3140
|
+
join(cwd, '.mipham', 'rules'),
|
|
3141
|
+
join(cwd, '.claude'),
|
|
3142
|
+
]
|
|
3143
|
+
const skillFiles: string[] = []
|
|
3144
|
+
// Also check standard project files
|
|
3145
|
+
const projectFiles = [join(cwd, 'CLAUDE.md'), join(cwd, 'MIPHAM.md'), join(cwd, 'PRODUCT.md')]
|
|
3146
|
+
|
|
3147
|
+
// Collect skill/rules files
|
|
3148
|
+
for (const dir of scanDirs) {
|
|
3149
|
+
try {
|
|
3150
|
+
if (!existsSync(dir)) continue
|
|
3151
|
+
const walk = (d: string) => {
|
|
3152
|
+
const entries = readdirSync(d)
|
|
3153
|
+
for (const e of entries) {
|
|
3154
|
+
const fp = join(d, e)
|
|
3155
|
+
const st = statSync(fp)
|
|
3156
|
+
if (st.isDirectory()) {
|
|
3157
|
+
walk(fp)
|
|
3158
|
+
continue
|
|
3159
|
+
}
|
|
3160
|
+
if (['.md', '.SKILL.md', '.mipham-skill.md', '.txt'].some((ext) => fp.endsWith(ext))) {
|
|
3161
|
+
skillFiles.push(fp)
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
walk(dir)
|
|
3166
|
+
} catch {
|
|
3167
|
+
/* skip */
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
|
|
3171
|
+
const allFiles = [...new Set([...projectFiles.filter((f) => existsSync(f)), ...skillFiles])]
|
|
3172
|
+
|
|
3173
|
+
if (allFiles.length === 0) {
|
|
3174
|
+
return {
|
|
3175
|
+
content: [
|
|
3176
|
+
'🔍 Prompt Audit',
|
|
3177
|
+
'',
|
|
3178
|
+
'No prompt files found to audit.',
|
|
3179
|
+
'Place skills in .mipham/skills/ and rules in .mipham/rules/.',
|
|
3180
|
+
].join('\n'),
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
|
|
3184
|
+
// Scan each file
|
|
3185
|
+
const results: Array<{
|
|
3186
|
+
file: string
|
|
3187
|
+
line: number
|
|
3188
|
+
ruleId: string
|
|
3189
|
+
severity: string
|
|
3190
|
+
message: string
|
|
3191
|
+
suggestion: string
|
|
3192
|
+
}> = []
|
|
3193
|
+
|
|
3194
|
+
for (const fp of allFiles) {
|
|
3195
|
+
try {
|
|
3196
|
+
const content = readFileSync(fp, 'utf-8')
|
|
3197
|
+
const lines = content.split('\n')
|
|
3198
|
+
for (const rule of AUDIT_RULES) {
|
|
3199
|
+
// Multi-line pattern: check full content
|
|
3200
|
+
if (rule.id === 'do-not-list' || rule.id === 'example-overload') {
|
|
3201
|
+
if (rule.pattern.test(content)) {
|
|
3202
|
+
// Find approx line
|
|
3203
|
+
const match = rule.pattern.exec(content)
|
|
3204
|
+
const idx = match ? content.slice(0, match.index).split('\n').length : 1
|
|
3205
|
+
results.push({
|
|
3206
|
+
file: fp.replace(cwd + '/', ''),
|
|
3207
|
+
line: idx,
|
|
3208
|
+
ruleId: rule.id,
|
|
3209
|
+
severity: rule.severity,
|
|
3210
|
+
message: rule.message,
|
|
3211
|
+
suggestion: rule.suggestion,
|
|
3212
|
+
})
|
|
3213
|
+
}
|
|
3214
|
+
continue
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3217
|
+
// Line-by-line patterns
|
|
3218
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3219
|
+
const line = lines[i]!
|
|
3220
|
+
if (rule.pattern.test(line)) {
|
|
3221
|
+
results.push({
|
|
3222
|
+
file: fp.replace(cwd + '/', ''),
|
|
3223
|
+
line: i + 1,
|
|
3224
|
+
ruleId: rule.id,
|
|
3225
|
+
severity: rule.severity,
|
|
3226
|
+
message: rule.message,
|
|
3227
|
+
suggestion: rule.suggestion,
|
|
3228
|
+
})
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
} catch {
|
|
3233
|
+
/* skip unreadable files */
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
// Format output
|
|
3238
|
+
const severityIcon: Record<string, string> = { high: '🔴', medium: '🟡', low: '🟢' }
|
|
3239
|
+
const grouped: Record<string, typeof results> = {}
|
|
3240
|
+
for (const r of results) {
|
|
3241
|
+
const key = r.file
|
|
3242
|
+
if (!grouped[key]) grouped[key] = []
|
|
3243
|
+
grouped[key]!.push(r)
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3246
|
+
const output: string[] = [
|
|
3247
|
+
`🔍 Prompt Audit — ${allFiles.length} file(s) scanned, ${results.length} finding(s)`,
|
|
3248
|
+
'',
|
|
3249
|
+
]
|
|
3250
|
+
|
|
3251
|
+
if (results.length === 0) {
|
|
3252
|
+
output.push('✅ All prompts look optimized for modern models. No issues found.')
|
|
3253
|
+
} else {
|
|
3254
|
+
for (const [file, items] of Object.entries(grouped)) {
|
|
3255
|
+
output.push(`📄 ${file} (${items!.length} finding${items!.length > 1 ? 's' : ''})`)
|
|
3256
|
+
for (const item of items!) {
|
|
3257
|
+
output.push(
|
|
3258
|
+
` ${severityIcon[item.severity] || '⚪'} L${item.line}: [${item.ruleId}] ${item.message}`,
|
|
3259
|
+
)
|
|
3260
|
+
output.push(` → ${item.suggestion}`)
|
|
3261
|
+
}
|
|
3262
|
+
output.push('')
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
|
|
3266
|
+
output.push('─'.repeat(60))
|
|
3267
|
+
output.push('Scanned: ' + allFiles.map((f) => basename(f)).join(', '))
|
|
3268
|
+
|
|
3269
|
+
return { content: output.join('\n') }
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3055
3272
|
const securityCmd: CommandHandler = async () => {
|
|
3056
3273
|
const findings: string[] = []
|
|
3057
3274
|
const ok: string[] = []
|
|
@@ -3272,7 +3489,8 @@ const ideCmd: CommandHandler = async (_ctx) => {
|
|
|
3272
3489
|
// ═══════════════════════════════════════════════════════════════
|
|
3273
3490
|
|
|
3274
3491
|
const terminalSetupCmd: CommandHandler = async () => {
|
|
3275
|
-
const { writeFileSync, appendFileSync, existsSync, mkdirSync } =
|
|
3492
|
+
const { writeFileSync, appendFileSync, existsSync, mkdirSync, readFileSync } =
|
|
3493
|
+
await import('node:fs')
|
|
3276
3494
|
const { join } = await import('node:path')
|
|
3277
3495
|
const { homedir } = await import('node:os')
|
|
3278
3496
|
|
|
@@ -3313,9 +3531,7 @@ const terminalSetupCmd: CommandHandler = async () => {
|
|
|
3313
3531
|
const sourceLine = `\n# Mipham Code shell integration\n[ -f ~/.mipham/shell-setup.sh ] && source ~/.mipham/shell-setup.sh\n`
|
|
3314
3532
|
|
|
3315
3533
|
try {
|
|
3316
|
-
const existing = existsSync(profilePath)
|
|
3317
|
-
? require('node:fs').readFileSync(profilePath, 'utf-8')
|
|
3318
|
-
: ''
|
|
3534
|
+
const existing = existsSync(profilePath) ? readFileSync(profilePath, 'utf-8') : ''
|
|
3319
3535
|
if (existing.includes('shell-setup.sh')) {
|
|
3320
3536
|
lines.push(` ⏭ ${profileName} already has Mipham Code integration`)
|
|
3321
3537
|
} else {
|
|
@@ -3692,6 +3908,128 @@ Run \`mipham agents\` for the interactive dashboard.`,
|
|
|
3692
3908
|
// Artifacts
|
|
3693
3909
|
// ═══════════════════════════════════════════════════════════════
|
|
3694
3910
|
|
|
3911
|
+
const forkCmd: CommandHandler = async (ctx, args) => {
|
|
3912
|
+
const prompt = args.join(' ')
|
|
3913
|
+
if (!prompt.trim()) {
|
|
3914
|
+
return {
|
|
3915
|
+
content: [
|
|
3916
|
+
'Usage: /fork <task description>',
|
|
3917
|
+
'',
|
|
3918
|
+
'Fork a task into an isolated worktree with auto commit/push.',
|
|
3919
|
+
'',
|
|
3920
|
+
'Workflow:',
|
|
3921
|
+
' 1. Creates a new git worktree on branch worktree/<slug>',
|
|
3922
|
+
' 2. Spawns a background agent to work on the task',
|
|
3923
|
+
' 3. Auto-commits changes with Co-Authored-By on completion',
|
|
3924
|
+
' 4. Auto-pushes to origin',
|
|
3925
|
+
' 5. Reports branch and worktree path in the result',
|
|
3926
|
+
'',
|
|
3927
|
+
'Examples:',
|
|
3928
|
+
' /fork Refactor the auth module',
|
|
3929
|
+
' /fork Add input validation to all API endpoints',
|
|
3930
|
+
].join('\n'),
|
|
3931
|
+
}
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3934
|
+
const { execSync } = await import('node:child_process')
|
|
3935
|
+
const { join } = await import('node:path')
|
|
3936
|
+
|
|
3937
|
+
try {
|
|
3938
|
+
execSync('git rev-parse --git-dir', { stdio: 'ignore' })
|
|
3939
|
+
} catch {
|
|
3940
|
+
return { content: '/fork requires a git repository.' }
|
|
3941
|
+
}
|
|
3942
|
+
|
|
3943
|
+
const agentViewManager = ctx.engine.getAgentViewManager?.()
|
|
3944
|
+
if (!agentViewManager) {
|
|
3945
|
+
return { content: 'Agent View manager is initializing...' }
|
|
3946
|
+
}
|
|
3947
|
+
|
|
3948
|
+
const slug = prompt
|
|
3949
|
+
.toLowerCase()
|
|
3950
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
3951
|
+
.replace(/^-|-$/g, '')
|
|
3952
|
+
.slice(0, 40)
|
|
3953
|
+
const name = `${slug}-${Date.now().toString(36)}`
|
|
3954
|
+
const branch = `worktree/${name}`
|
|
3955
|
+
const wtPath = join(process.cwd(), '.claude', 'worktrees', name)
|
|
3956
|
+
|
|
3957
|
+
try {
|
|
3958
|
+
execSync(`git worktree add -b ${branch} ${wtPath} HEAD`, { stdio: 'ignore', timeout: 30_000 })
|
|
3959
|
+
} catch (err) {
|
|
3960
|
+
try {
|
|
3961
|
+
execSync(`git worktree remove --force ${wtPath}`, { stdio: 'ignore' })
|
|
3962
|
+
} catch {
|
|
3963
|
+
/* ok */
|
|
3964
|
+
}
|
|
3965
|
+
try {
|
|
3966
|
+
execSync(`git branch -D ${branch}`, { stdio: 'ignore' })
|
|
3967
|
+
} catch {
|
|
3968
|
+
/* ok */
|
|
3969
|
+
}
|
|
3970
|
+
return {
|
|
3971
|
+
content: `Worktree creation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
|
|
3975
|
+
const session = agentViewManager.create(prompt, prompt, {
|
|
3976
|
+
provider: ctx.providerId,
|
|
3977
|
+
model: ctx.modelId,
|
|
3978
|
+
})
|
|
3979
|
+
agentViewManager.addMessage(session.id, { role: 'user', content: prompt })
|
|
3980
|
+
agentViewManager.updateStatus(session.id, 'working')
|
|
3981
|
+
session.worktree = wtPath
|
|
3982
|
+
session.branch = branch
|
|
3983
|
+
session.kind = 'forked'
|
|
3984
|
+
|
|
3985
|
+
const bgReg = (await import('../agent/background-registry')).getBackgroundAgentRegistry()
|
|
3986
|
+
bgReg.spawn(
|
|
3987
|
+
prompt,
|
|
3988
|
+
'general',
|
|
3989
|
+
async (_signal) => {
|
|
3990
|
+
const { SubAgent } = await import('../agent/sub-agent')
|
|
3991
|
+
const sa = new SubAgent(ctx.engine.getRegistry(), ctx.engine.getTools())
|
|
3992
|
+
const result = await sa.execute(prompt, 'fork: ' + prompt.slice(0, 60), {})
|
|
3993
|
+
try {
|
|
3994
|
+
const { execSync: ex } = await import('node:child_process')
|
|
3995
|
+
ex(`git -C ${wtPath} add -A`, { stdio: 'ignore', timeout: 10_000 })
|
|
3996
|
+
const st = ex(`git -C ${wtPath} status --porcelain`, { encoding: 'utf-8', timeout: 10_000 })
|
|
3997
|
+
if (st.trim()) {
|
|
3998
|
+
ex(
|
|
3999
|
+
`git -C ${wtPath} commit -m "feat: ${prompt.slice(0, 60)}\n\nCo-Authored-By: Claude <noreply@anthropic.com>"`,
|
|
4000
|
+
{ stdio: 'ignore', timeout: 10_000 },
|
|
4001
|
+
)
|
|
4002
|
+
ex(`git push origin ${branch}`, { stdio: 'ignore', timeout: 30_000 })
|
|
4003
|
+
}
|
|
4004
|
+
} catch {
|
|
4005
|
+
/* best-effort */
|
|
4006
|
+
}
|
|
4007
|
+
return [
|
|
4008
|
+
`## Fork done: ${prompt}`,
|
|
4009
|
+
'',
|
|
4010
|
+
`Branch: \`${branch}\``,
|
|
4011
|
+
`Worktree: \`${wtPath}\``,
|
|
4012
|
+
'',
|
|
4013
|
+
result || '(no output)',
|
|
4014
|
+
].join('\n')
|
|
4015
|
+
},
|
|
4016
|
+
'forked',
|
|
4017
|
+
)
|
|
4018
|
+
|
|
4019
|
+
return {
|
|
4020
|
+
content: [
|
|
4021
|
+
`✓ Forked: ${session.id}`,
|
|
4022
|
+
` Task: ${prompt.slice(0, 80)}`,
|
|
4023
|
+
` Branch: ${branch}`,
|
|
4024
|
+
` Worktree: ${wtPath}`,
|
|
4025
|
+
` Status: working`,
|
|
4026
|
+
'',
|
|
4027
|
+
'Agent will auto-commit + push on completion.',
|
|
4028
|
+
'Use /agents to track.',
|
|
4029
|
+
].join('\n'),
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
|
|
3695
4033
|
async function openBrowser(url: string): Promise<void> {
|
|
3696
4034
|
const cmd =
|
|
3697
4035
|
process.platform === 'darwin'
|
|
@@ -3858,6 +4196,7 @@ const commandsListCmd: CommandHandler = () => {
|
|
|
3858
4196
|
'/recommend': 'Project',
|
|
3859
4197
|
'/security': 'Project',
|
|
3860
4198
|
'/audit': 'Project',
|
|
4199
|
+
'/prompt-audit': 'Code Quality',
|
|
3861
4200
|
'/ide': 'Environment',
|
|
3862
4201
|
'/terminal-setup': 'Environment',
|
|
3863
4202
|
'/memory': 'Environment',
|
|
@@ -3867,6 +4206,7 @@ const commandsListCmd: CommandHandler = () => {
|
|
|
3867
4206
|
'/feedback': 'Account',
|
|
3868
4207
|
'/agents': 'Agents',
|
|
3869
4208
|
'/bg': 'Agents',
|
|
4209
|
+
'/fork': 'Agents',
|
|
3870
4210
|
'/artifact': 'Artifacts',
|
|
3871
4211
|
'/schedule': 'Other',
|
|
3872
4212
|
'/commit': 'Workflow',
|
|
@@ -3997,6 +4337,7 @@ registry.set('/permissions', permissionsCmd)
|
|
|
3997
4337
|
registry.set('/add-dir', addDirCmd)
|
|
3998
4338
|
registry.set('/security', securityCmd)
|
|
3999
4339
|
registry.set('/audit', securityCmd)
|
|
4340
|
+
registry.set('/prompt-audit', promptAuditCmd)
|
|
4000
4341
|
|
|
4001
4342
|
// Environment
|
|
4002
4343
|
registry.set('/theme', themeCmd)
|
|
@@ -4011,6 +4352,7 @@ registry.set('/logout', logoutCmd)
|
|
|
4011
4352
|
registry.set('/feedback', feedbackCmd)
|
|
4012
4353
|
registry.set('/agents', agentsCmd)
|
|
4013
4354
|
registry.set('/bg', bgCmd)
|
|
4355
|
+
registry.set('/fork', forkCmd)
|
|
4014
4356
|
|
|
4015
4357
|
// Artifacts
|
|
4016
4358
|
registry.set('/artifact', artifactBaseCmd)
|
|
@@ -4120,6 +4462,7 @@ const COMMAND_DESCRIPTIONS: Record<string, string> = {
|
|
|
4120
4462
|
'/recommend': 'Analyze project + recommend skills & setup',
|
|
4121
4463
|
'/security': 'Security review checklist',
|
|
4122
4464
|
'/audit': 'Same as /security',
|
|
4465
|
+
'/prompt-audit': 'Audit prompts for modern model optimization',
|
|
4123
4466
|
'/ide': 'IDE integration guide',
|
|
4124
4467
|
'/terminal-setup': 'Shell & terminal config',
|
|
4125
4468
|
'/memory': 'Manage AI memories',
|
|
@@ -4130,6 +4473,7 @@ const COMMAND_DESCRIPTIONS: Record<string, string> = {
|
|
|
4130
4473
|
'/feedback': 'Send feedback',
|
|
4131
4474
|
'/agents': 'Agent view dashboard',
|
|
4132
4475
|
'/bg': 'Run a background agent task',
|
|
4476
|
+
'/fork': 'Fork task into isolated worktree',
|
|
4133
4477
|
'/artifact': 'Manage artifacts',
|
|
4134
4478
|
'/schedule': 'View scheduled tasks and cron jobs',
|
|
4135
4479
|
'/commit': 'Generate commit message and review staged changes',
|
package/dist/mipham
DELETED
|
Binary file
|