@buivietphi/skill-mobile-mt 1.1.0 → 1.2.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.

Potentially problematic release.


This version of @buivietphi/skill-mobile-mt might be problematic. Click here for more details.

package/AGENTS.md CHANGED
@@ -6,16 +6,16 @@
6
6
 
7
7
  ## Agent Compatibility Matrix
8
8
 
9
- | Agent | Skill Path | Invocation | Think Block |
10
- |-------|-----------|------------|-------------|
11
- | Claude Code | `~/.claude/skills/skill-mobile-mt/` | `@skill-mobile-mt` or `@skill-mobile-mt project` | `<think>...</think>` |
12
- | Codex | `~/.codex/skills/skill-mobile-mt/` | `@skill-mobile-mt` or load as context | `<think>...</think>` |
13
- | Gemini CLI | `~/.gemini/skills/skill-mobile-mt/` | Load as context | `## Thinking:` block |
14
- | Kimi | `~/.kimi/skills/skill-mobile-mt/` | Load as context | `【思考】` or markdown |
15
- | Cursor | `~/.cursor/skills/skill-mobile-mt/` | Auto-loaded in Composer | Inline reasoning |
16
- | Copilot | `~/.copilot/skills/skill-mobile-mt/` | Loaded via workspace | `// PLAN:` comments |
17
- | Windsurf | `~/.windsurf/skills/skill-mobile-mt/` | Auto-loaded | Inline reasoning |
18
- | Antigravity | `~/.agents/skills/skill-mobile-mt/` | Loaded by orchestrator | Agent-native format |
9
+ | Agent | How it loads rules | Setup | Think Block |
10
+ |-------|-------------------|-------|-------------|
11
+ | Claude Code | `~/.claude/skills/` (auto) | `npx skill-mobile-mt --claude` | `<think>...</think>` |
12
+ | Codex | `~/.codex/skills/` (auto) | `npx skill-mobile-mt --codex` | `<think>...</think>` |
13
+ | Gemini CLI | `~/.gemini/skills/` (auto) | `npx skill-mobile-mt --gemini` | `## Thinking:` block |
14
+ | Kimi | `~/.kimi/skills/` (manual) | `npx skill-mobile-mt --kimi` | `【思考】` or markdown |
15
+ | **Cursor** | **`.cursorrules` in project root** | **`npx skill-mobile-mt --init cursor`** | Inline reasoning |
16
+ | **Copilot** | **`.github/copilot-instructions.md`** | **`npx skill-mobile-mt --init copilot`** | `// PLAN:` comments |
17
+ | **Windsurf** | **`.windsurfrules` in project root** | **`npx skill-mobile-mt --init windsurf`** | Inline reasoning |
18
+ | Antigravity | `~/.agents/skills/` (auto) | `npx skill-mobile-mt --antigravity` | Agent-native format |
19
19
 
20
20
  ---
21
21
 
@@ -137,7 +137,7 @@ The agent reads the task, then decides which extra file to load:
137
137
  ```yaml
138
138
  skill:
139
139
  name: skill-mobile-mt
140
- version: "1.0.0"
140
+ version: "1.2.0"
141
141
  author: buivietphi
142
142
  category: engineering
143
143
  tags:
@@ -299,10 +299,23 @@ Priority 6 (ON-DEMAND): shared/common-pitfalls.md — Known issue patterns
299
299
  - Supports both Chinese and English prompts
300
300
  - Think blocks use `【思考】` format
301
301
 
302
- ### Cursor / Copilot / Windsurf
303
- - Auto-loaded when skill directory detected in workspace
304
- - Mode determined by presence of project files in workspace
305
- - Think blocks embedded as comments before code
302
+ ### Cursor
303
+ - **Does NOT read from `~/.cursor/skills/`** reads `.cursorrules` from project root
304
+ - Run `npx @buivietphi/skill-mobile-mt --init cursor` in your project to generate `.cursorrules`
305
+ - The generated file includes auto-detected framework, rules, and security patterns
306
+ - Think blocks embedded as inline reasoning in Composer
307
+
308
+ ### GitHub Copilot
309
+ - **Does NOT read from `~/.copilot/skills/`** — reads `.github/copilot-instructions.md`
310
+ - Run `npx @buivietphi/skill-mobile-mt --init copilot` in your project to generate the file
311
+ - The generated file includes code patterns, required templates, and rules
312
+ - Think blocks as `// PLAN:` comments before code
313
+
314
+ ### Windsurf
315
+ - **Does NOT read from `~/.windsurf/skills/`** — reads `.windsurfrules` from project root
316
+ - Run `npx @buivietphi/skill-mobile-mt --init windsurf` in your project to generate `.windsurfrules`
317
+ - The generated file includes coding rules, security rules, and architecture patterns
318
+ - Think blocks as inline reasoning
306
319
 
307
320
  ### Antigravity
308
321
  - Orchestrator loads based on detected project type
@@ -340,6 +353,8 @@ Copy the relevant section to your project to enable auto-check rules in every se
340
353
 
341
354
  ## Installation Paths
342
355
 
356
+ ### Skill directory install (agents that read from skills/)
357
+
343
358
  ```bash
344
359
  # Claude Code (global)
345
360
  ~/.claude/skills/skill-mobile-mt/
@@ -356,15 +371,6 @@ Copy the relevant section to your project to enable auto-check rules in every se
356
371
  # Kimi
357
372
  ~/.kimi/skills/skill-mobile-mt/
358
373
 
359
- # Cursor
360
- ~/.cursor/skills/skill-mobile-mt/
361
-
362
- # Windsurf
363
- ~/.windsurf/skills/skill-mobile-mt/
364
-
365
- # Copilot
366
- ~/.copilot/skills/skill-mobile-mt/
367
-
368
374
  # Antigravity (shared agent directory)
369
375
  ~/.agents/skills/skill-mobile-mt/
370
376
 
@@ -372,6 +378,28 @@ Copy the relevant section to your project to enable auto-check rules in every se
372
378
  npx @buivietphi/skill-mobile-mt --path /your/custom/path
373
379
  ```
374
380
 
