Implement, write code, add a new screen, create a feature, new view, new processor, or wire up a new service in Bitwarden iOS. Use when asked to "implement", "write code", "add screen", "create feature", "new view", "new processor", "add service", or when translating a design doc into actual Swift code.
npx skills add https://github.com/bitwarden/ios --skill implementing-ios-code
Use this skill to implement Bitwarden iOS features following established patterns.
.claude/outputs/plans/<ticket-id>.md. If not, invoke planning-ios-implementation first.Docs/Architecture.md — it is the authoritative source for all patterns. This skill references it, not replaces it.From the plan, identify:
BitwardenShared, AuthenticatorShared, or BitwardenKit?Auth/, Autofill/, Platform/, Tools/, Vault/?See templates.md for file-set skeletons.
Implement from the bottom up:
Data Models (if needed)
Core/<Domain>/Models/Request/ and Response/Core/<Domain>/Models/Enum/switch over that enum (across all layers) rather than appending it — match the surrounding order.Persistence (if needed)
DataStore (add entities to Bitwarden.xcdatamodeld)AppSettingsStore (backed by UserDefaults)KeychainRepositoryStateService. Prefer adding a separate protocol over extending StateService, AppSettingsStore, or KeychainRepository directly, to maintain interface segregation.Services / Repositories
// sourcery: AutoMockableDefault<Name>Service / Default<Name>RepositoryHas<Name> protocoltemplates.md for service skeletonFor new screens, create all required files together (see templates.md):
Services typealiasstruct) holding all view-observable datareceive(_:)perform(_:)StateProcessor subclass, business logic onlystore.binding, store.perform, @ObservedObjectSwiftUI previews:
#Preview macros for new views — the modern default across the codebase. Do not add new PreviewProvider structs. Because the snapshot harness cannot enumerate #Preview macros, such a view's snapshot coverage comes from a test that instantiates the view directly; see the testing-ios-code skill for how to choose between that and iterating PreviewProvider._allPreviews when a view exposes both.New localization keys (BitwardenResources/.../Localizable.strings):
Archive for "Archive", not MoveToArchive or ArchiveTitle.DescriptionLong suffix on a shortened opening phrase. Example: PassphrasesAreOftenEasierToRememberDescriptionLong./* … */ comments describe meaning, placement, or constraints that affect translation — translators are the audience, not internal engineers.After creating a new service/repository:
Has<Name> conformance to ServiceContainer via extensionHas<Name> to the Services typealias of any processor that needs itBefore finishing:
BitwardenSdk for all encryption/decryptionKeychainRepository, not AppSettingsStoreInputValidatorNonLoggableErrorAll new public types and methods require DocC (///) documentation.
Exceptions: protocol property/function implementations (docs live in the protocol), mock classes.
Use pragma marks to organize code. // MARK: - is used to denote different objects in the same file; // MARK: is used to denote different sections within an object.
Run these checks after all code and tests are written, before handing back. Fix every violation found — do not leave warnings for the commit phase.
If new localization strings were added, regenerate first so SwiftGen picks them up:
mint run swiftgen config run --config swiftgen-bwr.yml # BitwardenResources (most common)
# Run the appropriate swiftgen-*.yml if strings landed in a different target
Then run the pre-commit checks:
./Scripts/pre-commit
This runs spell-check, SwiftFormat, and SwiftLint on changed files — the same checks that run at commit time. If violations are reported, fix them and re-run until it passes cleanly.
For SwiftLint violations that require manual fixes, prefer fixing the root cause over suppressing with // swiftlint:disable comments. Suppression is appropriate when the violation is structural and fixing it would require an artificial or non-idiomatic refactor. Common cases:
line_length — wrap long lines using Xcode's ⌃M style (each argument on its own indented line); fix rather than suppressfile_length — if a #if DEBUG preview section pushed a file over the limit, add // swiftlint:disable file_length at the top of the file (this is the established pattern — do NOT move previews to a separate file)type_body_length — split large types using // MARK: extensions in separate files if needed; suppress only if the type is inherently large and splitting would hurt readabilityOnly hand back once ./Scripts/pre-commit passes cleanly for files touched in this session.
// MARK: section, keep members in a single alphabetical order (stored properties, computed properties, methods, and static members share that order), and alphabetize function and initializer parameters the same way (default-valued, variadic, then trailing-closure parameters last). Insert new members and parameters at their alphabetical position rather than appending. Exceptions: UI objects (views, view modifiers) follow visual layout order, not alphabetical; and protocol *conformance* ordering is not enforced.static member on the relevant type or extension over a file-scope global function or property, even a private one.Date, etc.) rather than raw strings, unless deliberately mirroring an external contract (e.g. an SDK model that stores ISO date strings) where typed conversion is intentionally deferred.Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling
Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification
Take bitwarden/implementing-ios-code from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.