> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dedaluslabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Create a machine, run a command, get output.

export const Callout = ({icon = "lightbulb", iconJsx, color = "default", children}) => {
  const [isDark, setIsDark] = useState(false);
  useEffect(() => {
    const probe = () => setIsDark(document.documentElement.classList.contains("dark"));
    probe();
    const obs = new MutationObserver(probe);
    obs.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => obs.disconnect();
  }, []);
  const palette = {
    default: {
      bg: isDark ? "rgba(39, 39, 42, 0.6)" : "rgb(244, 244, 245)",
      fg: isDark ? "rgb(228, 228, 231)" : "rgb(39, 39, 42)"
    },
    brand: {
      bg: isDark ? "rgba(76, 29, 149, 0.2)" : "rgb(245, 243, 255)",
      fg: isDark ? "rgb(221, 214, 254)" : "rgb(76, 29, 149)"
    },
    info: {
      bg: isDark ? "rgba(30, 58, 138, 0.2)" : "rgb(239, 246, 255)",
      fg: isDark ? "rgb(191, 219, 254)" : "rgb(30, 58, 138)"
    },
    success: {
      bg: isDark ? "rgba(20, 83, 45, 0.2)" : "rgb(240, 253, 244)",
      fg: isDark ? "rgb(187, 247, 208)" : "rgb(20, 83, 45)"
    },
    warning: {
      bg: isDark ? "rgba(120, 53, 15, 0.2)" : "rgb(255, 251, 235)",
      fg: isDark ? "rgb(253, 230, 138)" : "rgb(120, 53, 15)"
    },
    danger: {
      bg: isDark ? "rgba(127, 29, 29, 0.2)" : "rgb(254, 242, 242)",
      fg: isDark ? "rgb(254, 202, 202)" : "rgb(127, 29, 29)"
    }
  };
  const tint = palette[color] ?? palette.default;
  const lucide = {
    "lightbulb": <>
				<path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5" />
				<path d="M9 18h6" />
				<path d="M10 22h4" />
			</>,
    "info": <>
				<circle cx="12" cy="12" r="10" />
				<path d="M12 16v-4" />
				<path d="M12 8h.01" />
			</>,
    "alert-triangle": <>
				<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z" />
				<path d="M12 9v4" />
				<path d="M12 17h.01" />
			</>,
    "alert-octagon": <>
				<polygon points="7.86 2 16.14 2 22 7.86 22 16.14 16.14 22 7.86 22 2 16.14 2 7.86 7.86 2" />
				<line x1="12" y1="8" x2="12" y2="12" />
				<line x1="12" y1="16" x2="12.01" y2="16" />
			</>,
    "check-circle": <>
				<path d="M21.801 10A10 10 0 1 1 17 3.335" />
				<path d="m9 11 3 3L22 4" />
			</>,
    "x-circle": <>
				<circle cx="12" cy="12" r="10" />
				<path d="m15 9-6 6" />
				<path d="m9 9 6 6" />
			</>,
    "sparkles": <>
				<path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" />
				<path d="M20 3v4" />
				<path d="M22 5h-4" />
				<path d="M4 17v2" />
				<path d="M5 18H3" />
			</>,
    "code": <>
				<polyline points="16 18 22 12 16 6" />
				<polyline points="8 6 2 12 8 18" />
			</>,
    "terminal": <>
				<polyline points="4 17 10 11 4 5" />
				<line x1="12" y1="19" x2="20" y2="19" />
			</>,
    "book-open": <>
				<path d="M12 7v14" />
				<path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
			</>,
    "zap": <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />,
    "clock": <>
				<circle cx="12" cy="12" r="10" />
				<polyline points="12 6 12 12 16 14" />
			</>
  };
  let resolvedIcon;
  if (iconJsx !== undefined) {
    resolvedIcon = iconJsx;
  } else {
    const paths = lucide[icon];
    if (!paths) {
      throw new Error(`<Callout icon="${icon}"> is not a known Lucide name. ` + `Either add it to the lucide table in callout.jsx, or pass iconJsx={...} for custom JSX. ` + `Available: ${Object.keys(lucide).join(", ")}`);
    }
    resolvedIcon = <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
				{paths}
			</svg>;
  }
  return <div className="flex items-start gap-3 px-4 py-3 my-4" style={{
    backgroundColor: tint.bg,
    color: tint.fg
  }}>
			<span className="leading-none mt-[3px] shrink-0 select-none [&>svg]:block">{resolvedIcon}</span>
			<div className="flex-1 min-w-0 [&>*:first-child]:mt-0 [&>*:last-child]:mb-0 [&_a_code]:no-underline [&_a]:underline-offset-[3px]">
				{children}
			</div>
		</div>;
};

