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

# Get Started with the Devbox CLI

> Install the Devbox CLI, authenticate with Namespace, then create and connect to a Devbox from your terminal.

export const KeepTabPosition = () => {
  useEffect(() => {
    const stateKey = "__namespaceKeepTabPosition";
    const releaseState = state => {
      state.instances -= 1;
      if (state.instances > 0) return;
      state.removeListeners();
      if (window[stateKey] === state) delete window[stateKey];
    };
    const existingState = window[stateKey];
    if (existingState) {
      existingState.instances += 1;
      return () => releaseState(existingState);
    }
    const maxSettleTime = 250;
    const requiredStableFrames = 3;
    const positionTolerance = 0.5;
    let animationFrame;
    let observer;
    let settleDeadline;
    let stableFrames = 0;
    let tabListToKeep;
    let tabListTop;
    const findTab = event => {
      if (!(event.target instanceof Element)) return null;
      return event.target.closest(".tab-container [role='tab']");
    };
    const findScrollContainer = element => {
      for (let parent = element.parentElement; parent; parent = parent.parentElement) {
        const {overflowY} = getComputedStyle(parent);
        if ((overflowY === "auto" || overflowY === "scroll") && parent.scrollHeight > parent.clientHeight) {
          return parent;
        }
      }
      return null;
    };
    const stopKeepingPosition = () => {
      if (animationFrame) cancelAnimationFrame(animationFrame);
      animationFrame = undefined;
      observer?.disconnect();
      tabListToKeep = undefined;
    };
    const restoreTabListPosition = () => {
      if (!tabListToKeep?.isConnected) return 0;
      const offset = tabListToKeep.getBoundingClientRect().top - tabListTop;
      if (Math.abs(offset) < positionTolerance) return offset;
      const scrollOptions = {
        top: offset,
        behavior: "instant"
      };
      const scrollContainer = findScrollContainer(tabListToKeep);
      if (scrollContainer) {
        scrollContainer.scrollBy(scrollOptions);
      } else {
        window.scrollBy(scrollOptions);
      }
      return offset;
    };
    const settlePosition = () => {
      const offset = restoreTabListPosition();
      stableFrames = Math.abs(offset) < positionTolerance ? stableFrames + 1 : 0;
      if (stableFrames >= requiredStableFrames || performance.now() >= settleDeadline) {
        stopKeepingPosition();
        return;
      }
      animationFrame = requestAnimationFrame(settlePosition);
    };
    observer = new MutationObserver(() => {
      stableFrames = 0;
      restoreTabListPosition();
    });
    const keepTabListInPlace = tab => {
      stopKeepingPosition();
      tabListToKeep = tab.closest("[role='tablist']");
      if (!tabListToKeep) return;
      tabListTop = tabListToKeep.getBoundingClientRect().top;
      settleDeadline = performance.now() + maxSettleTime;
      stableFrames = 0;
      observer.observe(document.getElementById("content") ?? document.documentElement, {
        attributes: true,
        attributeFilter: ["aria-selected", "class"],
        childList: true,
        subtree: true
      });
      animationFrame = requestAnimationFrame(settlePosition);
    };
    const selectWithoutNavigation = event => {
      if (!event.isTrusted) return;
      const tab = findTab(event);
      if (!tab) return;
      keepTabListInPlace(tab);
      event.preventDefault();
      event.stopPropagation();
      tab.click();
      restoreTabListPosition();
    };
    const selectWithKeyboard = event => {
      if (!event.isTrusted) return;
      const tab = findTab(event);
      const tabList = tab?.closest("[role='tablist']");
      if (!tab || !tabList) return;
      const tabs = Array.from(tabList.querySelectorAll(":scope > [role='tab']"));
      const currentIndex = tabs.indexOf(tab);
      let nextIndex;
      switch (event.key) {
        case "ArrowLeft":
          nextIndex = (currentIndex - 1 + tabs.length) % tabs.length;
          break;
        case "ArrowRight":
          nextIndex = (currentIndex + 1) % tabs.length;
          break;
        case "Home":
          nextIndex = 0;
          break;
        case "End":
          nextIndex = tabs.length - 1;
          break;
        case "Enter":
        case " ":
          nextIndex = currentIndex;
          break;
        default:
          return;
      }
      keepTabListInPlace(tab);
      event.preventDefault();
      event.stopPropagation();
      tabs[nextIndex]?.click();
      tabs[nextIndex]?.focus({
        preventScroll: true
      });
      restoreTabListPosition();
    };
    document.addEventListener("click", selectWithoutNavigation, true);
    document.addEventListener("keydown", selectWithKeyboard, true);
    const state = {
      instances: 1,
      removeListeners: () => {
        stopKeepingPosition();
        document.removeEventListener("click", selectWithoutNavigation, true);
        document.removeEventListener("keydown", selectWithKeyboard, true);
      }
    };
    window[stateKey] = state;
    return () => releaseState(state);
  }, []);
  return null;
};

