@miphamai/cli 0.2.4 → 0.4.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.
Files changed (37) hide show
  1. package/bin/mipham.ts +2 -0
  2. package/dist/mipham +0 -0
  3. package/package.json +10 -9
  4. package/skills/mipham/om-artifact.mipham-skill.md +69 -0
  5. package/skills/mipham/om-model-optimize.mipham-skill.md +58 -9
  6. package/skills/mipham/om-security.mipham-skill.md +85 -10
  7. package/skills/standard/doc-generator.SKILL.md +72 -11
  8. package/skills/standard/github-ops.SKILL.md +94 -13
  9. package/skills/standard/memory.SKILL.md +72 -11
  10. package/skills/standard/self-review.SKILL.md +50 -10
  11. package/skills/standard/superpower.SKILL.md +46 -8
  12. package/skills/standard/tdd.SKILL.md +85 -12
  13. package/skills/standard/web-search.SKILL.md +65 -13
  14. package/src/agent/sub-agent.ts +0 -1
  15. package/src/artifacts/manifest.ts +101 -0
  16. package/src/artifacts/server.ts +343 -0
  17. package/src/core/context.ts +73 -13
  18. package/src/core/engine.ts +194 -71
  19. package/src/core/instructions.ts +1 -1
  20. package/src/core/permission.ts +35 -4
  21. package/src/core/session-store.ts +5 -1
  22. package/src/index.tsx +35 -2
  23. package/src/mcp/transport.ts +42 -5
  24. package/src/providers/anthropic.ts +2 -1
  25. package/src/providers/fetch-utils.ts +101 -0
  26. package/src/providers/openai-compat.ts +53 -15
  27. package/src/providers/registry.ts +1 -0
  28. package/src/shared/constants.ts +8 -1
  29. package/src/shared/types.ts +21 -1
  30. package/src/skills/loader.ts +2 -2
  31. package/src/tools/artifact/artifact.ts +144 -0
  32. package/src/tools/index.ts +3 -0
  33. package/src/ui/app.tsx +122 -15
  34. package/src/ui/chat.tsx +29 -7
  35. package/src/ui/commands.ts +117 -19
  36. package/src/ui/input.tsx +117 -35
  37. package/src/ui/picker.tsx +2 -5
@@ -1,19 +1,57 @@
1
1
  ---
2
2
  name: superpower
3
- description: Use when starting any conversationestablishes how to find and use skills
4
- version: 1.0.0
3
+ description: Skill discovery and invocation system — find and use skills before any response or action
4
+ version: 2.0.0
5
5
  ---
6
6
 
7
- # Superpowers Skill
7
+ # Superpowers — Using Skills
8
8
 
9
- ## Instruction Priority
9
+ ## The Rule
10
10
 
11
- User's explicit instructions always take precedence.
11
+ **Invoke relevant or requested skills BEFORE any response or action.** Even a 1% chance a skill might apply means you should invoke it to check.
12
12
 
13
13
  ## How to Access Skills
14
14
 
15
- Use the Skill tool to invoke skills. When you invoke a skill, its content is loaded and presented to you — follow it directly.
15
+ Use the `Skill` tool to invoke skills by name. When you invoke a skill, its content is loaded — follow it directly.
16
16
 
17
- ## The Rule
17
+ ## Skill Discovery
18
+
19
+ ### Check Available Skills
20
+
21
+ Skills are listed in `<system-reminder>` messages. Scan this list when receiving a task.
22
+
23
+ ### Matching Algorithm
24
+
25
+ 1. Parse the user's request for intent keywords
26
+ 2. Scan skill names and descriptions for matches
27
+ 3. If ANY skill matches at ≥1% probability → invoke it
28
+ 4. Multiple matches → invoke all that may apply
29
+ 5. Invoked skill doesn't fit → that's fine, don't use it
30
+
31
+ ### Priority Order
32
+
33
+ 1. **Process skills first** — brainstorming, systematic-debugging, tdd. These determine HOW to approach
34
+ 2. **Implementation skills second** — frontend-design, mcp-builder. These guide execution
35
+
36
+ ## Red Flags
37
+
38
+ These thoughts mean STOP — you're rationalizing:
39
+
40
+ | Thought | Reality |
41
+ | ----------------------------------- | ---------------------------------------------- |
42
+ | "This is just a simple question" | Questions are tasks. Check skills. |
43
+ | "I need more context first" | Skill check comes BEFORE clarifying questions. |
44
+ | "Let me explore the codebase first" | Skills tell you HOW to explore. |
45
+ | "I remember this skill" | Skills evolve. Read current version. |
46
+ | "The skill is overkill" | Simple things become complex. Use it. |
47
+
48
+ ## Skill Types
49
+
50
+ - **Rigid** (TDD, systematic-debugging): Follow exactly. Don't adapt away discipline.
51
+ - **Flexible** (patterns): Adapt principles to context.
52
+
53
+ The skill itself tells you which type it is.
54
+
55
+ ## User Instructions
18
56
 