<Steps>
  <Step title="Install the CLI">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -fsSL https://www.dedaluslabs.ai/install/dedalus | bash
    ```
  </Step>

  <Step title="Set your API key">
    Get a key from the [Dashboard](https://dedaluslabs.ai/dashboard/api-keys).

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    export DEDALUS_API_KEY=<your-key>
    ```
  </Step>

  <Step title="Create a machine">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    dedalus machines create --vcpu 1 --memory-mib 1024 --storage-gib 10 --autosleep never
    ```

    Note the `machine_id` (starts with `dm-`).
  </Step>

  <Step title="Run a command">
    SSH is the fastest path when you're following along interactively. The CLI runs commands directly, without opening a shell. Do anything you'd like on a full Linux computer.

    <CodeGroup>
      ```bash SSH theme={"theme":{"light":"github-light","dark":"github-dark"}}
      dedalus ssh <machine_id>

      # Inside the machine:
      whoami && uname -a
      ```

      ```bash CLI theme={"theme":{"light":"github-light","dark":"github-dark"}}
      dedalus machines executions create \
        --machine-id <machine_id> \
        --command '["/bin/bash", "-c", "whoami && uname -a"]'

      dedalus machines executions output --machine-id <machine_id> --execution-id <exec_id>
      ```
    </CodeGroup>
  </Step>
</Steps>

## Use Dedalus Machines programmatically

Dedalus Machines work from both the CLI and SDKs. The example below creates a machine, runs a command, and prints its output.

<CodeGroup>
  ```bash CLI theme={"theme":{"light":"github-light","dark":"github-dark"}}
  dedalus machines create --vcpu 1 --memory-mib 1024 --storage-gib 10
  dedalus machines executions create \
    --machine-id <machine_id> \
    --command '["/bin/bash", "-c", "whoami && uname -a"]'
  dedalus machines executions output --machine-id <machine_id> --execution-id <exec_id>
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import time

  from dedalus_sdk import Dedalus

  client = Dedalus()
  DONE = {"succeeded", "failed", "cancelled", "expired"}

  dm = client.machines.create(vcpu=1, memory_mib=1024, storage_gib=10)
  stream = client.machines.watch(machine_id=dm.machine_id)
  for _ in stream:
      pass

  exc = client.machines.executions.create(
      machine_id=dm.machine_id,
      command=["/bin/bash", "-c", "whoami && uname -a"],
  )
  while exc.status not in DONE:
      time.sleep(0.5)
      exc = client.machines.executions.retrieve(
          machine_id=dm.machine_id,
          execution_id=exc.execution_id,
      )
  if exc.status != "succeeded":
      raise RuntimeError(f"{exc.status}: {exc.error_code}: {exc.error_message}")

  out = client.machines.executions.output(
      machine_id=dm.machine_id,
      execution_id=exc.execution_id,
  )
  print(out.stdout)
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import Dedalus from "dedalus";

  const client = new Dedalus();
  const DONE = new Set(["succeeded", "failed", "cancelled", "expired"]);
  const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));

  const dm = await client.machines.create({
    vcpu: 1,
    memory_mib: 1024,
    storage_gib: 10,
  });
  const stream = await client.machines.watch({ machine_id: dm.machine_id });
  for await (const _ of stream) {}

  let exc = await client.machines.executions.create({
    machine_id: dm.machine_id,
    command: ["/bin/bash", "-c", "whoami && uname -a"],
  });
  while (!DONE.has(exc.status)) {
    await sleep(500);
    exc = await client.machines.executions.retrieve({
      machine_id: dm.machine_id,
      execution_id: exc.execution_id,
    });
  }
  if (exc.status !== "succeeded") {
    throw new Error(`${exc.status}: ${exc.error_code}: ${exc.error_message}`);
  }

  const out = await client.machines.executions.output({
    machine_id: dm.machine_id,
    execution_id: exc.execution_id,
  });
  console.log(out.stdout);
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"github-dark"}}
  package main

  import (
      "context"
      "fmt"
      "time"

      dedalus "github.com/dedalus-labs/dedalus-go"
  )

  func main() {
      client := dedalus.NewClient()
      ctx := context.Background()
      done := map[dedalus.ExecutionStatus]bool{
          dedalus.ExecutionStatusSucceeded: true,
          dedalus.ExecutionStatusFailed:    true,
          dedalus.ExecutionStatusCancelled: true,
          dedalus.ExecutionStatusExpired:   true,
      }

      dm, err := client.Machines.New(ctx, dedalus.MachineNewParams{
          CreateParams: dedalus.CreateParams{
              VCPU: 1, MemoryMiB: 1024, StorageGiB: 10,
          },
      })
      check(err)
      stream := client.Machines.WatchStreaming(ctx, dedalus.MachineWatchParams{
          MachineID: dm.MachineID,
      })
      for stream.Next() {
      }
      check(stream.Err())

      exc, err := client.Machines.Executions.New(ctx, dedalus.MachineExecutionNewParams{
          MachineID: dm.MachineID,
          ExecutionCreateParams: dedalus.ExecutionCreateParams{
              Command: []string{"/bin/bash", "-c", "whoami && uname -a"},
          },
      })
      check(err)

      for !done[exc.Status] {
          time.Sleep(500 * time.Millisecond)
          exc, err = client.Machines.Executions.Get(ctx, dedalus.MachineExecutionGetParams{
              MachineID: dm.MachineID, ExecutionID: exc.ExecutionID,
          })
          check(err)
      }
      if exc.Status != dedalus.ExecutionStatusSucceeded {
          panic(fmt.Sprintf("%s: %s", exc.ErrorCode, exc.ErrorMessage))
      }

      out, err := client.Machines.Executions.Output(ctx, dedalus.MachineExecutionOutputParams{
          MachineID: dm.MachineID, ExecutionID: exc.ExecutionID,
      })
      check(err)
      fmt.Println(out.Stdout)
  }

  func check(err error) {
      if err != nil {
          panic(err)
      }
  }
  ```
</CodeGroup>

Now sleep, wake, watch, or delete the machine: [Lifecycle](/dcs/dm/lifecycle).
