/harmonyos-app
HarmonyOS application development expert. Use when building HarmonyOS apps with ArkTS, ArkUI, Stage model, and distributed capabilities. Covers HarmonyOS NEXT (API 12+) best practices.
$ npx -y skills add majiayu000/spellbook --skill harmonyos-app --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/harmonyos-app
Context preview
The summary Claude sees to decide when to auto-load this skill.
HarmonyOS application development expert. Use when building HarmonyOS apps with ArkTS, ArkUI, Stage model, and distributed capabilities. Covers HarmonyOS NEXT (API 12+) best practices.
SKILL.md
harmonyos-app.SKILL.mdname: harmonyos-app
description: HarmonyOS application development expert. Use when building HarmonyOS apps with ArkTS, ArkUI, Stage model, and distributed capabilities. Covers HarmonyOS NEXT (API 12+) best practices.
HarmonyOS Application Development
Core Principles
- **ArkTS First** — Use ArkTS with strict type safety, no `any` or dynamic types
- **Declarative UI** — Build UI with ArkUI's declarative components and state management
- **Stage Model** — Use modern Stage model (UIAbility), not legacy FA model
- **Distributed by Design** — Leverage cross-device capabilities from the start
- **Atomic Services** — Consider atomic services and cards for lightweight experiences
- **One-time Development** — Design for multi-device adaptation (phone, tablet, watch, TV)
---
Hard Rules (Must Follow)
> These rules are mandatory. Violating them means the skill is not working correctly.
No Dynamic Types
**ArkTS prohibits dynamic typing. Never use `any`, type assertions, or dynamic property access.**
// ❌ FORBIDDEN: Dynamic types
let data: any = fetchData();
let obj: object = {};
obj['dynamicKey'] = value; // Dynamic property access
(someVar as SomeType).method(); // Type assertion
// ✅ REQUIRED: Strict typing
interface UserData {
id: string;
name: string;
}
let data: UserData = fetchData();
// Use Record for dynamic keys
let obj: Record<string, string> = {};
obj['key'] = value; // OK with Record typeNo Direct State Mutation
**Never mutate @State/@Prop variables directly in nested objects. Use immutable updates.**
// ❌ FORBIDDEN: Direct mutation
@State user: User = { name: 'John', age: 25 };
updateAge() {
this.user.age = 26; // UI won't update!
}
// ✅ REQUIRED: Immutable update
updateAge() {
this.user = { ...this.user, age: 26 }; // Creates new object, triggers UI update
}
// For arrays
@State items: string[] = ['a', 'b'];
// ❌ FORBIDDEN
this.items.push('c'); // UI won't update
// ✅ REQUIRED
this.items = [...this.items, 'c'];Stage Model Only
**Always use Stage model (UIAbility). Never use deprecated FA model (PageAbility).**
// ❌ FORBIDDEN: FA Model (deprecated)
// config.json with "pages" array
export default {
onCreate() { ... } // PageAbility lifecycle
}
// ✅ REQUIRED: Stage Model
// module.json5 with abilities configuration
import { UIAbility } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// Modern Stage model lifecycle
}
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index');
}
}Component Reusability
**Extract reusable UI into @Component. No inline complex UI in build() methods.**
// ❌ FORBIDDEN: Monolithic build method
@Entry
@Component
struct MainPage {
build() {
Column() {
// 200+ lines of inline UI...
Row() {
Image($r('app.media.avatar'))
Column() {
Text(this.user.name)
Text(this.user.email)
}
}
// More inline UI...
}
}
}
// ✅ REQUIRED: Extract components
@Component
struct UserCard {
@Prop user: User;
build() {
Row() {
Image($r('app.media.avatar'))
Column() {
Text(this.user.name)
Text(this.user.email)
}
}
}
}
@Entry
@Component
struct MainPage {
@State user: User = { name: 'John', email: 'john@example.com' };
build() {
Column() {
UserCard({ user: this.user })
}
}
}---
Quick Reference
When to Use What
| Scenario | Pattern | Example | |----------|---------|---------| | Component-local state | @State | Counter, form inputs | | Parent-to-child data | @Prop | Read-only child data | | Two-way binding | @Link | Shared mutable state | | Cross-component state | @Provide/@Consume | Theme, user context | | Persistent state | PersistentStorage | User preferences | | App-wide state | AppStorage | Global state | | Complex state logic | @Observed/@ObjectLink | Nested object updates |
State Decorator Selection
@State → Component owns the state, triggers re-render on change
@Prop → Parent passes value, child gets copy (one-way)
@Link → Parent passes reference, child can modify (two-way)
@Provide → Ancestor provides value to all descendants
@Consume → Descendant consumes value from ancestor
@StorageLink → Syncs with AppStorage, two-way binding
@StorageProp → Syncs with AppStorage, one-way binding
@Observed → Class decorator for observable objects
@ObjectLink → Links to @Observed object in parent
---
Project Structure
Recommended Architecture
MyApp/
├── entry/ # Main entry module
│ ├── src/main/
│ │ ├── ets/
│ │ │ ├── entryability/ # UIAbility definitions
│ │ │ │ └── EntryAbility.ets
│ │ │ ├── pages/ # Page components
│ │ │ │ ├── Index.ets
│ │ │ │ └── Detail.ets
│ │ │ ├── components/ # Reusable UI components
│ │ │ │ ├── common/ # Common components
│ │ │ │ └── business/ # Business-specific components
│ │ │ ├── viewmodel/ # ViewModels (MVVM)
│ │ │ ├── model/ # Data models
│ │ │ ├── service/ # Business logic services
│ │ │ ├── repository/ # Data access layer
│ │ │ ├── utils/ # Utility functions
│ │ │ └── constants/ # Constants and configs
│ │ ├── resources/ # Resources (strings, images)
│ │ └── module.json5 # Module configuration
│ └── build-profile.json5
├── common/ # Shared library module
│ └── src/main/ets/
├── features/ # Feature modules
│ ├── feature_home/
│ └── feature_profile/
└── build-profile.json5 # Project configuration
Layer Separatio
Read more
name: harmonyos-app description: HarmonyOS application development expert. Use when building HarmonyOS apps with ArkTS, ArkUI, Stage model, and distributed capabilities. Covers HarmonyOS NEXT (API 12+) best practices.
HarmonyOS Application Development
Core Principles
- **ArkTS First** — Use ArkTS with strict type safety, no `any` or dynamic types
- **Declarative UI** — Build UI with ArkUI's declarative components and state management
- **Stage Model** — Use modern Stage model (UIAbility), not legacy FA model
- **Distributed by Design** — Leverage cross-device capabilities from the start
- **Atomic Services** — Consider atomic services and cards for lightweight experiences
- **One-time Development** — Design for multi-device adaptation (phone, tablet, watch, TV)
---
Hard Rules (Must Follow)
> These rules are mandatory. Violating them means the skill is not working correctly.
No Dynamic Types
**ArkTS prohibits dynamic typing. Never use `any`, type assertions, or dynamic property access.**
// ❌ FORBIDDEN: Dynamic types
let data: any = fetchData();
let obj: object = {};
obj['dynamicKey'] = value; // Dynamic property access
(someVar as SomeType).method(); // Type assertion
// ✅ REQUIRED: Strict typing
interface UserData {
id: string;
name: string;
}
let data: UserData = fetchData();
// Use Record for dynamic keys
let obj: Record<string, string> = {};
obj['key'] = value; // OK with Record typeNo Direct State Mutation
**Never mutate @State/@Prop variables directly in nested objects. Use immutable updates.**
// ❌ FORBIDDEN: Direct mutation
@State user: User = { name: 'John', age: 25 };
updateAge() {
this.user.age = 26; // UI won't update!
}
// ✅ REQUIRED: Immutable update
updateAge() {
this.user = { ...this.user, age: 26 }; // Creates new object, triggers UI update
}
// For arrays
@State items: string[] = ['a', 'b'];
// ❌ FORBIDDEN
this.items.push('c'); // UI won't update
// ✅ REQUIRED
this.items = [...this.items, 'c'];Stage Model Only
**Always use Stage model (UIAbility). Never use deprecated FA model (PageAbility).**
// ❌ FORBIDDEN: FA Model (deprecated)
// config.json with "pages" array
export default {
onCreate() { ... } // PageAbility lifecycle
}
// ✅ REQUIRED: Stage Model
// module.json5 with abilities configuration
import { UIAbility } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// Modern Stage model lifecycle
}
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index');
}
}Component Reusability
**Extract reusable UI into @Component. No inline complex UI in build() methods.**
// ❌ FORBIDDEN: Monolithic build method
@Entry
@Component
struct MainPage {
build() {
Column() {
// 200+ lines of inline UI...
Row() {
Image($r('app.media.avatar'))
Column() {
Text(this.user.name)
Text(this.user.email)
}
}
// More inline UI...
}
}
}
// ✅ REQUIRED: Extract components
@Component
struct UserCard {
@Prop user: User;
build() {
Row() {
Image($r('app.media.avatar'))
Column() {
Text(this.user.name)
Text(this.user.email)
}
}
}
}
@Entry
@Component
struct MainPage {
@State user: User = { name: 'John', email: 'john@example.com' };
build() {
Column() {
UserCard({ user: this.user })
}
}
}---
Quick Reference
When to Use What
| Scenario | Pattern | Example | |----------|---------|---------| | Component-local state | @State | Counter, form inputs | | Parent-to-child data | @Prop | Read-only child data | | Two-way binding | @Link | Shared mutable state | | Cross-component state | @Provide/@Consume | Theme, user context | | Persistent state | PersistentStorage | User preferences | | App-wide state | AppStorage | Global state | | Complex state logic | @Observed/@ObjectLink | Nested object updates |
State Decorator Selection
@State → Component owns the state, triggers re-render on change @Prop → Parent passes value, child gets copy (one-way) @Link → Parent passes reference, child can modify (two-way) @Provide → Ancestor provides value to all descendants @Consume → Descendant consumes value from ancestor @StorageLink → Syncs with AppStorage, two-way binding @StorageProp → Syncs with AppStorage, one-way binding @Observed → Class decorator for observable objects @ObjectLink → Links to @Observed object in parent
---
Project Structure
Recommended Architecture
MyApp/ ├── entry/ # Main entry module │ ├── src/main/ │ │ ├── ets/ │ │ │ ├── entryability/ # UIAbility definitions │ │ │ │ └── EntryAbility.ets │ │ │ ├── pages/ # Page components │ │ │ │ ├── Index.ets │ │ │ │ └── Detail.ets │ │ │ ├── components/ # Reusable UI components │ │ │ │ ├── common/ # Common components │ │ │ │ └── business/ # Business-specific components │ │ │ ├── viewmodel/ # ViewModels (MVVM) │ │ │ ├── model/ # Data models │ │ │ ├── service/ # Business logic services │ │ │ ├── repository/ # Data access layer │ │ │ ├── utils/ # Utility functions │ │ │ └── constants/ # Constants and configs │ │ ├── resources/ # Resources (strings, images) │ │ └── module.json5 # Module configuration │ └── build-profile.json5 ├── common/ # Shared library module │ └── src/main/ets/ ├── features/ # Feature modules │ ├── feature_home/ │ └── feature_profile/ └── build-profile.json5 # Project configuration
Layer Separatio
Cross-runtime skills for Claude Code, Codex, and multi-agent workflows.
Repo: majiayu000/spellbook
Other skills on spellbook.
- /agentsmd-optimize
Audit AND optimize a CLAUDE.md / AGENTS.md instruction file — score it against the five high-leverage patterns, flag anti-patterns, then apply approved fixes in place. Use when the user says 优化 CLAUDE.md / 优化 AGENTS.md / optimize my agent doc / 帮我改 claudemd, or after an audit
Open skill - /agentsmd-scaffold
Generate or update repository-specific AGENTS.md instruction files from real repo evidence. Use when asked to create, design, scaffold, split, or improve root or scoped AGENTS.md files for Codex/Claude/agent workflows, especially when a repo needs directory-specific rules,
Open skill - /api-design
REST/GraphQL/gRPC API design best practices. Use when designing APIs, defining contracts, handling versioning. Covers OpenAPI 3.2, GraphQL Federation, gRPC streaming.
Open skill - /app-ui-design
Mobile app UI design expert for iOS and Android. Use when designing app interfaces, creating design systems, ensuring accessibility, or following platform guidelines. Covers Material Design 3, Human Interface Guidelines, color theory, typography, and 2025 trends.
Open skill - /app-user-story-qa
End-to-end app feature inventory and user-story testing workflow with a canonical tracker. Use when the user asks to audit every feature, derive expected behavior from code, test user journeys, or explicitly fix and retest documented UX or logistical defects.
Open skill - /architecture-foundation
Design architecture foundations before implementation. Use when asked to design or refactor architecture, choose Rust/Go crate, package, module, runtime, workflow, or service boundaries, compare mature project architecture, prevent stacked one-off PRs, audit migration debt in
Open skill

