Official client libraries for the Codewire API.
| Language | Package | Status |
|---|---|---|
| TypeScript | @codewire/sdk |
Alpha |
| Go | codewire.sh/sdk-go |
Alpha |
| Python | codewire |
Alpha |
from codewire import Codewire
cw = Codewire()
env = cw.environments.create(template_slug="python", wait=True)
result = env.exec(command=["python3", "-c", "print('hello')"])
print(result["stdout"])
env.remove()import { Codewire } from "@codewire/sdk";
const cw = new Codewire();
const env = await cw.environments.create(
{ template_slug: "python" },
{ wait: true },
);
const result = await env.exec({ command: ["python3", "-c", "print('hello')"] });
console.log(result.stdout);
await env.remove();import codewire "codewire.sh/sdk-go"
client := codewire.New("")
env, err := client.Environments.Create(ctx, api.CreateEnvironmentBody{
TemplateSlug: ptr("python"),
}, codewire.CreateOptions{Wait: true})
result, err := env.Exec(ctx, api.ExecBody{
Command: &[]string{"python3", "-c", "print('hello')"},
})
fmt.Println(result.Stdout)
env.Remove(ctx)The SDK is built around the environment as the primary object. The typical flow:
- Create --
create()returns anEnvironmentwith methods bound to it. - Wait -- pass
wait=Trueto block until the environment is running, or callwait_ready()/WaitReady()separately. - Exec -- run commands via
env.exec(...). - Files -- transfer files via
env.files.*. - Cleanup -- destroy with
env.remove().
Environment methods:
env.exec(...) # Execute a command
env.start() # Start a stopped environment
env.stop() # Stop a running environment
env.remove() # Delete the environment
env.wait_ready() # Poll until state is "running"
env.list_ports() # List exposed ports
env.create_port(...) # Expose a port
env.delete_port(...) # Remove a port
File operations live under env.files:
env.files.list(path) # List files at path
env.files.upload(data, path) # Upload a file
env.files.download(path) # Download a file
env.files.upload(b"input data", "/workspace/input.txt")
entries = env.files.list("/workspace")
content = env.files.download("/workspace/output.txt")await env.files.upload(new TextEncoder().encode("input data"), "/workspace/input.txt");
const entries = await env.files.list("/workspace");
const buf = await env.files.download("/workspace/output.txt");env.Files.Upload(ctx, strings.NewReader("input data"), "/workspace/input.txt")
entries, _ := env.Files.List(ctx, ptr("/workspace"))
body, _ := env.Files.Download(ctx, "/workspace/output.txt")All SDKs provide these services:
- Environments -- create, list, get, delete, start, stop, exec, files, ports
- Templates -- create, list, get, update, delete
- API Keys -- create, list, delete
- Secrets -- list, set, delete (org + user scopes)
- Secret Projects -- create, list, delete, manage project secrets
- Local -- operate local VMs through
cw local(docker & lima backends today) - Relay -- networks, nodes, groups, credentials, KV (construct a separate
RelayClient)
Each SDK ships a local service that mirrors environments but targets VMs
managed by the cw local CLI on the
developer's host. Requires the cw binary on PATH (or $CW_BIN). The SDK
shells out to cw local <cmd> --json, so no extra credentials are needed.
from codewire import Codewire, LocalSpec
cw = Codewire() # no API key needed for local-only use
inst = cw.local.create(
LocalSpec(image="python:3.12"),
backend="docker",
wait=True,
)
result = inst.exec(command=["python", "-c", "print('hi')"])
print(result.stdout)
inst.files.upload(b"hello", "/workspace/greeting.txt")
print(inst.files.download("/workspace/greeting.txt"))
inst.remove()import { Codewire } from "@codewire/sdk";
const cw = new Codewire();
const inst = await cw.local.create(
{ image: "python:3.12" },
{ backend: "docker", wait: true },
);
const result = await inst.exec({ command: ["python", "-c", "print('hi')"] });
console.log(result.stdout);
await inst.files.upload(new TextEncoder().encode("hello"), "/workspace/greeting.txt");
console.log(new TextDecoder().decode(await inst.files.download("/workspace/greeting.txt")));
await inst.remove();import codewire "codewire.sh/sdk-go"
cw := codewire.New("")
inst, _ := cw.Local.Create(ctx,
codewire.LocalSpec{Image: "python:3.12"},
codewire.LocalCreateOptions{Backend: "docker", Wait: true},
)
res, _ := inst.Exec(ctx, codewire.LocalExecRequest{Command: []string{"python", "-c", "print('hi')"}})
fmt.Println(res.Stdout)
inst.Files.Upload(ctx, strings.NewReader("hello"), "/workspace/greeting.txt")
rc, _ := inst.Files.Download(ctx, "/workspace/greeting.txt")
// …
inst.Remove(ctx)Supported backends through the SDK: docker, lima. firecracker and
incus remain CLI-only.
Relay endpoints run on a separate host from the platform API, with their own
auth token. All three SDKs expose a RelayClient with identical coverage:
networks, nodes, groups, credentials (runtime + sender delegations), and KV.
from codewire import RelayClient
relay = RelayClient("https://relay.codewire.sh", "cw_relay_...")
relay.networks.create("my-network")
relay.kv.set("my-network", "session-state", "key1", b"value1", ttl="1h")import { RelayClient } from "@codewire/sdk";
const relay = new RelayClient("https://relay.codewire.sh", "cw_relay_...");
await relay.networks.create("my-network");
await relay.kv.set("my-network", "session-state", "key1", "value1", { ttl: "1h" });relay := codewire.NewRelayClient("https://relay.codewire.sh", "cw_relay_...")
relay.Networks.Create(ctx, "my-network")
relay.KV.Set(ctx, "my-network", "session-state", "key1", []byte("value1"), "1h")Set credentials via environment variables:
CODEWIRE_API_KEY=cw_...
CODEWIRE_ORG_ID=org_...
Or pass them to the client constructor:
cw = Codewire(api_key="cw_...", org_id="org_...")const cw = new Codewire({ apiKey: "cw_...", orgId: "org_..." });client := codewire.New("cw_...", codewire.WithOrgID("org_..."))Types are generated from the server's OpenAPI spec:
cd sdk && make generate # Regenerate all types
cd sdk && make check # Verify everything compilesMIT