381
+ ### Project-level files (agents that read from project root)
382
+
383
+ These agents read rules from project-level files, NOT from a skills directory.
384
+ Use `--init` to generate them:
385
+
386
+ ```bash
387
+ # Generate all project-level files (interactive selector)
388
+ npx @buivietphi/skill-mobile-mt --init
389
+
390
+ # Generate specific agent file
391
+ npx @buivietphi/skill-mobile-mt --init cursor # → .cursorrules
392
+ npx @buivietphi/skill-mobile-mt --init copilot # → .github/copilot-instructions.md
393
+ npx @buivietphi/skill-mobile-mt --init windsurf # → .windsurfrules
394
+ npx @buivietphi/skill-mobile-mt --init all # → all three files
395
+ ```
396
+
397
+ **What `--init` does:**
398
+ 1. Auto-detects your project (framework, language, state management, etc.)
399
+ 2. Generates rules files pre-filled with your detected stack
400
+ 3. Includes all mobile best practices, security rules, and quality gates
401
+ 4. Won't overwrite existing files (safe to run multiple times)
402
+
375
403
  ---
376
404
 
377
405
  ## Metadata
@@ -380,7 +408,7 @@ npx @buivietphi/skill-mobile-mt --path /your/custom/path
380
408
  {
381
409
  "id": "skill-mobile-mt",
382
410
  "name": "skill-mobile-mt",
383
- "version": "1.0.0",
411
+ "version": "1.2.0",
384
412
  "author": "buivietphi",
385
413
  "category": "engineering",
386
414
  "description": "Master Senior Mobile Engineer. Pre-built patterns from 18 production apps + project adaptation. Auto-detects language and framework. React Native, Flutter, iOS, Android.",
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Master Senior Mobile Engineer** — AI skill for Claude Code, Codex, Gemini CLI, Kimi, Cursor, Copilot, Windsurf, and Antigravity.
4
4
 
5
- Pre-built architecture patterns from **18 production mobile apps + 4 production open-source skills** + auto-adaptation to your current project.
5
+ Pre-built architecture patterns from **30+ production repos (200k+ GitHub stars)** including Ignite, Expensify, Mattermost, Immich, AppFlowy, Now in Android, TCA + auto-adaptation to your current project.
6
6
 
7
7
  ## Install
8
8
 
@@ -10,20 +10,38 @@ Pre-built architecture patterns from **18 production mobile apps + 4 production
10
10
  npx @buivietphi/skill-mobile-mt
11
11
  ```
12
12
 
13
- Interactive mode — detects which AI agents are installed and prompts you.
13
+ Interactive checkbox UI — detects which AI agents are installed, lets you select with arrow keys + space.
14
14
 
15
15
  ### Install to specific agents
16
16
 
17
17
  ```bash
18
- npx @buivietphi/skill-mobile-mt --claude # Claude Code only
19
- npx @buivietphi/skill-mobile-mt --codex # Codex only
20
- npx @buivietphi/skill-mobile-mt --gemini # Gemini CLI only
21
- npx @buivietphi/skill-mobile-mt --kimi # Kimi only
22
- npx @buivietphi/skill-mobile-mt --antigravity # Antigravity only
23
- npx @buivietphi/skill-mobile-mt --all # All detected agents
18
+ npx @buivietphi/skill-mobile-mt --claude # Claude Code
19
+ npx @buivietphi/skill-mobile-mt --codex # Codex
20
+ npx @buivietphi/skill-mobile-mt --gemini # Gemini CLI
21
+ npx @buivietphi/skill-mobile-mt --kimi # Kimi
22
+ npx @buivietphi/skill-mobile-mt --antigravity # Antigravity
23
+ npx @buivietphi/skill-mobile-mt --all # All agents
24
24
  npx @buivietphi/skill-mobile-mt --path ./dir # Custom directory
25
25
  ```
26
26
 
27
+ ### Generate project-level rules (Cursor, Copilot, Windsurf)
28
+
29
+ Cursor, Copilot, and Windsurf read rules from **project-level files**, not from a skills directory. Run `--init` inside your project to generate them:
30
+
31
+ ```bash
32
+ npx @buivietphi/skill-mobile-mt --init # Interactive selector
33
+ npx @buivietphi/skill-mobile-mt --init cursor # .cursorrules
34
+ npx @buivietphi/skill-mobile-mt --init copilot # .github/copilot-instructions.md
35
+ npx @buivietphi/skill-mobile-mt --init windsurf # .windsurfrules
36
+ npx @buivietphi/skill-mobile-mt --init all # All three files
37
+ ```
38
+
39
+ **What `--init` does:**
40
+ 1. Auto-detects your project (framework, language, state management, navigation, API client, package manager)
41
+ 2. Generates rules files pre-filled with your detected stack
42
+ 3. Includes mobile best practices, security rules, and quality gates
43
+ 4. Won't overwrite existing files (safe to run multiple times)
44
+
27
45
  ## Usage
28
46
 
29
47
  ### Mode 1: Pre-Built Architecture (default)
@@ -32,11 +50,11 @@ npx @buivietphi/skill-mobile-mt --path ./dir # Custom directory
32
50
  @skill-mobile-mt
33
51
  ```
34
52
 
35
- Uses battle-tested patterns extracted from real production apps:
36
- - **10 React Native apps** — Redux, MobX, Apollo/GraphQL, React Navigation
37
- - **3 Flutter apps** — Riverpod, Clean Architecture, Dio, GoRouter
38
- - **4 Android Native apps** — Multi-module Gradle, Hilt, Compose, Room
39
- - **1 iOS Native app** Swift, MVVM, CocoaPods, Combine
53
+ Uses battle-tested patterns from 30+ production repos:
54
+ - **React Native** — Ignite (19.7k stars), Obytes Template, Expensify/App, Mattermost Mobile, Artsy Eigen
55
+ - **Flutter** — Immich (93.5k stars), AppFlowy (68.2k), Spotube (44.6k), Hiddify, Ente Photos
56
+ - **iOS** TCA / Point-Free (14.4k), Clean Arch SwiftUI, Modern Clean Arch
57
+ - **Android** Now in Android (20.7k), Android Showcase, Mihon (18.8k)
40
58
 
41
59
  ### Mode 2: Adapt to Your Project (project)
42
60
 
@@ -47,8 +65,123 @@ Uses battle-tested patterns extracted from real production apps:
47
65
  Reads your current project first, then follows **your** conventions:
48
66
  - Detects framework, language, package manager, state management, navigation
49
67
  - Matches your naming, imports, file structure, patterns
68
+ - Clones the most similar existing feature when scaffolding new ones
50
69
  - Never suggests migrations or imposes different architecture
51
70
 
71
+ ## Quick Start Examples
72
+
73
+ ### Step 1: Install the skill
74
+
75
+ ```bash
76
+ # Install globally (one-time setup)
77
+ npx @buivietphi/skill-mobile-mt
78
+ ```
79
+
80
+ You'll see an interactive checkbox — use arrow keys to navigate, space to select, Enter to confirm:
81
+
82
+ ```
83
+ Select agents to install:
84
+ ↑↓ navigate Space toggle A select all Enter confirm Q cancel
85
+
86
+ › ◉ Claude Code [detected]
87
+ ◯ Cursor [detected]
88
+ ◯ Windsurf [not found]
89
+ ◯ Copilot [not found]
90
+ ◯ Codex [not found]
91
+ ◉ Gemini CLI [detected]
92
+ ◯ Kimi [not found]
93
+ ◯ Antigravity [not found]
94
+ ```
95
+
96
+ ### Step 2 (Cursor/Copilot/Windsurf only): Generate project rules
97
+
98
+ ```bash
99
+ # cd into your mobile project first
100
+ cd ~/projects/my-app
101
+
102
+ # Generate rules for your agents
103
+ npx @buivietphi/skill-mobile-mt --init all
104
+ ```
105
+
106
+ Output:
107
+
108
+ ```
109
+ 📁 Project directory: /Users/you/projects/my-app
110
+ 🔍 Detected: Expo (React Native) (TypeScript)
111
+
112
+ ✓ .cursorrules → Cursor (auto-detected: Expo (React Native))
113
+ ✓ .github/copilot-instructions.md → GitHub Copilot
114
+ ✓ .windsurfrules → Windsurf
115
+
116
+ ✅ Done! → 3 file(s) generated
117
+ ```
118
+
119
+ ### Step 3: Use in your AI agent
120
+
121
+ #### Claude Code
122
+
123
+ ```bash
124
+ # In Claude Code terminal, type:
125
+ @skill-mobile-mt
126
+
127
+ # Then ask anything:
128
+ > Create auth feature with login and register screens
129
+
130
+ # Or with project mode (reads YOUR code first):
131
+ @skill-mobile-mt project
132
+ > Add cart feature following the same pattern as ProductList
133
+ ```
134
+
135
+ #### Cursor
136
+
137
+ After running `--init cursor`, Cursor auto-loads `.cursorrules` every session. Just open your project and code — Cursor follows the rules automatically.
138
+
139
+ ```
140
+ # In Cursor Composer, just ask:
141
+ > Create a login screen with email/password
142
+ > Fix the crash in ProductDetail when images is null
143
+ > Review this PR for mobile best practices
144
+ ```
145
+
146
+ #### GitHub Copilot
147
+
148
+ After running `--init copilot`, Copilot reads `.github/copilot-instructions.md` as workspace context.
149
+
150
+ ```
151
+ # In VS Code with Copilot Chat:
152
+ > Add pagination to the product list
153
+ > Handle offline mode for the cart feature
154
+ ```
155
+
156
+ #### Windsurf
157
+
158
+ After running `--init windsurf`, Windsurf auto-loads `.windsurfrules`. Just code normally.
159
+
160
+ #### Gemini CLI
161
+
162
+ ```bash
163
+ # In Gemini CLI:
164
+ @skill-mobile-mt
165
+ > Setup a new Flutter project with Riverpod + clean architecture
166
+ ```
167
+
168
+ #### Codex / Kimi / Antigravity
169
+
170
+ Same as Claude Code — the skill is loaded from the skills directory.
171
+
172
+ ### Example Prompts (all agents)
173
+
174
+ | What you want | What to type |
175
+ |--------------|-------------|
176
+ | New feature | `Create auth feature with login, register, forgot password` |
177
+ | New screen | `Add settings screen with profile, notifications, theme toggle` |
178
+ | Fix bug | `Fix crash when product.images is undefined` |
179
+ | Code review | `Review src/features/cart/ for mobile best practices` |
180
+ | Performance | `Optimize ProductList — it's janky when scrolling 100+ items` |
181
+ | Architecture | `Setup project structure for a new Expo app with Zustand + TanStack Query` |
182
+ | Release | `Prepare the app for App Store submission` |
183
+ | Security | `Audit the auth flow for security vulnerabilities` |
184
+
52
185
  ## Auto-Detect
53
186
 
54
187
  The skill automatically detects before any action:
@@ -102,6 +235,7 @@ iOS only?
102
235
  | `shared/code-review.md` | 865 |
103
236
  | `shared/bug-detection.md` | 499 |
104
237
  | `shared/prompt-engineering.md` | 3,927 |
238
+ | `shared/architecture-intelligence.md` | 4,500 |
105
239
  | `shared/common-pitfalls.md` | 1,160 |
106
240
  | `shared/error-recovery.md` | 2,435 |
107
241
  | `shared/document-analysis.md` | 1,200 |
@@ -111,36 +245,51 @@ iOS only?
111
245
  | `shared/platform-excellence.md` | 1,500 |
112
246
  | `shared/version-management.md` | 3,500 |
113
247
  | `shared/observability.md` | 3,000 |
114
- | **Total** | **~41,700** |
248
+ | `shared/claude-md-template.md` | ~500 |
249
+ | `shared/agent-rules-template.md` | ~2,500 |
250
+ | **Total** | **~46,000** |
115
251
 
116
252
  ## Installed Structure
117
253
 
118
254
  ```
119
255
  ~/.claude/skills/ (or ~/.gemini/skills/, ~/.agents/skills/, etc.)
120
256
  └── skill-mobile-mt/
121
- ├── SKILL.md Entry point + auto-detect
122
- ├── AGENTS.md Multi-agent compatibility
257
+ ├── SKILL.md Entry point + auto-detect + quality gates
258
+ ├── AGENTS.md Multi-agent compatibility
123
259
  ├── react-native/
124
- │ └── react-native.md React Native patterns
260
+ │ └── react-native.md React Native + Expo patterns
125
261
  ├── flutter/
126
- │ └── flutter.md Flutter patterns
262
+ │ └── flutter.md Flutter + Dart patterns
127
263
  ├── ios/
128
- │ └── ios-native.md iOS Swift patterns
264
+ │ └── ios-native.md iOS Swift patterns
129
265
  ├── android/
130
- │ └── android-native.md Android Kotlin patterns
266
+ │ └── android-native.md Android Kotlin patterns
131
267
  └── shared/
132
- ├── code-review.md Senior review checklist
133
- ├── bug-detection.md Auto bug scanner
134
- ├── prompt-engineering.md Intelligent prompt generation
135
- ├── common-pitfalls.md Problem Symptoms Solution
136
- ├── error-recovery.md Fix build/runtime errors
137
- ├── document-analysis.md Parse docs/images code
138
- ├── anti-patterns.md PII, cardinality, payload detection
139
- ├── performance-prediction.md Predict FPS/memory BEFORE shipping
140
- ├── platform-excellence.md iOS 18+ vs Android 15+ guidelines
141
- ├── version-management.md SDK compatibility matrix + release testing
142
- ├── observability.md Sessions as 4th pillar, context-rich events
143
- └── release-checklist.md Pre-release verification
268
+ ├── code-review.md Senior review checklist
269
+ ├── bug-detection.md Auto bug scanner
270
+ ├── prompt-engineering.md Auto-think + prompt templates
271
+ ├── architecture-intelligence.md Patterns from 30+ production repos
272
+ ├── common-pitfalls.md Problem Symptoms → Solution
273
+ ├── error-recovery.md 16 build/runtime error fixes
274
+ ├── document-analysis.md Parse docs/images code
275
+ ├── anti-patterns.md PII, cardinality, payload detection
276
+ ├── performance-prediction.md Frame budget, FPS prediction
277
+ ├── platform-excellence.md iOS 18+ vs Android 15+ guidelines
278
+ ├── version-management.md SDK compatibility matrix
279
+ ├── observability.md Sessions as 4th pillar
280
+ ├── release-checklist.md Pre-release verification
281
+ ├── claude-md-template.md CLAUDE.md template for projects
282
+ └── agent-rules-template.md Rules templates for all agents
283
+ ```
284
+
285
+ ### Project-level files (generated by `--init`)
286
+
287
+ ```
288
+ your-project/
289
+ ├── .cursorrules Cursor rules (auto-detected stack)
290
+ ├── .windsurfrules Windsurf rules (auto-detected stack)
291
+ └── .github/
292
+ └── copilot-instructions.md Copilot rules (auto-detected stack)
144
293
  ```
145
294
 
146
295
  ## What's Included
@@ -183,6 +332,10 @@ iOS only?
183
332
  - Requirements Extraction: user stories, screen flows, data models, business rules
184
333
  - Document → Code pipeline: read → extract → map features → scaffold
185
334
 
335
+ ### Architecture Intelligence (from 30+ production repos)
336
+
337
+ - **Architecture Intelligence** (`architecture-intelligence.md`): Cross-platform patterns from Ignite, Immich, AppFlowy, TCA, Now in Android and more. Includes: dual state management, feature-based modules, bootstrap/startup pattern, functional error handling, architecture validation (Konsist), production folder structure templates, and decision matrices for state/nav/testing.
338
+
186
339
  ### Production Patterns (from Senaiverse, Mhuxain, VoltAgent, Nexus)
187
340
 
188
341
  - **Anti-Pattern Detection** (`anti-patterns.md`): Detect PII leaks (CRITICAL), high cardinality tags, unbounded payloads, unstructured logs, sync telemetry on main thread — with auto-fix suggestions
@@ -208,16 +361,16 @@ iOS only?
208
361
 
209
362
  ## Supported Agents
210
363
 
211
- | Agent | Install Path | Status |
212
- |-------|-------------|--------|
213
- | Claude Code | `~/.claude/skills/skill-mobile-mt/` | Full support |
214
- | Codex | `~/.codex/skills/skill-mobile-mt/` | Full support |
215
- | Gemini CLI | `~/.gemini/skills/skill-mobile-mt/` | Full support |
216
- | Kimi | `~/.kimi/skills/skill-mobile-mt/` | Full support |
217
- | Cursor | `~/.cursor/skills/skill-mobile-mt/` | Full support |
218
- | Copilot | `~/.copilot/skills/skill-mobile-mt/` | Full support |
219
- | Windsurf | `~/.windsurf/skills/skill-mobile-mt/` | Full support |
220
- | Antigravity | `~/.agents/skills/skill-mobile-mt/` | Full support |
364
+ | Agent | How it works | Setup command |
365
+ |-------|-------------|---------------|
366
+ | **Claude Code** | Reads from `~/.claude/skills/` | `npx skill-mobile-mt --claude` |
367
+ | **Codex** | Reads from `~/.codex/skills/` | `npx skill-mobile-mt --codex` |
368
+ | **Gemini CLI** | Reads from `~/.gemini/skills/` | `npx skill-mobile-mt --gemini` |
369
+ | **Kimi** | Reads from `~/.kimi/skills/` | `npx skill-mobile-mt --kimi` |
370
+ | **Antigravity** | Reads from `~/.agents/skills/` | `npx skill-mobile-mt --antigravity` |
371
+ | **Cursor** | Reads `.cursorrules` from project root | `npx skill-mobile-mt --init cursor` |
372
+ | **Copilot** | Reads `.github/copilot-instructions.md` | `npx skill-mobile-mt --init copilot` |
373
+ | **Windsurf** | Reads `.windsurfrules` from project root | `npx skill-mobile-mt --init windsurf` |
221
374
 
222
375
  ## License
223
376
 
package/SKILL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: skill-mobile-mt
3
3
  description: "Master Senior Mobile Engineer. Patterns from 30+ production repos (200k+ GitHub stars: Ignite, Expensify, Mattermost, Immich, AppFlowy, Now in Android, TCA). Use when: building mobile features, fixing mobile bugs, reviewing mobile code, mobile architecture, React Native, Flutter, iOS Swift, Android Kotlin, mobile performance, mobile security audit, mobile code review, app release. Two modes: (1) default = pre-built production patterns, (2) 'project' = reads current project and adapts."
4
- version: "1.1.0"
4
+ version: "1.2.0"
5
5
  author: buivietphi
6
6
  priority: high
7
7
  user-invocable: true
package/bin/install.mjs CHANGED
@@ -14,9 +14,14 @@
14
14
  * npx @buivietphi/skill-mobile --antigravity # Antigravity
15
15
  * npx @buivietphi/skill-mobile --auto # Auto-detect (postinstall)
16
16
  * npx @buivietphi/skill-mobile --path DIR # Custom path
17
+ * npx @buivietphi/skill-mobile --init # Generate project-level rules (interactive)
18
+ * npx @buivietphi/skill-mobile --init cursor # Generate .cursorrules
19
+ * npx @buivietphi/skill-mobile --init copilot # Generate .github/copilot-instructions.md
20
+ * npx @buivietphi/skill-mobile --init windsurf # Generate .windsurfrules
21
+ * npx @buivietphi/skill-mobile --init all # Generate all project-level files
17
22
  */
18
23
 
19
- import { existsSync, mkdirSync, cpSync, readFileSync } from 'node:fs';
24
+ import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync } from 'node:fs';
20
25
  import { join, resolve, dirname } from 'node:path';
