Awesome-omni-skill feature
Creates a new feature module with minimal viable structure. Use when bootstrapping a new feature from scratch, scaffolding the Tuist module, Container, Feature entry point, DeepLinkHandler, and initial screen with placeholder Text view. Includes all unit tests, mocks, stubs, and app integration. For adding domain/data layers afterward, use /datasource, /repository, /usecase. For enhancing views, use /view, /viewmodel, /navigator.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data-ai/feature" ~/.claude/skills/diegosouzapw-awesome-omni-skill-feature && rm -rf "$T"
skills/data-ai/feature/SKILL.mdSkill: Feature
Create a new feature module with the minimum viable structure: Tuist module, Feature entry point, Container, DeepLinkHandler, and one screen with placeholder
Text. Integrates into the app.
Parameters
Gather from user before starting:
| Parameter | Format | Example |
|---|---|---|
| Feature | PascalCase | |
| Screen | PascalCase | |
| Deep link host | lowercase | |
| Deep link path segment | lowercase, no slash | |
Derived: module name =
Challenge{Feature}, event prefix = snake_case of Screen.
File Structure
Features/{Feature}/ ├── Sources/ │ ├── {Feature}Feature.swift │ ├── {Feature}Container.swift │ └── Presentation/ │ ├── Navigation/ │ │ ├── {Feature}IncomingNavigation.swift │ │ └── {Feature}DeepLinkHandler.swift │ └── {Screen}/ │ ├── Navigator/ │ │ ├── {Screen}NavigatorContract.swift │ │ └── {Screen}Navigator.swift │ ├── Tracker/ │ │ ├── {Screen}TrackerContract.swift │ │ ├── {Screen}Tracker.swift │ │ └── {Screen}Event.swift │ ├── ViewModels/ │ │ ├── {Screen}ViewModelContract.swift │ │ └── {Screen}ViewModel.swift │ └── Views/ │ └── {Screen}View.swift └── Tests/ ├── Unit/ │ ├── Feature/ │ │ └── {Feature}FeatureTests.swift │ └── Presentation/ │ ├── Navigation/ │ │ └── {Feature}DeepLinkHandlerTests.swift │ └── {Screen}/ │ ├── Navigator/ │ │ └── {Screen}NavigatorTests.swift │ ├── Tracker/ │ │ ├── {Screen}TrackerTests.swift │ │ └── {Screen}EventTests.swift │ └── ViewModels/ │ └── {Screen}ViewModelTests.swift └── Shared/ ├── Mocks/ │ ├── {Screen}NavigatorMock.swift │ └── {Screen}TrackerMock.swift └── Stubs/ └── {Screen}ViewModelStub.swift
Conventions
- No
on minimal ViewModels (no observable state). Only add when ViewModel has@Observable
.private(set) var - No
keyword on internal protocol types. Only on public protocols from other modules (e.g.,any
in Container).any TrackerContract - No imports in ViewModel when all types are internal to the module.
- Deep link paths are scoped per host —
under/list
host is independent fromepisode
under/list
host.character - Deep links use path-based URLs — parameters are embedded in the path (e.g.,
), never as query items (challenge://character/detail/42
). Use?id=42
for parsing.url.pathComponents - Tuist module uses
string interpolation for target names.\(appName) - Features always receive
as their network dependency — never specific clients likeHTTPClientContract
. The Container is responsible for creating specific clients (e.g.,GraphQLClientContract
) internally from theGraphQLClient
. This keeps features decoupled from transport details.HTTPClientContract - Features that don't need networking only receive
.tracker: any TrackerContract - Features that need networking receive
.httpClient: any HTTPClientContract, tracker: any TrackerContract
Workflow
Step 1: Tuist Module
Create
Tuist/ProjectDescriptionHelpers/Modules/{Feature}Module.swift:
import ProjectDescription public let {feature}Module = Module.create(directory: "Features/{Feature}")
Register the module in
— Add Modules.swift
{feature}Module to the Modules.all array. This single registration automatically includes the module's package in the root project and its test target in the Challenge.xctestplan.
Step 2: Source Files
Create all source files from sources.md.
Order: IncomingNavigation → DeepLinkHandler → NavigatorContract → Navigator → TrackerContract → Tracker → Event → ViewModelContract → ViewModel → View → Container → Feature.
Step 3: Test Files
Create all test files from tests.md.
Order: Mocks → Stubs → Unit tests.
Step 4: App Integration
Wire the feature into the app — 4 files to modify:
— Add dependency:Tuist/ProjectDescriptionHelpers/Modules/AppKitModule.swift
{feature}Module.targetDependency,
— Three changes:AppKit/Sources/AppContainer.swift
- Add import:
import Challenge{Feature} - Add property:
private let {feature}Feature: {Feature}Feature - Initialize in
:init- Without networking:
{feature}Feature = {Feature}Feature(tracker: self.tracker) - With networking:
{feature}Feature = {Feature}Feature(httpClient: self.httpClient, tracker: self.tracker)
- Without networking:
- Add to
arrayfeatures
— No changes needed (AppKit/Tests/Unit/AppContainerTests.swift
features is private, tested indirectly).
Step 5: Verify
xcodebuild test \ -workspace Challenge.xcworkspace \ -scheme "Challenge (Dev)" \ -testPlan Challenge \ -destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=latest'
Extending the Feature
| Need | Skill |
|---|---|
| REST API data source | |
| Repository + DTO mapping | |
| Business logic | |
| Enhance ViewModel with state | |
| Enhance View with design system | |
| Add more navigation | |
| Snapshot tests | |
| UI tests | |