# Quickstart

> Sign in, get an API key, and create, use, reach, stop, and delete your first machine with the CLI, TypeScript, or Python.

This guide takes you from a new account to a running machine and back. Each step shows the `vy` CLI, the TypeScript SDK, and the Python SDK; pick a tab once and every example on the page follows it. Port and SSH steps use the HTTP API so every client can follow them; the CLI also has `vy ports` and `vy ssh`.

## 1. Sign in

Open the VMYard console and sign in with one of the methods it offers, such as GitHub, Google, or a 6-digit code sent to your email. Your first sign-in creates your VMYard user. See [Sign-in methods](/docs/guides/sign-in).

> [!NOTE]
> Organizations are set up by your VMYard operator. If the console says **No organizations available**, ask them to add you; machines, keys, and billing all belong to an organization.

## 2. Install the tools

The CLI and SDKs are in private preview and are not published to npm or PyPI. Get access to the [erphq/vmyard-sdk](https://github.com/erphq/vmyard-sdk) repository from your VMYard contact, then build from a checkout:

```sh tab="CLI"
git clone https://github.com/erphq/vmyard-sdk.git
cd vmyard-sdk && npm ci && npm run build
npm install -g ./cli
```

```sh tab="TypeScript"
git clone https://github.com/erphq/vmyard-sdk.git
cd vmyard-sdk && npm ci && npm run build
cd your-project && npm install ../vmyard-sdk/typescript
```

```sh tab="Python"
git clone https://github.com/erphq/vmyard-sdk.git
pip install ./vmyard-sdk/python
```

The CLI needs Node.js 20 or newer, the TypeScript SDK Node.js 20 or newer, and the Python SDK Python 3.9 or newer. None of them has a default server: set `VMYARD_API_URL` to your API origin.

```sh
export VMYARD_API_URL=https://api.example.com   # your VMYard API origin
```

## 3. Get an API key

With the CLI, `vy login` opens the console, you approve the request, and the CLI stores a new API key. See [CLI device login](/docs/guides/cli-login).

```sh tab="CLI"
vy login
vy whoami
```

```ts tab="TypeScript"
// Create a key in the console: API keys → Create key → preset "Create and use".
// The SDK reads VMYARD_API_KEY and VMYARD_API_URL from the environment.
import { VMYard } from "@vmyard/sdk";

const vy = new VMYard();
console.log(await vy.me());
```

```python tab="Python"
# Create a key in the console: API keys -> Create key -> preset "Create and use".
# The SDK reads VMYARD_API_KEY and VMYARD_API_URL from the environment.
from vmyard import VMYard

vy = VMYard()
print(vy.me())
```

For the SDKs, create a key in the console under **API keys** with the **Create and use** preset and export it as `VMYARD_API_KEY`. The secret (`vmy_…`) is shown once. See [API keys and presets](/docs/guides/api-keys).

## 4. Create a machine

Pick a plan from the catalog (`vy plans`), or let the client use the first one. `--auto-stop 2` stops the machine two hours after it starts so a forgotten machine doesn't keep billing.

```sh tab="CLI"
vy plans
vy new --plan small --name dev --auto-stop 2 --wait
```

```ts tab="TypeScript"
const machine = await vy.machines.create({
  name: "dev",
  plan: "small",
  autoStopAfterSeconds: 2 * 3600,
}); // resolves when the create operation succeeds
console.log(machine.data.id, machine.data.observed_state);
```

```python tab="Python"
machine = vy.machines.create(name="dev", plan="small", auto_stop_after_seconds=2 * 3600)
print(machine.id, machine.state)
```

Creating returns an operation; the CLI (with `--wait`) and the SDKs wait until it succeeds, which means VMYard observed the machine running. See [Operations and idempotency](/docs/concepts/operations).

## 5. Run a command

```sh tab="CLI"
vy exec dev -- uname -a
vy exec dev -c 'cd /work && echo hello > hello.txt && ls -l'
```

```ts tab="TypeScript"
const result = await machine.exec("uname -a");
console.log(result.exitCode, result.stdout);

for await (const frame of machine.exec(["ls", "-l", "/work"], { stream: true })) {
  if (frame.type === "stdout") process.stdout.write(frame.data);
}
```

```python tab="Python"
result = machine.exec("uname -a")
print(result.exit_code, result.stdout)

with machine.exec(["ls", "-l", "/work"], stream=True) as stream:
    for frame in stream:
        if frame.type == "stdout":
            print(frame.data.decode(), end="")
```

The CLI streams output as it arrives and exits with the command's exit code. See [Running commands](/docs/guides/commands).

## 6. Open a port

Start a web server as a [background command](/docs/guides/background-commands), then expose its port. Private ports (the default) need a short-lived token.

```ts tab="TypeScript"
await machine.commands.start("python3 -m http.server 8080");
```

```python tab="Python"
machine.commands.start("python3 -m http.server 8080")
```

```sh tab="curl"
MACHINE_ID=$(vy get dev --json | jq -r .id)

curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/commands" \
  -H "Authorization: Bearer $VMYARD_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"command": "python3 -m http.server 8080"}'
```

```sh title="Expose port 8080 and get a link (HTTP API)"
MACHINE_ID=$(vy get dev --json | jq -r .id)   # or machine.data.id in the SDKs

curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports" \
  -H "Authorization: Bearer $VMYARD_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"port": 8080}'

curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports/8080/token" \
  -H "Authorization: Bearer $VMYARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ttl_seconds": 900}'
```

Exposing a port is an operation: follow the returned `operation_url` until it succeeds. Open `url_with_token` from the token response in a browser. The example assumes the image has `python3`; use any server your image provides. See [Ports and private URLs](/docs/guides/ports).

> [!NOTE]
> When you signed in with `vy login`, the key lives in the CLI's config file rather than in `VMYARD_API_KEY`. For the HTTP examples, export a key you created in the console.

## 7. Connect over SSH

Install your public key; VMYard allocates an SSH gateway port and reports how to connect in the machine's `ssh` field.

```sh title="Install a key and connect (HTTP API)"
curl -X PUT "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ssh-key" \
  -H "Authorization: Bearer $VMYARD_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d "{\"public_key\": \"$(cat ~/.ssh/id_ed25519.pub)\"}"

# After the operation succeeds:
vy get dev --json | jq .ssh      # {"host": "...", "port": 2201, "user": "vmyard"}
ssh -p 2201 vmyard@<host>
```

See [SSH](/docs/guides/ssh).

## 8. Stop and start

Stopping ends metering. Files in `/work` are kept, and starting brings the same machine back.

```sh tab="CLI"
vy stop dev --wait
vy start dev --wait
```

```ts tab="TypeScript"
await machine.stop();
await machine.start();
```

```python tab="Python"
machine.stop()
machine.start()
```

## 9. Delete the machine

```sh tab="CLI"
vy rm dev --wait
```

```ts tab="TypeScript"
await machine.delete();
```

```python tab="Python"
machine.delete()
```

Deleting is permanent. The delete operation succeeds once VMYard confirms the machine is gone from its host.

## Next steps

- Check what you spent with `vy usage` and read [Usage, billing, and limits](/docs/guides/billing).
- Get notified when machines become ready or fail with [webhooks](/docs/guides/webhooks).
- Browse the [CLI reference](/docs/cli) and the [API reference](/docs/api).
