CopilotforXcodeKit is a Swift package that allow you to build extensions for Copilot for Xcode.
- In-app Configuration Screen
- Suggestion Service
- Custom Chat Tab
- Chat Service
- Prompt to Code Service
- APIs for other Xcode Source Editor Extensions
- Custom Models
Create a Generic Extension target. The extension should target macOS 13+. It can be sandboxed.
In the info.plist of the target, set ExtensionPointIdentifier
to com.intii.CopilotForXcode.ExtensionService.Extension
:
<key>EXAppExtensionAttributes</key>
<dict>
<key>EXExtensionPointIdentifier</key>
<string>com.intii.CopilotForXcode.ExtensionService.Extension</string>
</dict>
Add this repo as an dependency in Package.swift or via UI in Xcode.
Create a class that conforms to CopilotForXcodeExtension
, and mark it with @main
.
import CopilotForXcodeKit
@main
class Extension: CopilotForXcodeExtension {
...
}
When the extension is turned on in Copilot for Xcode, the connection will be established. connectionDidActivate(connectedTo:)
will be called and host
will be set.
Once host
is set, you can use it to communicate with Copilot for Xcode.
class Extension: CopilotForXcodeExtension {
var host: HostServer?
func connectionDidActivate(connectedTo host: HostServer) {
Task {
try await host.toast("Connected to Example Extension")
}
}
...
}
Copilot for Xcode will occasionally communicate with your extension to provide updates about Xcode. You can implement observer methods such as workspace(_:didOpenFileAt:)
to receive this information.
To provide a configuration screen that users can access from the extension list, you must
- Create a type that conforms to
CopilotForXcodeExtensionSceneConfiguration
. Then, return a scene through theconfigurationScene
property. - Return the configuration from the
sceneConfiguration
property of the extension.
struct SceneConfiguration: CopilotForXcodeExtensionSceneConfiguration {
var configurationScene: ConfigurationScene<ConfigurationView>? {
.init { viewModel in
ConfigurationView(model: viewModel)
} onConnection: { _ in
return true
}
}
}
The ConfigurationView
is instantiated when the configuration screen is opened, and the connection is established at this point.
You can then utilize the host
property of the view model to communicate with Copilot for Xcode.
struct ConfigurationView: View {
@ObservedObject var model: CopilotForXcodeSceneModel
var body: some View {
Button("Toast") {
Task { @MainActor in
try? await model.host?.toast("Hello")
}
}
}
}
To enable the suggestion service within your extension, you must:
- Implement a type that conforms to the
SuggestionServiceType
protocol. - Provide an instance of this type by returning it from the
suggestionService
property.
class SuggestionService: SuggestionServiceType {
var configuration: SuggestionServiceConfiguration {
.init(acceptsRelevantCodeSnippets: true)
}
func getSuggestions(
_ request: SuggestionRequest,
workspace: WorkspaceInfo
) async throws -> [CodeSuggestion] {
[
.init(
id: UUID().uuidString,
text: "Hello World",
position: request.cursorPosition,
range: .init(start: request.cursorPosition, end: request.cursorPosition)
),
]
}
...
}
If you need to maintain multiple suggestion services for different workspaces, such as those utilizing language servers, you will be responsible for managing the lifecycle of each service individually.
To debug the extension, you have two options: running it directly in Xcode or simply building it. There is no practical difference between the two methods, as Xcode does not automatically attach to the extension's process (may be a bug).
Either way, once the extension is built, it will be available in Copilot for Xcode. Then you need to enable the extension:
- Click "Extensions" in Copilot for Xcode.app.
- Click "Select Extensions" to see all available extensions.
- Enable the extension you want to debug.
After that, the extension process will start to run. You can attach to it from Xcode's Debug menu.
It is recommended to give the debug build a different bundle identifier to prevent conflicts with the release version.
When running the extension from Xcode, you will be prompted to choose a target application. Please select "Copilot for Xcode.app".