19
- Invoke relevant or requested skills BEFORE any response or action. Even a 1% chance a skill might apply means that you should invoke the skill to check.
57
+ Instructions say WHAT, not HOW. "Add X" or "Fix Y" doesn't mean skip workflows.
@@ -1,20 +1,93 @@
1
1
  ---
2
2
  name: tdd
3
- description: Test-Driven Development workflow — red, green, refactor
4
- version: 1.0.0
3
+ description: Test-Driven Development — red-green-refactor cycle with language-specific guidance and test design rules
4
+ version: 2.0.0
5
5
  ---
6
6
 
7
- # TDD Skill
7
+ # Test-Driven Development (TDD)
8
8
 
9
- ## Workflow
9
+ ## The Cycle
10
10
 
11
- 1. **Red**: Write a failing test that defines the expected behavior
12
- 2. **Green**: Write the minimum code to make the test pass
13
- 3. **Refactor**: Clean up the code while tests remain green
11
+ ```
12
+ RED GREEN REFACTOR repeat
13
+ ```
14
14
 
15
- ## Rules
15
+ ### 1. RED — Write a Failing Test
16
16
 
17
- - Never write production code without a failing test
18
- - Write only enough test to fail
19
- - Write only enough code to pass
20
- - Tests must be deterministic and isolated
17
+ Write the smallest test that captures the behavior you want:
18
+
19
+ - Name the test descriptively: `it('should return 0 for empty string')`
20
+ - Use the AAA pattern: **A**rrange → **A**ct → **A**ssert
21
+ - Run to confirm it **fails** (not errors — fails)
22
+ - If it passes before implementation, your test is wrong
23
+
24
+ ### 2. GREEN — Make It Pass
25
+
26
+ Write the **minimum** code to make the test pass:
27
+
28
+ - Don't optimize, don't generalize, don't add features
29
+ - A hardcoded return is fine if it passes the test
30
+ - Run all tests — the new one should pass, old ones should still pass
31
+
32
+ ### 3. REFACTOR — Clean Up
33
+
34
+ Improve the code while tests stay green:
35
+
36
+ - Remove duplication (test code and production code)
37
+ - Improve names, extract helpers
38
+ - Simplify logic
39
+ - Run tests after each change
40
+
41
+ ## Test Design Rules
42
+
43
+ - **Deterministic**: No `Date.now()`, `Math.random()`, or network calls in test bodies
44
+ - **Isolated**: Each test sets up its own state; no test-order dependency
45
+ - **Fast**: Unit tests should run in milliseconds, not seconds
46
+ - **Readable**: Test output should explain what broke without reading source
47
+
48
+ ## Language-Specific Guidance
49
+
50
+ ### TypeScript / JavaScript (Vitest)
51
+
52
+ ```ts
53
+ import { describe, it, expect } from 'vitest'
54
+
55
+ describe('sum', () => {
56
+ it('should add two positive numbers', () => {
57
+ expect(sum(2, 3)).toBe(5)
58
+ })
59
+ it('should handle zero', () => {
60
+ expect(sum(0, 5)).toBe(5)
61
+ })
62
+ })
63
+ ```
64
+
65
+ File naming: `src/foo.ts` → `test/foo.test.ts`
66
+
67
+ ### Python (pytest)
68
+
69
+ ```python
70
+ def test_sum_positive():
71
+ assert sum(2, 3) == 5
72
+
73
+ def test_sum_zero():
74
+ assert sum(0, 5) == 5
75
+ ```
76
+
77
+ ### Go (testing package)
78
+
79
+ ```go
80
+ func TestSumPositive(t *testing.T) {
81
+ got := Sum(2, 3)
82
+ want := 5
83
+ if got != want {
84
+ t.Errorf("Sum(2,3) = %d; want %d", got, want)
85
+ }
86
+ }
87
+ ```
88
+
89
+ ## When NOT to TDD
90
+
91
+ - Exploratory spikes (throw away after learning)
92
+ - Configuration files and types (compile-time enforced)
93
+ - Generated code
@@ -1,23 +1,75 @@
1
1
  ---
