> ## 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.

# Run a Command in an Instance

> Create an instance and execute a command inside one of its containers with the CommandService.

`CommandService` runs a command inside a container and returns its output, with no ingress, SSH key, or port to configure.
Reaching it takes two clients: the Compute API creates the instance, and the response carries a per-instance regional endpoint that serves the command service.

<Steps titleSize="h3">
  <Step title="Create an instance that stays alive">
    The container has to be running when the command arrives, so give it a process that waits. `sleep` is enough.

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { loadDefaults } from "@namespacelabs/sdk/auth";
      import { createComputeClient } from "@namespacelabs/sdk/api/compute";
      import { timestampFromDate } from "@bufbuild/protobuf/wkt";

      const tokenSource = await loadDefaults();
      const computeClient = createComputeClient({ tokenSource });

      const created = await computeClient.compute.createInstance({
        shape: { virtualCpu: 2, memoryMegabytes: 4096, machineArch: "amd64" },
        documentedPurpose: "exec example",
        deadline: timestampFromDate(new Date(Date.now() + 10 * 60 * 1000)),
        containers: [
          {
            name: "ubuntu",
            imageRef: "ubuntu:latest",
            args: ["sleep", "600"],
          },
        ],
      });

      const instanceId = created.metadata!.instanceId;
      ```

      ```go Go theme={null}
      token, err := auth.LoadDefaults()
      if err != nil {
      	return err
      }

      computeClient, err := compute.NewClient(ctx, token)
      if err != nil {
      	return err
      }
      defer computeClient.Close()

      resp, err := computeClient.Compute.CreateInstance(ctx, &computepb.CreateInstanceRequest{
      	Shape: &computepb.InstanceShape{
      		VirtualCpu:      2,
      		MemoryMegabytes: 4 * 1024,
      		MachineArch:     "amd64",
      	},
      	DocumentedPurpose: "exec example",
      	Deadline:          timestamppb.New(time.Now().Add(10 * time.Minute)),
      	Containers: []*computepb.ContainerRequest{{
      		Name:       "ubuntu",
      		ImageRef:   "ubuntu:latest",
      		Entrypoint: []string{"sleep", "600"},
      		Args:       []string{},
      	}},
      })
      if err != nil {
      	return fmt.Errorf("failed to create instance: %w", err)
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Read the command service endpoint">
    The create response carries the endpoint in `extendedMetadata.commandServiceEndpoint`. It is a regional base URL, such as `https://zrh2.compute.namespaceapis.com`, and the region depends on where the instance landed rather than on where you called the API from. Read it from the response instead of hardcoding it.

    <CodeGroup>
      ```typescript TypeScript theme={null}
      const endpoint = created.extendedMetadata?.commandServiceEndpoint;
      if (!endpoint) {
        throw new Error("command service endpoint not available");
      }
      ```

      ```go Go theme={null}
      endpoint := resp.ExtendedMetadata.GetCommandServiceEndpoint()
      if endpoint == "" {
      	return fmt.Errorf("command service endpoint not available")
      }
      ```
    </CodeGroup>

    <Info>
      There is no need to call `WaitInstanceSync` first. The command service accepts the call as soon as the container is up, so going straight from `CreateInstance` to `RunCommandSync` is the fastest path from nothing to running code.
    </Info>
  </Step>

  <Step title="Open a client against that endpoint">
    The endpoint is a separate service from the Compute API, so it needs its own client carrying the same credential.

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { createClient } from "@connectrpc/connect";
      import { createConnectTransport } from "@connectrpc/connect-node";
      import { bearerAuthInterceptor } from "@namespacelabs/sdk/api";
      import { CommandService } from "@namespacelabs/sdk/proto/namespace/cloud/compute/v1beta/command_pb";

      const cmdTransport = createConnectTransport({
        httpVersion: "1.1",
        baseUrl: endpoint,
        useBinaryFormat: false,
        interceptors: [bearerAuthInterceptor(tokenSource)],
      });

      const cmdClient = createClient(CommandService, cmdTransport);
      ```

      ```go Go theme={null}
      import "namespacelabs.dev/integrations/nsc/grpcapi"

      conn, err := grpcapi.NewConnectionWithEndpoint(ctx, endpoint, token)
      if err != nil {
      	return fmt.Errorf("failed to connect to command service: %w", err)
      }
      defer conn.Close()

      cmdCli := computepb.NewCommandServiceClient(conn)
      ```
    </CodeGroup>
  </Step>

  <Step title="Run the command">
    `targetContainerName` selects which container in the instance runs the command. `RunCommandSync` blocks and returns the full output, while `RunCommand` streams it.

    <CodeGroup>
      ```typescript TypeScript theme={null}
      const result = await cmdClient.runCommandSync({
        instanceId,
        targetContainerName: "ubuntu",
        command: { command: ["uname", "-a"] },
      });

      const decoder = new TextDecoder();
      process.stdout.write(decoder.decode(result.stdout));

      if (result.exitCode !== 0) {
        throw new Error(`command exited with code ${result.exitCode}`);
      }
      ```

      ```go Go theme={null}
      result, err := cmdCli.RunCommandSync(ctx, &computepb.RunCommandRequest{
      	InstanceId:          resp.Metadata.InstanceId,
      	TargetContainerName: "ubuntu",
      	Command: &computepb.Command{
      		Command: []string{"uname", "-a"},
      	},
      })
      if err != nil {
      	return fmt.Errorf("failed to run command: %w", err)
      }

      fmt.Fprintf(os.Stdout, "%s", result.Stdout)

      if result.ExitCode != 0 {
      	return fmt.Errorf("command exited with code %d", result.ExitCode)
      }
      ```
    </CodeGroup>

    `stdout` and `stderr` are returned as bytes.
  </Step>
</Steps>

## Source

`go/exec` and `typescript/exec` in [github.com/namespacelabs/examples](https://github.com/namespacelabs/examples).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.