Skip to main content
Version: Next

Swift API

Looking for the cross-language FFI contract? See ./ffi-abi.md for callNative, the "ERROR:" prefix, buffer sizes, CKclLib (the systemLibrary wrapping libkcl_lib), and the exported Rust symbols. The 20 typed methods on API below are thin wrappers around that single dispatcher.

The official Swift package lives at kcl-lang/lib/tree/main/swift and exposes the entire KclService and BuiltinService surface area as strongly-typed Swift methods generated from spec/spec.proto via swift-protobuf. The package is published as two library products — KclLib (the FFI + RPC client) and KclLibAST (a pure-Foundation parser for the astJson strings emitted by ParseFileResult and ParseProgramResult).

Installation​

Add the package to Package.swift:

// swift-tools-version: 5.8
import PackageDescription

let package = Package(
name: "MyApp",
products: [.executable(name: "MyApp", targets: ["MyApp"])],
dependencies: [
.package(url: "https://github.com/kcl-lang/lib.git", branch: "main")
],
targets: [
.executableTarget(
name: "MyApp",
dependencies: [
.product(name: "KclLib", package: "lib"),
// optional: typed AST parser for `ParseFileResult.astJson`
.product(name: "KclLibAST", package: "lib"),
]
),
]
)

The package transitively pulls swift-protobuf >= 1.27.0 and a CKclLib systemLibrary that links against the prebuilt libkcl_lib.{dylib,so,dll} shared object shipped under Sources/CKclLib/lib/. Set KCL_LIB_HOME (or drop the shared library on your loader path) if the linker cannot find libkcl_lib automatically.

Quick Start​

With a schema.k file:

schema AppConfig:
replicas: int

app: AppConfig {
replicas: 2
}
import Foundation
import KclLib

let api = API()
var args = ExecProgramArgs()
args.kFilenameList = ["schema.k"]
let result = try api.execProgram(args)
print(result.yamlResult) // "app:\n replicas: 2\n"

Errors thrown by the dispatcher are surfaced as KclError.runtime(...) — the underlying "ERROR:" prefix the Rust dispatcher prepends is stripped before the message reaches Swift.

API Reference​

API conforms to Service (declared in Sources/KclLib/Service.swift). Every method takes the corresponding *Args struct (generated from spec.proto) and returns the matching *Result struct. ExecProgramArgs inherits the v0.13.0 additions from spec.proto — errorFormat, format, and sourcemapOutput are all settable as args.errorFormat = "sarif", args.format = "json", args.sourcemapOutput = "./out.json" etc.

ping(_:)​

Round-trip a value through the dispatcher. Useful for sanity-checking the native library is loadable.

let result = try api.ping(PingArgs.with { $0.value = "hello" })
assert(result.value == "hello")

getVersion(_:)​

Returns the underlying kcl runtime version metadata.

let v = try api.getVersion(GetVersionArgs())
print(v.version, v.gitSha, v.checksum)

parseProgram(_:) / parseFile(_:)​

Parse KCL source and return the AST as a JSON string.

let parsed = try api.parseFile(ParseFileArgs.with {
$0.path = "schema.k"
})
print(parsed.astJson)
print(parsed.errors)

loadPackage(_:)​

Parse and resolve a KCL package, returning AST + symbol + scope + type tables. Heavy method — set loadSettings.resolveAst = false if you only want the symbol index.

execProgram(_:)​

Run one or more KCL files and return both yamlResult and jsonResult.

var exec = ExecProgramArgs()
exec.kFilenameList = ["schema.k"]
exec.format = "yaml" // skip the JSON encoder
exec.errorFormat = "sarif" // machine-readable diagnostics
let r = try api.execProgram(exec)

overrideFile(_:)​

Apply *-override specifications to a .k file. Mutates the file on disk.

listVariables(_:) / listOptions(_:)​

Introspection helpers driven by KclService.ListVariables and KclService.ListOptions. listOptions takes a ParseProgramArgs (the spec reuses ParseProgram here), not a dedicated args struct.

getSchemaTypeMapping(_:) / getSchemaTypeMappingUnderPath(_:)​

getSchemaTypeMapping flattens all schemas under __main__; getSchemaTypeMappingUnderPath (added in v0.13.0, see kcl-lang/kcl#1546) keeps each kcl.mod dependency under its own package name.

formatCode(_:) / formatPath(_:)​

formatCode formats a source string in memory; formatPath rewrites files (set dryRun = true to only report what would change).

lintPath(_:)​

Runs kcl lint over the given paths and returns the warnings/errors as a list of strings.

validateCode(_:)​

Validate a YAML/JSON data string against a schema declared in a KCL source string. format selects YAML or JSON for the data argument.

loadSettingsFiles(_:)​

Loads kcl.yaml (or its aliases) into a LoadSettingsFilesResult.

rename(_:) / renameCode(_:)​

rename rewrites files on disk; renameCode returns the modified sources as a map without touching the filesystem.

test(_:)​

Runs _test.* functions across the listed KCL packages and returns per-case results, including line coverage data added in v0.13.0.

updateDependencies(_:)​

Downloads the kcl.mod dependency graph and returns the resolved external packages, ready to feed back into execProgram.execArgs.externalPkgs.

listMethod()​

Returns the list of fully-qualified RPC names the runtime implements (["KclService.ExecProgram", "KclService.ParseFile", …]).

KclLibAST​

KclLibAST is a sibling SwiftPM product in the same package that parses ParseFileResult.astJson / ParseProgramResult.astJson into typed Foundation structs (Module, Stmt, Decorator, FunctionType, IndexSignature, …) without going through SwiftProtobuf.

import KclLibAST

let parsed = try api.parseFile(ParseFileArgs.with { $0.path = "schema.k" })
let module = try KclLibAST.parse(astJson: parsed.astJson)
for stmt in module.body {
print(strictTypeName(of: stmt)) // "Schema", "Assign", …
}

Buffer convention​

API allocates a 4 MiB result buffer (2048 * 2048 UInt8s) per callNative invocation and copies the response into it. If you call a method that returns a payload larger than 4 MiB (notably loadPackage with resolveAst = true), bring your own buffer:

// Future: when `API.callNative` is exposed publicly, callers can
// override the buffer size. Today the 4 MiB default is hard-coded.

Track kcl-lang/lib issue tracker for the buffer-size negotiation patch.

Errors​

ErrorWhen
KclError.runtime("…")The Rust side returned an "ERROR:<message>" reply. The prefix is stripped.
SwiftProtobuf.ErrorThe args struct failed to encode, or the response failed to decode.

There is no PluginAgent callback exposed by API; KCL programs that import kcl_plugin.* are not supported from Swift today.

Examples​

The repo ships runnable examples under swift/examples/ covering execProgram, parseProgram, formatCode, and the AST parser.