scaffold_ios_project
Generate a modern iOS project with Xcode workspace structure, SPM package for features, and proper iOS configuration, including bundle identifier, deployment target, and device orientation settings.
Instructions
Scaffold a new iOS project from templates. Creates a modern Xcode project with workspace structure, SPM package for features, and proper iOS configuration.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| bundleIdentifier | No | Bundle identifier (e.g., com.example.myapp). If not provided, will use com.example.projectname | |
| currentProjectVersion | No | Build number (e.g., 1, 42, 100). If not provided, will use 1 | |
| customizeNames | No | Whether to customize project names and identifiers. Default is true. | |
| deploymentTarget | No | iOS deployment target (e.g., 18.4, 17.0). If not provided, will use 18.4 | |
| displayName | No | App display name (shown on home screen/dock). If not provided, will use projectName | |
| marketingVersion | No | Marketing version (e.g., 1.0, 2.1.3). If not provided, will use 1.0 | |
| outputPath | Yes | Path where the project should be created | |
| projectName | Yes | Name of the new project | |
| supportedOrientations | No | Supported orientations for iPhone | |
| supportedOrientationsIpad | No | Supported orientations for iPad | |
| targetedDeviceFamily | No | Targeted device families |
Implementation Reference
- Zod schema definitions for the tool parameters, including base schema extended for iOS-specific fields.// Common base schema for both iOS and macOS const BaseScaffoldSchema = z.object({ projectName: z.string().min(1).describe('Name of the new project'), outputPath: z.string().describe('Path where the project should be created'), bundleIdentifier: z .string() .optional() .describe( 'Bundle identifier (e.g., com.example.myapp). If not provided, will use com.example.projectname', ), displayName: z .string() .optional() .describe( 'App display name (shown on home screen/dock). If not provided, will use projectName', ), marketingVersion: z .string() .optional() .describe('Marketing version (e.g., 1.0, 2.1.3). If not provided, will use 1.0'), currentProjectVersion: z .string() .optional() .describe('Build number (e.g., 1, 42, 100). If not provided, will use 1'), customizeNames: z .boolean() .default(true) .describe('Whether to customize project names and identifiers. Default is true.'), }); // iOS-specific schema const ScaffoldiOSProjectSchema = BaseScaffoldSchema.extend({ deploymentTarget: z .string() .optional() .describe('iOS deployment target (e.g., 18.4, 17.0). If not provided, will use 18.4'), targetedDeviceFamily: z .array(z.enum(['iphone', 'ipad', 'universal'])) .optional() .describe('Targeted device families'), supportedOrientations: z .array(z.enum(['portrait', 'landscape-left', 'landscape-right', 'portrait-upside-down'])) .optional() .describe('Supported orientations for iPhone'), supportedOrientationsIpad: z .array(z.enum(['portrait', 'landscape-left', 'landscape-right', 'portrait-upside-down'])) .optional() .describe('Supported orientations for iPad'), });
- Core handler function that orchestrates iOS project scaffolding, handles errors, and returns the response.export async function scaffold_ios_projectLogic( params: ScaffoldIOSProjectParams, commandExecutor: CommandExecutor, fileSystemExecutor: FileSystemExecutor, ): Promise<ToolResponse> { try { const projectParams = { ...params, platform: 'iOS' }; const projectPath = await scaffoldProject(projectParams, commandExecutor, fileSystemExecutor); const response = { success: true, projectPath, platform: 'iOS', message: `Successfully scaffolded iOS project "${params.projectName}" in ${projectPath}`, nextSteps: [ `Important: Before working on the project make sure to read the README.md file in the workspace root directory.`, `Build for simulator: build_sim({ workspacePath: "${projectPath}/${params.customizeNames ? params.projectName : 'MyProject'}.xcworkspace", scheme: "${params.customizeNames ? params.projectName : 'MyProject'}", simulatorName: "iPhone 16" })`, `Build and run on simulator: build_run_sim({ workspacePath: "${projectPath}/${params.customizeNames ? params.projectName : 'MyProject'}.xcworkspace", scheme: "${params.customizeNames ? params.projectName : 'MyProject'}", simulatorName: "iPhone 16" })`, ], }; return { content: [ { type: 'text', text: JSON.stringify(response, null, 2), }, ], }; } catch (error) { log( 'error', `Failed to scaffold iOS project: ${error instanceof Error ? error.message : String(error)}`, ); return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', }, null, 2, ), }, ], isError: true, }; } }
- Tool registration exporting the tool object with name, description, schema, and a thin handler that parses args and calls the core logic.export default { name: 'scaffold_ios_project', description: 'Scaffold a new iOS project from templates. Creates a modern Xcode project with workspace structure, SPM package for features, and proper iOS configuration.', schema: ScaffoldiOSProjectSchema.shape, async handler(args: Record<string, unknown>): Promise<ToolResponse> { const params = ScaffoldiOSProjectSchema.parse(args); return scaffold_ios_projectLogic( params, getDefaultCommandExecutor(), getDefaultFileSystemExecutor(), ); }, };
- Key helper function that handles template retrieval, project validation, and recursive directory processing for scaffolding.async function scaffoldProject( params: Record<string, unknown>, commandExecutor?: CommandExecutor, fileSystemExecutor: FileSystemExecutor = getDefaultFileSystemExecutor(), ): Promise<string> { const projectName = params.projectName as string; const outputPath = params.outputPath as string; const platform = params.platform as 'iOS' | 'macOS'; const customizeNames = (params.customizeNames as boolean | undefined) ?? true; log('info', `Scaffolding project: ${projectName} (${platform}) at ${outputPath}`); // Validate project name if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(projectName)) { throw new ValidationError( 'Project name must start with a letter and contain only letters, numbers, and underscores', ); } // Get template path from TemplateManager let templatePath; try { // Use the default command executor if not provided commandExecutor ??= getDefaultCommandExecutor(); templatePath = await TemplateManager.getTemplatePath( platform, commandExecutor, fileSystemExecutor, ); } catch (error) { throw new ValidationError( `Failed to get template for ${platform}: ${error instanceof Error ? error.message : String(error)}`, ); } // Use outputPath directly as the destination const projectPath = outputPath; // Check if the output directory already has Xcode project files const xcworkspaceExists = fileSystemExecutor.existsSync( join(projectPath, `${customizeNames ? projectName : 'MyProject'}.xcworkspace`), ); const xcodeprojExists = fileSystemExecutor.existsSync( join(projectPath, `${customizeNames ? projectName : 'MyProject'}.xcodeproj`), ); if (xcworkspaceExists || xcodeprojExists) { throw new ValidationError(`Xcode project files already exist in ${projectPath}`); } try { // Process the template directly into the output path await processDirectory(templatePath, projectPath, params, fileSystemExecutor); return projectPath; } finally { // Clean up downloaded template if needed await TemplateManager.cleanup(templatePath, fileSystemExecutor); } }