Cloudticon
curl -fsSL https://cloudticon.com/install.sh | sudo shWrite TypeScript, not YAML
Section titled “Write TypeScript, not YAML”Readable, type-safe resource definitions with IDE autocomplete — no boilerplate, no templating hacks.
import { deployment, service, ingress } from "github.com/cloudticon/k8s@master";
const app = "api";
const labels = {"app.kubernetes.io/name": app,"app.kubernetes.io/part-of": "acme-platform","app.kubernetes.io/managed-by": "ct",};
deployment({ name: app, labels, image: "ghcr.io/acme/api:2.1.0", replicas: 3, resources: { requests: { cpu: "100m", memory: "128Mi" }, limits: { cpu: "500m", memory: "512Mi" }, }});
service({ name: app, labels, selector: labels, ports: [ { name: "http", port: 80, targetPort: 8080 }, { name: "metrics", port: 9090, targetPort: 9090 }, ]});
ingress({ name: app, labels, rules: [ { host: "api.acme.com", http: { paths: [ { path: "/", pathType: "Prefix", backend: { service: app, port: 80 }, }, ], }, }, ]});apiVersion: apps/v1kind: Deploymentmetadata: name: api labels: app.kubernetes.io/name: api app.kubernetes.io/part-of: acme-platform app.kubernetes.io/managed-by: ctspec: replicas: 3 selector: matchLabels: app.kubernetes.io/name: api app.kubernetes.io/part-of: acme-platform app.kubernetes.io/managed-by: ct template: metadata: labels: app.kubernetes.io/name: api app.kubernetes.io/part-of: acme-platform app.kubernetes.io/managed-by: ct spec: containers: - name: api image: ghcr.io/acme/api:2.1.0 resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "500m" memory: "512Mi"---apiVersion: v1kind: Servicemetadata: name: api labels: app.kubernetes.io/name: api app.kubernetes.io/part-of: acme-platform app.kubernetes.io/managed-by: ctspec: selector: app.kubernetes.io/name: api app.kubernetes.io/part-of: acme-platform app.kubernetes.io/managed-by: ct ports: - name: http port: 80 targetPort: 8080 - name: metrics port: 9090 targetPort: 9090---apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: api labels: app.kubernetes.io/name: api app.kubernetes.io/part-of: acme-platform app.kubernetes.io/managed-by: ctspec: rules: - host: api.acme.com http: paths: - path: / pathType: Prefix backend: service: name: api port: number: 8050 lines vs 80 lines — labels repeated 5×, indentation 8 levels deep, and that’s just one microservice. Now imagine scaling that.
Dev mode in one command
Section titled “Dev mode in one command”Add a dev.ct file next to your resources:
// dev.ctconfig({ namespace: "myapp-dev" });
dev("api", { command: ["npm", "run", "dev"], sync: [{ from: "./", to: "/app" }], ports: [[8080, 3000]],});ct devPort forwarding, file sync, log streaming — all start in parallel. Edit a file locally and it lands in the container instantly. No Docker rebuilds, no separate YAML config. Full CT Dev docs →
Build your own factory in minutes
Section titled “Build your own factory in minutes”You don’t have to use built-in primitives only — create a custom resource factory, push it to GitHub, and every team can import it instantly with a single URL.
1. Define the factory — a plain TypeScript function that calls lower-level primitives:
import { deployment, service, ingress } from "github.com/cloudticon/k8s@master";
interface WebStackOptions { name: string; image: string; replicas?: number; host?: string;}
export function webApp(opts: WebStackOptions) { const labels = { "app.kubernetes.io/name": opts.name, "app.kubernetes.io/managed-by": "ct", };
deployment({ name: opts.name, labels, image: opts.image, replicas: opts.replicas ?? 1, resources: { requests: { cpu: "100m", memory: "128Mi" }, limits: { cpu: "500m", memory: "512Mi" }, }, });
service({ name: opts.name, labels, selector: labels, ports: [{ name: "http", port: 80, targetPort: 8080 }], });
if (opts.host) { ingress({ name: opts.name, labels, rules: [{ host: opts.host, http: { paths: [{ path: "/", pathType: "Prefix", backend: { service: opts.name, port: 80 } }] } }], }); }}2. Push to GitHub — that’s it. No registry, no publish step.
3. Import anywhere — any .ct file in any repo can pull your factory by URL:
import { webApp } from "github.com/your/repo@master";
webApp({ name: "api", image: "ghcr.io/acme/api:2.1.0", replicas: 3, host: "api.acme.com"});CT fetches and caches the module at ct template time — no npm install, no pre-build. Version-pin with a tag (@v1), a branch (@main), or a commit SHA for full reproducibility.
High-level library: k8s-factories
Section titled “High-level library: k8s-factories”Want less boilerplate for common single-container workloads? Use k8s-factories and start from webApp() plus optional expose() routing.
import { webApp, env, vol } from "github.com/cloudticon/k8s-factories@master";
webApp({ name: "api", image: "ghcr.io/acme/api:2.1.0", port: 8080, env: { NODE_ENV: "production", DB_PASSWORD: env.secret("db-credentials", "password"), }, volumes: { "/data": vol.pvc({ size: "10Gi" }), "/cache": vol.emptyDir(), }, probes: { path: "/health" }, hpa: { min: 2, max: 8, cpu: 75 }, expose: { type: "istio", host: "api.acme.com", },});This single call creates Deployment + Service, and can also add HPA, PVC-backed volumes, and inline exposure. For more patterns, see Examples.
Real programming language, real power
Section titled “Real programming language, real power”.ct files are TypeScript — so you get if, for, map, spread, destructuring, and every other language feature out of the box. No custom DSL, no {{- if }} hacks.
values.json
{ "domain": "acme.com", "apps": [ { "name": "api", "image": "ghcr.io/acme/api:2.1.0", "replicas": 3, "public": true }, { "name": "auth", "image": "ghcr.io/acme/auth:1.0.0", "replicas": 1, "public": false }, { "name": "billing", "image": "ghcr.io/acme/billing:3.2.1", "replicas": 5, "public": true } ]}app.ct
import { deployment, service, ingress } from "github.com/cloudticon/k8s@master";
function labels(app: string) { return { "app.kubernetes.io/name": app, "app.kubernetes.io/managed-by": "ct" };}
for (const app of Values.apps) { deployment({ name: app.name, labels: labels(app.name), image: app.image, replicas: app.replicas, });
service({ name: app.name, labels: labels(app.name), selector: labels(app.name), ports: [{ name: "http", port: 80, targetPort: 8080 }], });
if (app.public) { ingress({ name: app.name, labels: labels(app.name), rules: [ { host: `${app.name}.${Values.domain}`, http: { paths: [ { path: "/", pathType: "Prefix", backend: { service: app.name, port: 80 } } ] } } ] }); }}Values come from values.json (or values.yaml) and are fully typed via ct types .. Loop over a list, conditionally create an Ingress, extract a helper function — all in plain TypeScript. No copy-paste drift, no forgotten fields, and the compiler catches every typo.
Full IntelliSense in VS Code
Section titled “Full IntelliSense in VS Code”.ct files are TypeScript — so your editor already knows how to help. Install the CT VS Code extension and run ct types . to unlock:
- Autocomplete for every field — type
deployment({and seename,image,replicas,resources,labelssuggested instantly. No guessing field names, no checking docs mid-flow. - Typed Values —
Values.replicas,Values.imagecome straight from yourvalues.jsonorvalues.yaml. Rename a key and the editor flags every broken reference. - URL import resolution — types from
github.com/cloudticon/k8s@masterare fetched, cached, and visible to TypeScript. Jump-to-definition works across packages. - Errors before you run — misspell a field, pass a number where a string is expected, forget a required property — red squiggles appear immediately, not after
ct templatefails.
deployment({ name: "api", image: "ghcr.io/acme/api:2.1.0", replicas: "3", // ~~~ Type 'string' is not assignable to type 'number'});The extension watches .ct and values files — types refresh automatically on save. See CT VS Code for setup details.
First run in 60 seconds
Section titled “First run in 60 seconds”curl -fsSL https://cloudticon.com/install.sh | sudo shct init my-appcd my-appct template my-app-dev . --namespace default- Install CT.
- Initialize a project.
- Render resources with a release name.
- Iterate in VS Code with IntelliSense and
ct types.
Documentation map
Section titled “Documentation map”- CT CLI — full command and flag reference, workflows, troubleshooting.
- ct delete — remove a release from cluster using inventory (no source path required).
- CT vs Helm — why TypeScript beats Go templates.
- CT Dev — development mode for Kubernetes — port forwarding, file sync, logs.
- CT VS Code — extension setup, type generation, diagnostics.
- K8s Resource Factories — reusable
resource()based APIs. - K8s High-level Factories —
webApp()andexpose()patterns fromk8s-factories. - CT Operator — runtime and deployment model.