一键导入
add-screen
Add a new screen to an existing feature module with Store, UI, factories, and tests
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Add a new screen to an existing feature module with Store, UI, factories, and tests
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | add-screen |
| description | Add a new screen to an existing feature module with Store, UI, factories, and tests |
| disable-model-invocation | true |
| argument-hint | <feature-name> <ScreenName> |
Add a new screen to an existing feature module. This scaffolds the Screen, State, Event, Store, UI, and Factory within the feature's directory.
Input: $ARGUMENTS
Extract the feature name and screen name from the input.
Verify the feature directory exists at <AppTarget>/<FeatureName>/. If the feature doesn't exist, suggest running /add-feature first.
Read the existing screen files in the feature module to match:
Also read existing screens from other features if the current feature has no prior screens.
Ask the user:
TrapezioScreen struct)TrapezioNavigator injection?TrapezioInterop injection?Place at: <AppTarget>/<FeatureName>/<ScreenName>Screen.swift
import Trapezio
struct <ScreenName>Screen: TrapezioScreen {
// navigation arguments as properties (must be Hashable & Codable)
}
struct <ScreenName>State: TrapezioState {
// display properties — value types only, must be Equatable
}
enum <ScreenName>Event: TrapezioEvent {
// user intents
}
Place at: <AppTarget>/<FeatureName>/<ScreenName>Store.swift
import Foundation
import Trapezio
import TrapezioNavigation
import Strata
@MainActor
final class <ScreenName>Store: TrapezioStore<<ScreenName>Screen, <ScreenName>State, <ScreenName>Event> {
private let navigator: (any TrapezioNavigator)?
// injected dependencies
init(
screen: <ScreenName>Screen,
navigator: (any TrapezioNavigator)?
// additional dependencies
) {
self.navigator = navigator
super.init(screen: screen, initialState: <ScreenName>State(/* initial values */))
setupBindings()
}
private func setupBindings() {
// strataCollect streams here
}
override func handle(event: <ScreenName>Event) {
switch event {
// handle events
}
}
}
Place at: <AppTarget>/<FeatureName>/<ScreenName>Ui.swift
import SwiftUI
import Trapezio
struct <ScreenName>UI: TrapezioUI {
func map(state: <ScreenName>State, onEvent: @escaping @MainActor (<ScreenName>Event) -> Void) -> some View {
// stateless composable — no @State, @StateObject, or side effects
}
}
Place at: <AppTarget>/<FeatureName>/<ScreenName>Factory.swift
import SwiftUI
import Trapezio
import TrapezioNavigation
struct <ScreenName>Factory {
@ViewBuilder @MainActor
static func make(screen: <ScreenName>Screen, navigator: (any TrapezioNavigator)?, interop: (any TrapezioInterop)?) -> some View {
// assemble dependencies
TrapezioContainer(
makeStore: <ScreenName>Store(
screen: screen,
navigator: navigator
// pass dependencies
),
ui: <ScreenName>UI()
)
}
}
Add the screen to the ContentView builder closure:
case let <name> as <ScreenName>Screen:
<ScreenName>Factory.make(screen: <name>, navigator: navigator, interop: interop)
Automatically generate test files following the conventions from the /add-tests skill:
For Counter app (XCTest):
import XCTest
import Trapezio
import TrapezioNavigation
@testable import <AppTarget>
@MainActor
final class <ScreenName>StoreTests: XCTestCase {
var store: <ScreenName>Store!
override func setUp() {
super.setUp()
let screen = <ScreenName>Screen(/* params */)
store = <ScreenName>Store(
screen: screen,
/* inject fakes */
navigator: nil
)
}
func test_initialState_isCorrect() {
// assert initial state
}
}
For MESA library (Swift Testing) — use TrapezioTest utilities when testing navigation:
import Foundation
import Testing
import TrapezioTest
@testable import <Target>
@Suite("<ScreenName>Store")
struct <ScreenName>StoreTests {
@Test("initial state is correct")
@MainActor func initialState() {
let store = <ScreenName>Store(
screen: <ScreenName>Screen(/* params */),
navigator: nil
)
#expect(store.state == <ScreenName>State(/* expected */))
}
// Use FakeTrapezioNavigator to assert navigation:
// let nav = FakeTrapezioNavigator()
// store.handle(event: .someNavEvent)
// #expect(nav.navigatedScreens.count == 1)
}
All generated files MUST include the Apache 2.0 license header:
/*
* Copyright 2026 Jason Jamieson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Run cd MESA && swift build to verify compilation.
Report:
Then ask:
/add-interactor <feature-name> <InteractorName>Add missing test cases, targeting a specific file or all changed files on the branch
Thorough pre-merge audit — dependency graph, correctness, conventions, security, test coverage, and improvement suggestions
Quick review of the current diff for bugs, logic errors, convention violations, and test gaps
Scaffold a new feature module with the appropriate layers and MESA conventions
Scaffold a new Strata interactor with interface, implementation, fake, and test
Bump library version in VERSION file and prepare release notes