2
2
  name: web-search
3
- description: Search the web for current information, documentation, and news
4
- version: 1.0.0
3
+ description: Search the web for current information documentation, news, technical references, and troubleshooting
4
+ version: 2.0.0
5
5
  ---
6
6
 
7
- # Web Search Skill
7
+ # Web Search
8
8
 
9
- Use WebSearch tool to find current information.
9
+ Use `WebSearch` tool to find current, accurate information from the web.
10
10
 
11
11
  ## When to Use
12
12
 
13
- - Up-to-date documentation for libraries and frameworks
14
- - Current events and news
15
- - Technical troubleshooting with recent solutions
16
- - API reference and version-specific features
13
+ - **Library/framework docs**: API references, migration guides, version-specific features
14
+ - **Current events**: News, releases, incidents (anything after training cutoff)
15
+ - **Troubleshooting**: Error messages, stack traces, known issues
16
+ - **Comparisons**: Technology trade-offs, benchmark data
17
+ - **Code examples**: Real-world usage patterns, configuration snippets
17
18
 
18
- ## Best Practices
19
+ ## Query Best Practices
19
20
 
20
- - Be specific with search queries
21
- - Use allowed_domains to focus results
22
- - Verify information from multiple sources
23
- - Cite sources in responses
21
+ ### Be Specific
22
+
23
+ ```
24
+ "React" → too broad
25
+ ❌ "React problems" → ambiguous
26
+ ✅ "React 19 useEffect double mount fix" → specific, versioned
27
+ ✅ "Next.js 14 App Router caching behavior 2026" → targeted
28
+ ```
29
+
30
+ ### Use Technical Terms
31
+
32
+ ```
33
+ ❌ "how to make website fast"
34
+ ✅ "Core Web Vitals LCP optimization Next.js 14"
35
+ ```
36
+
37
+ ### Include Version Numbers
38
+
39
+ ```
40
+ ❌ "prisma query"
41
+ ✅ "Prisma 5.0 findMany with nested include filter"
42
+ ```
43
+
44
+ ### Domain Filtering
45
+
46
+ Use `allowed_domains` for authoritative sources:
47
+
48
+ - `docs.github.com` — GitHub documentation
49
+ - `nextjs.org` — Next.js official docs
50
+ - `developer.mozilla.org` — MDN Web Docs
51
+ - `nodejs.org` — Node.js official
52
+
53
+ ## Verification
54
+
55
+ - **Cross-reference**: Verify claims across 2+ independent sources
56
+ - **Recency**: Prefer results from the current year; note article dates
57
+ - **Authority**: Official docs > well-known blogs > Stack Overflow > random forums
58
+ - **Cite sources**: Always include source URLs in responses
59
+
60
+ ## Source Attribution
61
+
62
+ After answering from search results, end with:
63
+
64
+ ```markdown
65
+ Sources:
66
+
67
+ - [Title](URL) — brief note
68
+ - [Title](URL) — brief note
69
+ ```
70
+
71
+ ## When NOT to Search
72
+
73
+ - Pure logic or algorithmic questions (reasoning, not research)
74
+ - Questions answerable from code already in context
75
+ - Opinions and subjective recommendations (search for data, not consensus)
@@ -1,6 +1,5 @@
1
1
  import { ContextManager } from '../core/context'
2
2
  import type { ProviderRegistry } from '../providers/registry'
3
- import type { Message } from '../shared/types'
4
3
 
