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

# Commands And Processes

> Run commands, stream output, manage background processes, and send stdin.

Use `machine.commands` for foreground and background execution inside a running
machine.

Use `shell=True` for authored shell snippets. Use `args=[...]` for exact argv;
`shell=True` cannot be combined with `args`.

## Foreground commands

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
from nullspace import Machine

with Machine.create() as machine:
    result = machine.commands.run(
        "echo $GREETING",
        shell=True,
        envs={"GREETING": "hello"},
        cwd="/workspace",
        timeout=30,
    )
    print(result.stdout.strip(), result.exit_code)
```

`CommandResult` includes `exit_code`, `stdout`, `stderr`, and optional `pid`.
Non-zero command exits are returned in `exit_code`; they are not raised as SDK
exceptions.

## Background processes

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
process = machine.commands.run("python3 -m http.server 8080", shell=True, background=True)
try:
    print(machine.commands.get_logs(process.pid).stdout)
finally:
    process.kill()
    result = process.wait()
    print(result.exit_code)
```

The returned `BackgroundCommand` exposes `pid`, `wait()`, `kill()`,
`get_logs()`, `disconnect()`, and iteration over new stdout/stderr chunks.

Pass callbacks with `background=True` when you want live output while the
process keeps running:

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
process = machine.commands.run(
    "python3 -u worker.py",
    shell=True,
    background=True,
    on_stdout=lambda chunk: print(chunk, end=""),
)
process.disconnect()
```

## Streaming

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
def on_stdout(chunk: str) -> None:
    print(chunk, end="")

result = machine.commands.run_streaming(
    "python3 -u script.py",
    shell=True,
    on_stdout=on_stdout,
)
```

You can also pass `on_stdout` or `on_stderr` directly to
`machine.commands.run(...)` to use the streaming path.

Reconnect to an existing running PID:

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
handle = machine.commands.connect(process.pid, on_stdout=on_stdout)
result = handle.wait()
```

## Stdin and argv

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
proc = machine.commands.run("python3 -i", shell=True, background=True)
machine.commands.send_stdin(proc.pid, "print('hello')\n")
machine.commands.send_stdin(proc.pid, "exit()\n")

exact = machine.commands.run("python3", args=["-c", "print('argv')"])
print(exact.stdout.strip())
```

Command `cwd` values must be valid machine paths and cannot target
runtime-managed paths under `/workspace/.nullspace`.

Process APIs return `ProcessInfo(pid, command, running)` and
`CommandLogs(stdout, stderr, output, exit_code)`.

## Async

`AsyncMachine` exposes the same commands namespace with awaitable methods:

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
from nullspace import AsyncMachine

async with await AsyncMachine.create() as machine:
    result = await machine.commands.run("echo async", shell=True)
    print(result.stdout.strip())

    proc = await machine.commands.run("sleep 10", shell=True, background=True)
    await proc.kill()
```

## Git helpers

`machine.git` includes first-class helpers for common repository workflows:

```python theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
machine.git.configure_user(
    "Example User",
    "user@example.com",
    scope="local",
    path="/tmp/project",
)
machine.git.commit("Update docs", files=["README.md"], path="/tmp/project")
```

Helpers include `clone()`, `pull()`, `checkout()`, `create_branch()`,
`delete_branch()`, `branches()`, `add()`, `commit()`, `push()`, `status()`,
`diff()`, `remote_add()`, `set_config()`, `get_config()`, `configure_user()`,
`add_ssh_key()`, and `dangerously_authenticate()`. `commit()` uses the repo's
configured Git identity unless you pass `author_name` and `author_email` for a
one-off commit.

Concept: [Exec](../../concepts/exec). API reference:
[execCommand](../../api-reference), [listProcesses](../../api-reference),
[sendStdin](../../api-reference), [getProcessLogs](../../api-reference), and
[killProcess](../../api-reference).