<KeepTabPosition />

The Devbox CLI creates, connects to, and manages Devboxes from your terminal. Use it when you want to drive Devboxes from your existing shell workflow, script them, or open one in a local IDE.

This page takes you from an empty machine to a Devbox you can run commands in. If you prefer to start in the browser, follow the Dashboard flow in the [Introduction](/docs/devbox#getting-started).

## Getting Started

<Steps titleSize="h3">
  <Step id="install-the-devbox-cli" title="Install the Devbox CLI">
    <Tabs>
      <Tab title="macOS" icon="https://mintcdn.com/namespace-labs/YnODJWPvsMShiQQC/images/icons/apple.svg?fit=max&auto=format&n=YnODJWPvsMShiQQC&q=85&s=1076263ef0a75ced2146cc606bb3871b" width="24" height="24" data-path="images/icons/apple.svg">
        ```bash theme={null}
        curl -fsSL get.namespace.so/devbox/install.sh | bash
        ```
      </Tab>

      <Tab title="Linux" icon="https://mintcdn.com/namespace-labs/RAfpS6JkeZq1maU3/images/icons/linux.svg?fit=max&auto=format&n=RAfpS6JkeZq1maU3&q=85&s=5442034c78f9da6d7b50cbdc5a915f3a" width="24" height="24" data-path="images/icons/linux.svg">
        ```bash theme={null}
        curl -fsSL get.namespace.so/devbox/install.sh | bash
        ```
      </Tab>

      <Tab title="Windows" icon="https://mintcdn.com/namespace-labs/YnODJWPvsMShiQQC/images/icons/windows.svg?fit=max&auto=format&n=YnODJWPvsMShiQQC&q=85&s=63c0bb0e51580dcbd2cbef4b1801f545" width="4875" height="4875" data-path="images/icons/windows.svg">
        Run the following command in PowerShell:

        ```powershell theme={null}
        irm https://get.namespace.so/devbox/install.ps1 | iex
        ```

        Restart your terminal if `devbox` is not available on your `PATH` after installation.

        Connecting over SSH also requires an [OpenSSH client](https://learn.microsoft.com/windows-server/administration/openssh/openssh_install_firstuse). Most modern Windows installations include one.
      </Tab>
    </Tabs>

    Confirm the installation:

    ```bash theme={null}
    devbox version
    ```
  </Step>

  <Step title="Authenticate with Namespace">
    ```bash theme={null}
    devbox login
    ```

    The command prints a login URL and opens it in your browser. Complete the flow there, and the CLI stores a user credential in your operating system's user configuration directory.

    Check the stored credential at any time:

    ```bash theme={null}
    devbox auth check
    ```
  </Step>

  <Step title="Create a Devbox">
    `devbox create` provisions a Devbox and activates it, so it is ready to connect to when the command returns. Supply its configuration interactively or as flags.

    <Tabs>
      <Tab title="Interactive">
        The CLI prompts for a name, an image, and a machine size:

        ```bash theme={null}
        devbox create --checkout github.com/your-org/your-repo
        ```
      </Tab>

      <Tab title="Non-interactive">
        Pass every value as a flag to skip the prompts:

        ```bash theme={null}
        devbox create --name my-devbox --image builtin:agents --size m --checkout github.com/your-org/your-repo
        ```
      </Tab>
    </Tabs>

    `--checkout` clones a repository into the Devbox and requires a [connected GitHub organization](/docs/devbox#getting-started). Omitting it applies the workspace default repository, and `--no_checkout` skips the checkout entirely.

    See [`devbox create`](/docs/reference/devbox-cli/create) for the full set of options, including Blueprints, ephemeral Devboxes, and specification files.
  </Step>

  <Step title="Connect to your Devbox">
    `devbox ssh` opens an interactive shell inside the Devbox. The connection is tunneled through the Namespace API, so no public IP address or open port is involved.

    <Info>
      Connecting to a stopped Devbox starts it first, and your files persist across stop and start cycles.
    </Info>

    <Tabs>
      <Tab title="Interactive">
        Omit the name and the CLI lists your Devboxes so you can pick one:

        ```bash theme={null}
        devbox ssh
        ```
      </Tab>

      <Tab title="Non-interactive">
        Pass the name to connect straight to a known Devbox:

        ```bash theme={null}
        devbox ssh my-devbox
        ```

        Run `devbox list` to see the Devboxes in your workspace and their state.
      </Tab>
    </Tabs>

    And run `ls` to see the cloned files:

    ```bash theme={null}
    ls
    ```
  </Step>

  <Step title="Open an IDE">
    Open the Devbox in a local editor:

    ```bash theme={null}
    devbox open-ide my-devbox
    ```

    See [IDEs](/docs/devbox/ides) for JetBrains, and [Remote Development](/docs/devbox/remote-development#configure-ssh) for using your own SSH config.
  </Step>
</Steps>

## Run a command without a shell

`devbox exec` runs a single command in the Devbox and streams the output back to your terminal:

```bash theme={null}
devbox exec my-devbox -- go build ./...
```

For commands that outlive your connection, see [Executing Commands](/docs/devbox/exec) and [Running long tasks](/docs/guides/devbox/long-running-tasks).

## Devbox CLI reference

Every command, flag, and option is documented in the reference, starting with [installation and updates](/docs/reference/devbox-cli/installation).

<Columns cols={3}>
  <Card title="devbox create" icon="plus" href="/docs/reference/devbox-cli/create">
    Images, sizes, Blueprints, and specification files.
  </Card>

  <Card title="devbox ssh" icon="terminal" href="/docs/reference/devbox-cli/ssh">
    Interactive sessions, remote commands, and agent forwarding.
  </Card>

  <Card title="devbox exec" icon="play" href="/docs/reference/devbox-cli/exec">
    Detached executions and retrieving their logs.
  </Card>
</Columns>

## Set this up with a coding agent

Namespace publishes Devbox agent skills in [`namespacelabs/agent-skills`](https://github.com/namespacelabs/agent-skills). A skill is an instruction pack that gives a coding agent a repeatable workflow for Devboxes: installing the CLI, logging in, creating and hydrating them, running commands, and tearing them down.

Hand your agent the prompt below. It installs the skill, then follows it. You will need to complete the login in your browser when the agent reaches that step.

```text wrap Agent Prompt theme={null}
Install the Namespace devboxes agent skill, then use it to set me up:

  npx skills add namespacelabs/agent-skills

Following that skill:

1. Install the Devbox CLI for my operating system, then confirm it works.
2. Log me in to Devbox, then verify that the login succeeded.
3. Create a Devbox for me at size `m`. If we are working in a git repository,
   check that repository out in the Devbox so my code is already there.
4. List my Devboxes, then report the new one's name, its state, and how I can
   open a shell in it.

Do not delete or stop any Devbox that already exists in my workspace.
```

To install the skill yourself, or to install it globally rather than per project, see [Agent Skills](/docs/devbox/agent-skills).

## Next steps

<Columns cols={3}>
  <Card title="Remote Development" icon="monitor" href="/docs/devbox/remote-development">
    SSH access and SSH config for a Devbox.
  </Card>

  <Card title="Devbox Lifecycle" icon="refresh-cw" href="/docs/devbox/lifecycle">
    Listing, starting, stopping, idleness, and deleting.
  </Card>

  <Card title="IDEs" icon="code" href="/docs/devbox/ides">
    Open a Devbox in VS Code, Cursor, JetBrains, or Zed.
  </Card>
</Columns>