5
4
  export type SubAgentType = 'general' | 'explore' | 'plan' | 'code-review'
6
5
 
@@ -0,0 +1,101 @@
1
+ import {
2
+ readFileSync,
3
+ writeFileSync,
4
+ existsSync,
5
+ mkdirSync,
6
+ renameSync,
7
+ copyFileSync,
8
+ unlinkSync,
9
+ } from 'node:fs'
10
+ import { join } from 'node:path'
11
+ import type { ArtifactManifest, ArtifactEntry } from '../shared/types'
12
+
13
+ /**
14
+ * Read the artifact manifest from disk, or return an empty one if it doesn't exist.
15
+ */
16
+ export function readManifest(dir: string): ArtifactManifest {
17
+ const path = join(dir, 'index.json')
18
+ if (!existsSync(path)) {
19
+ return { version: 1, artifacts: [] }
20
+ }
21
+ try {
22
+ return JSON.parse(readFileSync(path, 'utf-8'))
23
+ } catch {
24
+ return { version: 1, artifacts: [] }
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Write the manifest to disk, creating parent directories as needed.
30
+ */
31
+ export function writeManifest(dir: string, manifest: ArtifactManifest): void {
32
+ mkdirSync(dir, { recursive: true })
33
+ writeFileSync(join(dir, 'index.json'), JSON.stringify(manifest, null, 2), 'utf-8')
34
+ }
35
+
36
+ /**
37
+ * Add an entry to the manifest and persist it.
38
+ * If an entry with the same name already exists, it is replaced.
39
+ */
40
+ export function addToManifest(dir: string, entry: ArtifactEntry, port?: number): ArtifactManifest {
41
+ const manifest = readManifest(dir)
42
+ if (port !== undefined) manifest.port = port
43
+
44
+ const idx = manifest.artifacts.findIndex((a) => a.name === entry.name)
45
+ if (idx >= 0) {
46
+ manifest.artifacts[idx] = entry
47
+ } else {
48
+ manifest.artifacts.push(entry)
49
+ }
50
+
51
+ writeManifest(dir, manifest)
52
+ return manifest
53
+ }
54
+
55
+ /**
56
+ * Get all artifacts for a specific session.
57
+ */
58
+ export function getSessionArtifacts(dir: string, sessionId: string): ArtifactEntry[] {
59
+ const manifest = readManifest(dir)
60
+ return manifest.artifacts.filter((a) => a.sessionId === sessionId)
61
+ }
62
+
63
+ /**
64
+ * Archive an existing artifact file by renaming it with a version tag.
65
+ * e.g. dashboard.html → dashboard.v1.html, dashboard.v1.html → dashboard.v2.html.
66
+ *
67
+ * Returns the version tag assigned to the archived file.
68
+ */
69
+ export function archiveVersion(dir: string, entry: ArtifactEntry): string {
70
+ const manifest = readManifest(dir)
71
+ const versionCount = (entry.versionCount || 1) + 1
72
+ const ext = entry.type === 'svg' ? '.svg' : '.html'
73
+ const versionTag = `v${versionCount}`
74
+
75
+ // Rename the current file to a versioned copy
76
+ const baseName = entry.name
77
+ const currentPath = join(dir, entry.sessionId, `${baseName}${ext}`)
78
+ const archivedPath = join(dir, entry.sessionId, `${baseName}.${versionTag}${ext}`)
79
+
80
+ if (existsSync(currentPath)) {
81
+ try {
82
+ renameSync(currentPath, archivedPath)
83
+ } catch {
84
+ // If rename fails (e.g. cross-device), copy instead
85
+ copyFileSync(currentPath, archivedPath)
86
+ unlinkSync(currentPath)
87
+ }
88
+ }
89
+
90
+ // Update manifest entry
91
+ const artifact = manifest.artifacts.find((a) => a.name === entry.name)
92
+ if (artifact) {
93
+ const versions = artifact.versions || ['v1']
94
+ versions.push(versionTag)
95
+ artifact.versions = versions
96
+ artifact.versionCount = versionCount
97
+ }
98
+
99
+ writeManifest(dir, manifest)
100
+ return versionTag
101
+ }