21
26
  import { homedir } from 'node:os';
22
27
  import { fileURLToPath } from 'node:url';
@@ -56,7 +61,7 @@ const fail = m => log(` ${c.red}✗${c.reset} ${m}`);
56
61
 
57
62
  function banner() {
58
63
  log(`\n${c.bold}${c.cyan} ┌──────────────────────────────────────────────┐`);
59
- log(` │ 📱 @buivietphi/skill-mobile-mt v1.1.0 │`);
64
+ log(` │ 📱 @buivietphi/skill-mobile-mt v1.2.0 │`);
60
65
  log(` │ Master Senior Mobile Engineer │`);
61
66
  log(` │ │`);
62
67
  log(` │ Claude · Codex · Gemini · Kimi │`);
@@ -113,6 +118,368 @@ function install(baseDir, agentName) {
113
118
  return n;
114
119
  }
115
120
 
121
+ // ─── Project Auto-Detect ─────────────────────────────────────────────────────
122
+
123
+ function detectProject(dir) {
124
+ const has = f => existsSync(join(dir, f));
125
+ const readJson = f => { try { return JSON.parse(readFileSync(join(dir, f), 'utf-8')); } catch { return null; } };
126
+
127
+ let framework = '[React Native CLI / Expo / Flutter / iOS / Android]';
128
+ let language = '[TypeScript / Dart / Swift / Kotlin]';
129
+ let state = '[Redux Toolkit / Zustand / Riverpod / BLoC / StateFlow]';
130
+ let nav = '[React Navigation / Expo Router / GoRouter / UIKit / Jetpack]';
131
+ let api = '[axios / fetch / Dio / Firebase / Retrofit]';
132
+ let pkgMgr = '[yarn / npm / bun / flutter pub]';
133
+
134
+ // Detect framework + language
135
+ if (has('pubspec.yaml')) {
136
+ framework = 'Flutter'; language = 'Dart'; pkgMgr = 'flutter pub';
137
+ } else if (has('package.json')) {
138
+ const pkg = readJson('package.json');
139
+ const deps = { ...(pkg?.dependencies || {}), ...(pkg?.devDependencies || {}) };
140
+ if (deps['expo']) { framework = 'Expo (React Native)'; }
141
+ else if (deps['react-native']) { framework = 'React Native CLI'; }
142
+ language = deps['typescript'] || has('tsconfig.json') ? 'TypeScript' : 'JavaScript';
143
+ // State
144
+ if (deps['@reduxjs/toolkit'] || deps['redux']) state = 'Redux Toolkit';
145
+ else if (deps['zustand']) state = 'Zustand';
146
+ else if (deps['mobx-react-lite'] || deps['mobx'])state = 'MobX';
147
+ // Nav
148
+ if (deps['expo-router']) nav = 'Expo Router';
149
+ else if (deps['@react-navigation/native']) nav = 'React Navigation';
150
+ // API
151
+ if (deps['axios']) api = 'axios';
152
+ else if (deps['@apollo/client']) api = 'GraphQL (Apollo)';
153
+ // Pkg manager
154
+ if (has('yarn.lock')) pkgMgr = 'yarn';
155
+ else if (has('pnpm-lock.yaml')) pkgMgr = 'pnpm';
156
+ else if (has('bun.lockb')) pkgMgr = 'bun';
157
+ else pkgMgr = 'npm';
158
+ } else if (has('build.gradle') || has('build.gradle.kts')) {
159
+ framework = 'Android Native'; language = 'Kotlin'; pkgMgr = 'Gradle';
160
+ }
161
+ // iOS detection (*.xcodeproj) is harder — leave as placeholder
162
+
163
+ return { framework, language, state, nav, api, pkgMgr };
164
+ }
165
+
166
+ // ─── Project-Level File Templates ────────────────────────────────────────────
167
+
168
+ const PROJECT_AGENTS = {
169
+ cursor: {
170
+ name: 'Cursor',
171
+ file: '.cursorrules',
172
+ dir: '.',
173
+ generate: (p) => `# ${p.framework} Project — Cursor Rules
174
+ # Generated by @buivietphi/skill-mobile-mt
175
+
176
+ ## Project
177
+ - Framework: ${p.framework}
178
+ - Language: ${p.language}
179
+ - State: ${p.state}
180
+ - Navigation: ${p.nav}
181
+ - API: ${p.api}
182
+ - Package Manager: ${p.pkgMgr}
183
+
184
+ ## Code Style
185
+ - PascalCase for screens and components
186
+ - camelCase for hooks, services, utils
187
+ - Absolute imports with @/ alias (if configured)
188
+
189
+ ## Auto-Check (before every completion)
190
+ - No console.log / print in production code
191
+ - No hardcoded secrets or API keys
192
+ - All async wrapped in try/catch
193
+ - All 4 states: loading / error / empty / success
194
+ - useEffect has cleanup (return () => ...)
195
+ - FlatList (not ScrollView) for dynamic lists > 20 items
196
+ - No implicit 'any' in TypeScript
197
+ - No force unwrap (! / !!) without null check
198
+ - New screens registered in navigator
199
+
200
+ ## Performance
201
+ - React.memo / const widget for expensive components
202
+ - useMemo/useCallback for stable references
203
+ - Images cached and resized
204
+ - No main thread blocking
205
+
206
+ ## Security (non-negotiable)
207
+ - Tokens → SecureStore / Keychain / EncryptedSharedPreferences
208
+ - API calls → HTTPS only
209
+ - Sensitive data → never in logs
210
+ - User input → sanitize before display
211
+ - Deep links → validate before navigation
212
+
213
+ ## Never
214
+ - Change framework or architecture
215
+ - Change state management library
216
+ - Add packages without checking SDK compatibility
217
+ - Mix package managers
218
+ - Use ScrollView for long lists
219
+ - Leave empty catch blocks
220
+ - Store tokens in AsyncStorage / SharedPreferences / UserDefaults
221
+
222
+ ## Architecture
223
+ - Dependencies flow inward: UI → Domain → Data
224
+ - Single responsibility per file (max 300 lines)
225
+ - Feature-based organization preferred
226
+
227
+ ## Reference
228
+ - Full skill: ~/.cursor/skills/skill-mobile-mt/
229
+ - Patterns from 30+ production repos (200k+ GitHub stars)
230
+ `,
231
+ },
232
+
233
+ copilot: {
234
+ name: 'GitHub Copilot',
235
+ file: 'copilot-instructions.md',
236
+ dir: '.github',
237
+ generate: (p) => `# Copilot Instructions — ${p.framework} Project
238
+
239
+ > Generated by @buivietphi/skill-mobile-mt
240
+
241
+ ## Project Context
242
+ - **Framework:** ${p.framework}
243
+ - **Language:** ${p.language}
244
+ - **State Management:** ${p.state}
245
+ - **Navigation:** ${p.nav}
246
+ - **API:** ${p.api}
247
+ - **Package Manager:** ${p.pkgMgr}
248
+
249
+ ## Conventions
250
+ - PascalCase: components, screens, classes
251
+ - camelCase: hooks, services, utilities, variables
252
+ - Files named same as their default export
253
+
254
+ ## Required Patterns
255
+
256
+ ### Every async function
257
+ \`\`\`typescript
258
+ try {
259
+ setLoading(true);
260
+ const result = await apiCall();
261
+ setData(result);
262
+ } catch (error) {
263
+ setError(error.message);
264
+ } finally {
265
+ setLoading(false);
266
+ }
267
+ \`\`\`
268
+
269
+ ### Every screen must handle 4 states
270
+ \`\`\`typescript
271
+ if (loading) return <LoadingScreen />;
272
+ if (error) return <ErrorScreen error={error} />;
273
+ if (!data?.length) return <EmptyScreen />;
274
+ return <DataScreen data={data} />;
275
+ \`\`\`
276
+
277
+ ### Every useEffect with subscriptions
278
+ \`\`\`typescript
279
+ useEffect(() => {
280
+ const sub = subscribe();
281
+ return () => sub.unsubscribe(); // REQUIRED
282
+ }, []);
283
+ \`\`\`
284
+
285
+ ## Rules
286
+ - No console.log / print in production
287
+ - No hardcoded secrets or API keys
288
+ - FlatList (not ScrollView) for dynamic lists
289
+ - Tokens in SecureStore / Keychain only
290
+ - No force unwrap (! / !!) without null check
291
+ - No implicit 'any' in TypeScript
292
+ - No empty catch blocks
293
+ - No inline functions in render/build
294
+ - Images cached and resized
295
+ - New screens registered in navigator
296
+
297
+ ## Security
298
+ - Tokens → SecureStore / Keychain / EncryptedSharedPreferences
299
+ - API calls → HTTPS only
300
+ - Sensitive data → never in logs
301
+ - User input → sanitize before rendering
302
+ - Deep links → validate before navigation
303
+
304
+ ## Never
305
+ - Suggest migrating to a different framework
306
+ - Change state management library
307
+ - Add packages without checking SDK compatibility
308
+ - Mix package managers (yarn + npm)
309
+ - Use ScrollView for lists > 20 items
310
+ - Store tokens in AsyncStorage / SharedPreferences / UserDefaults
311
+
312
+ ## Architecture
313
+ - Clean Architecture: UI → Domain → Data
314
+ - Single responsibility per file (max 300 lines)
315
+ - Feature-based organization preferred
316
+
317
+ ## Reference
318
+ Full skill with patterns from 30+ production repos: ~/.copilot/skills/skill-mobile-mt/
319
+ `,
320
+ },
321
+
322
+ windsurf: {
323
+ name: 'Windsurf',
324
+ file: '.windsurfrules',
325
+ dir: '.',
326
+ generate: (p) => `# ${p.framework} Project — Windsurf Rules
327
+ # Generated by @buivietphi/skill-mobile-mt
328
+
329
+ Project: ${p.framework}
330
+ Language: ${p.language}
331
+ State management: ${p.state}
332
+ Navigation: ${p.nav}
333
+ API: ${p.api}
334
+ Package manager: ${p.pkgMgr}
335
+
336
+ ## Coding Rules
337
+
338
+ Always:
339
+ - Wrap all async operations in try/catch
340
+ - Handle all 4 states: loading, error, empty, success
341
+ - Add cleanup to useEffect (return () => ...)
342
+ - Use FlatList for dynamic lists (not ScrollView)
343
+ - Use PascalCase for components and screens
344
+ - Use camelCase for hooks, services, and utilities
345
+ - No implicit 'any' in TypeScript
346
+ - No force unwrap (! / !!) without null check
347
+ - New screens registered in navigator
348
+ - React.memo / const widget for expensive components
349
+ - Images cached and resized
350
+
351
+ Never:
352
+ - Leave console.log / print in production code
353
+ - Hardcode secrets, tokens, or API keys
354
+ - Store tokens in AsyncStorage / SharedPreferences / UserDefaults
355
+ - Change the framework or architecture
356
+ - Change state management library
357
+ - Add packages without verifying SDK compatibility
358
+ - Mix yarn and npm
359
+ - Use ScrollView for lists > 20 items
360
+ - Leave empty catch blocks
361
+ - Use index as list key
362
+
363
+ ## Security (non-negotiable)
364
+ - Tokens → SecureStore / Keychain / EncryptedSharedPreferences
365
+ - API calls → HTTPS only
366
+ - Sensitive data → never in logs
367
+ - User input → sanitize before display
368
+ - Deep links → validate before navigation
369
+
370
+ ## Architecture
371
+ - Clean Architecture: UI → Domain → Data
372
+ - Single responsibility per file (max 300 lines)
373
+ - Feature-based organization preferred
374
+
375
+ ## Reference
376
+ Full skill: ~/.windsurf/skills/skill-mobile-mt/
377
+ Patterns from 30+ production repos (200k+ GitHub stars)
378
+ `,
379
+ },
380
+ };
381
+
382
+ // Agents that need project-level files (don't just read from skills dir)
383
+ const NEEDS_PROJECT_FILE = new Set(['cursor', 'copilot', 'windsurf']);
384
+
385
+ function initProjectFiles(dir, agents) {
386
+ const project = detectProject(dir);
387
+ let created = 0;
388
+
389
+ for (const key of agents) {
390
+ const agent = PROJECT_AGENTS[key];
391
+ if (!agent) continue;
392
+
393
+ const targetDir = join(dir, agent.dir);
394
+ const targetFile = join(targetDir, agent.file);
395
+
396
+ if (existsSync(targetFile)) {
397
+ info(`${c.yellow}${agent.file}${c.reset} already exists — skipped (won't overwrite)`);
398
+ continue;
399
+ }
400
+
401
+ mkdirSync(targetDir, { recursive: true });
402
+ writeFileSync(targetFile, agent.generate(project), 'utf-8');
403
+ ok(`${c.bold}${join(agent.dir, agent.file)}${c.reset} → ${agent.name} ${c.dim}(auto-detected: ${project.framework})${c.reset}`);
404
+ created++;
405
+ }
406
+
407
+ return created;
408
+ }
409
+
410
+ async function selectProjectAgents() {
411
+ if (!process.stdin.isTTY) return Object.keys(PROJECT_AGENTS);
412
+
413
+ const keys = Object.keys(PROJECT_AGENTS);
414
+ const selected = new Set(keys); // all selected by default
415
+ let cursor = 0;
416
+
417
+ const UP = '\x1b[A';
418
+ const DOWN = '\x1b[B';
419
+ const ERASE_DN = '\x1b[J';
420
+ const HIDE_CUR = '\x1b[?25l';
421
+ const SHOW_CUR = '\x1b[?25h';
422
+ const moveUp = n => `\x1b[${n}A`;
423
+ const TOTAL_LINES = 3 + keys.length;
424
+
425
+ function render(first) {
426
+ if (!first) process.stdout.write(moveUp(TOTAL_LINES) + ERASE_DN);
427
+ process.stdout.write(`\n${c.bold} Select project-level files to generate:${c.reset}\n`);
428
+ process.stdout.write(` ${c.dim}↑↓ navigate Space toggle A select all Enter confirm Q cancel${c.reset}\n`);
429
+
430
+ for (let i = 0; i < keys.length; i++) {
431
+ const k = keys[i];
432
+ const agent = PROJECT_AGENTS[k];
433
+ const isCur = i === cursor;
434
+ const isSel = selected.has(k);
435
+
436
+ const ptr = isCur ? `${c.cyan}›${c.reset}` : ' ';
437
+ const box = isSel ? `${c.green}◉${c.reset}` : `${c.dim}◯${c.reset}`;
438
+ const name = isCur ? `${c.bold}${c.cyan}${agent.name}${c.reset}` : agent.name;
439
+ const file = `${c.dim}→ ${join(agent.dir, agent.file)}${c.reset}`;
440
+
441
+ process.stdout.write(` ${ptr} ${box} ${name.padEnd(20)}${file}\n`);
442
+ }
443
+ }
444
+
445
+ process.stdout.write(HIDE_CUR);
446
+ render(true);
447
+
448
+ return new Promise(resolve => {
449
+ process.stdin.setRawMode(true);
450
+ process.stdin.resume();
451
+ process.stdin.setEncoding('utf8');
452
+
453
+ const onKey = key => {
454
+ const done = result => {
455
+ process.stdin.setRawMode(false);
456
+ process.stdin.pause();
457
+ process.stdin.off('data', onKey);
458
+ process.stdout.write(SHOW_CUR + '\n');
459
+ resolve(result);
460
+ };
461
+
462
+ if (key === '\x03') { done(null); process.exit(0); }
463
+ if (key === 'q' || key === 'Q' || key === '\x1b') { done([]); return; }
464
+ if (key === '\r' || key === '\n') { done([...selected]); return; }
465
+
466
+ if (key === UP) cursor = (cursor - 1 + keys.length) % keys.length;
467
+ else if (key === DOWN) cursor = (cursor + 1) % keys.length;
468
+ else if (key === ' ') {
469
+ if (selected.has(keys[cursor])) selected.delete(keys[cursor]);
470
+ else selected.add(keys[cursor]);
471
+ } else if (key === 'a' || key === 'A') {
472
+ if (selected.size === keys.length) selected.clear();
473
+ else keys.forEach(k => selected.add(k));
474
+ }
475
+
476
+ render(false);
477
+ };
478
+
479
+ process.stdin.on('data', onKey);
480
+ });
481
+ }
482
+
116
483
  // ─── Checkbox UI ─────────────────────────────────────────────────────────────
117
484
 
118
485
  async function selectAgents(detected) {
@@ -201,6 +568,56 @@ async function main() {
201
568
  const flags = new Set(args.map(a => a.replace(/^--?/, '')));
202
569
 
203
570
  banner();
571
+
572
+ // ─── --init mode: generate project-level files ─────────────────────────────
573
+ if (flags.has('init')) {
574
+ const cwd = process.cwd();
575
+ log(`${c.bold} 📁 Project directory:${c.reset} ${c.dim}${cwd}${c.reset}`);
576
+
577
+ const project = detectProject(cwd);
578
+ log(`${c.bold} 🔍 Detected:${c.reset} ${c.cyan}${project.framework}${c.reset} (${project.language})\n`);
579
+
580
+ // Determine which agents to init
581
+ let initTargets = [];
582
+ const initIdx = args.indexOf('--init');
583
+ const initArg = args[initIdx + 1];
584
+
585
+ if (initArg === 'all') {
586
+ initTargets = Object.keys(PROJECT_AGENTS);
587
+ } else if (initArg && PROJECT_AGENTS[initArg]) {
588
+ initTargets = [initArg];
589
+ } else if (initArg && !initArg.startsWith('-')) {
590
+ fail(`Unknown agent: ${initArg}. Available: ${Object.keys(PROJECT_AGENTS).join(', ')}, all`);
591
+ process.exit(1);
592
+ } else {
593
+ // Interactive selection
594
+ const chosen = await selectProjectAgents();
595
+ if (!chosen || chosen.length === 0) { info('Cancelled.'); return; }
596
+ initTargets = chosen;
597
+ }
598
+
599
+ log(`\n${c.bold} Generating project-level rules...${c.reset}\n`);
600
+ const n = initProjectFiles(cwd, initTargets);
601
+
602
+ if (n > 0) {
603
+ log(`\n${c.green}${c.bold} ✅ Done!${c.reset} → ${n} file(s) generated\n`);
604
+ log(` ${c.bold}Generated files:${c.reset}`);
605
+ for (const k of initTargets) {
606
+ const agent = PROJECT_AGENTS[k];
607
+ if (agent) {
608
+ const fp = join(agent.dir, agent.file);
609
+ log(` ${c.green}●${c.reset} ${agent.name.padEnd(18)} ${c.dim}${fp}${c.reset}`);
610
+ }
611
+ }
612
+ log(`\n ${c.dim}Files are auto-detected for ${project.framework}.`);
613
+ log(` Edit the generated files to customize for your project.${c.reset}\n`);
614
+ } else {
615
+ info('No files generated (all already exist).\n');
616
+ }
617
+ return;
618
+ }
619
+
620
+ // ─── Normal install mode ───────────────────────────────────────────────────
204
621
  showContext();
205
622
 
206
623
  let targets = [];
@@ -237,13 +654,28 @@ async function main() {
237
654
 
238
655
  log(`\n${c.green}${c.bold} ✅ Done!${c.reset} → ${targets.length} agent(s)\n`);
239
656
  log(` ${c.bold}Usage:${c.reset}`);
240
- log(` ${c.cyan}@skill-mobile-mt${c.reset} Pre-built patterns (18 production apps)`);
657
+ log(` ${c.cyan}@skill-mobile-mt${c.reset} Pre-built patterns (30+ production repos)`);
241
658
  log(` ${c.cyan}@skill-mobile-mt project${c.reset} Read current project, adapt to it\n`);
242
659
  log(` ${c.bold}Installed to:${c.reset}`);
243
660
  for (const k of targets) {
244
661
  log(` ${c.green}●${c.reset} ${AGENTS[k].name.padEnd(14)} ${c.dim}${AGENTS[k].dir}/${SKILL_NAME}${c.reset}`);
245
662
  }
246
- log('');
663
+
664
+ // Show tip for agents that need project-level files
665
+ const needsInit = targets.filter(k => NEEDS_PROJECT_FILE.has(k));
666
+ if (needsInit.length > 0) {
667
+ const names = needsInit.map(k => AGENTS[k].name).join(', ');
668
+ log('');
669
+ log(` ${c.yellow}${c.bold}💡 Important:${c.reset} ${names} read rules from ${c.bold}project-level files${c.reset},`);
670
+ log(` not from the skills directory. Run this in your project root:`);
671
+ log('');
672
+ log(` ${c.cyan}npx @buivietphi/skill-mobile-mt --init${c.reset}`);
673
+ log('');
674
+ log(` This generates ${c.bold}.cursorrules${c.reset}, ${c.bold}.windsurfrules${c.reset}, ${c.bold}.github/copilot-instructions.md${c.reset}`);
675
+ log(` with auto-detected project settings.\n`);
676
+ } else {
677
+ log('');
678
+ }
247
679
  }
248
680
 
249
681
  main().catch(e => { fail(e.message); process.exit(1); });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buivietphi/skill-mobile-mt",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Master Senior Mobile Engineer skill for AI agents. Pre-built patterns from 18 production apps + local project adaptation. React Native, Flutter, iOS, Android. Supports Claude, Gemini, Kimi, Cursor, Copilot, Antigravity.",
5
5
  "author": "buivietphi",
6
6
  "license": "MIT",
@@ -38,7 +38,12 @@
38
38
  "install:claude": "node bin/install.mjs --claude",
39
39
  "install:gemini": "node bin/install.mjs --gemini",
40
40
  "install:kimi": "node bin/install.mjs --kimi",
41
- "install:all": "node bin/install.mjs --all"
41
+ "install:all": "node bin/install.mjs --all",
42
+ "init": "node bin/install.mjs --init",
43
+ "init:cursor": "node bin/install.mjs --init cursor",
44
+ "init:copilot": "node bin/install.mjs --init copilot",
45
+ "init:windsurf": "node bin/install.mjs --init windsurf",
46
+ "init:all": "node bin/install.mjs --init all"
42
47
  },
43
48
  "engines": {
44
49
  "node": ">=18"