# Getting Started

> Build a Taskbox client and call your first tool.

Source: https://taskbox.n.yatsyk.com/docs/tools/getting-started

# Getting Started

## 1. Install

```bash
npm i @taskbox/tools @taskbox/podman @taskbox/core @taskbox/schemas
```

You only ever interact with `@taskbox/tools` directly; the others come along
as transitive dependencies but stay accessible if you need them.

## 2. Wire a runtime

```ts
import { createTaskbox } from "@taskbox/tools";
import { podman } from "@taskbox/podman";

const tbx = createTaskbox({
  runtime: podman({ pullPolicy: "if-missing" }),
  // optional defaults applied to every call
  defaults: {
    timeoutMs: 60_000,
    networkMode: "direct",
  },
});
```

## 3. Sanity-check the runtime + image

```ts
const ready = await tbx.prepare();
// {
//   runtime: "podman",
//   image: { ref: "taskbox/kitchen-sink:0.1.0", digest: "sha256:..." },
//   rootless: true,
//   version: "5.x.x",
// }
```

`prepare()` throws `TaskboxError({ code: "E_RUNTIME_UNAVAILABLE" })` if the
runtime adapter reports `available().ok === false`.

## 4. Call a tool

```ts
const result = await tbx.media.downloadSubtitles(
  {
    url: "https://youtu.be/jNQXAC9IVRw",
    languages: ["en", "de"],
    format: "srt",
    auto: false,
    outputDir: "/tmp/subs",
  },
  {
    onEvent: (e) => {
      if (e.type === "task.failed") console.error(e.error.message);
    },
  },
);
```

A `proxy` field on the input flips network mode to `"proxy"` automatically
so tasks behind a corporate egress reuse the same code path.

## 5. Drop down to `runTask` when needed

```ts
const raw = await tbx.runTask({
  tool: "media.downloadSubtitles",
  input: { url: "https://...", languages: ["en"] },
  network: { mode: "direct" },
});
```

`tbx.runTask` accepts an unknown spec, validates it via
`TaskSpecSchema`, and returns a typed `TaskResult`. Use it when you're
forwarding a spec from a queue, IPC, or another process.
