Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "steel-cli"
version = "0.5.0-preview.1"
version = "0.5.0-preview.2"
edition = "2024"
description = "Steel CLI - Browser automation for AI agents"
license = "MIT"
Expand Down
108 changes: 108 additions & 0 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ Steel CLI - browser automation for AI agents. This file is generated from `steel
- [steel computer use](#steel-computer-use)
- [steel computer exec](#steel-computer-exec)
- [steel computer ssh](#steel-computer-ssh)
- [steel computer checkpoint](#steel-computer-checkpoint)
- [steel computer quota](#steel-computer-quota)
- [steel checkpoint](#steel-checkpoint)
- [steel checkpoint list](#steel-checkpoint-list)
- [steel checkpoint get](#steel-checkpoint-get)
- [steel checkpoint delete](#steel-checkpoint-delete)
- [steel checkpoint restore](#steel-checkpoint-restore)
- [steel init](#steel-init)
- [steel login](#steel-login)
- [steel logout](#steel-logout)
Expand Down Expand Up @@ -1550,6 +1557,8 @@ steel computer
- `use`: Remember a computer as the default for other commands
- `exec`: Run one command in a computer
- `ssh`: Open an SSH session to a computer
- `checkpoint`: Save a computer as a checkpoint
- `quota`: Show how many computers and checkpoints you can have

## steel computer create

Expand Down Expand Up @@ -1700,6 +1709,105 @@ steel computer ssh
Example: `steel computer ssh <computer-id>`
Streaming: websocket `/v1/computers/{id}/ssh`

## steel computer checkpoint

Save a computer as a checkpoint

### Usage

```bash
steel computer checkpoint
```

### Parameters

- `computer_id` (string, optional): Computer ID (defaults to STEEL_COMPUTER_ID or `steel computer use`)
- `--name` (string, optional): Name for the checkpoint
- `--wait` (boolean, optional): Wait until the checkpoint is ready

## steel computer quota

Show how many computers and checkpoints you can have

### Usage

```bash
steel computer quota
```

## steel checkpoint

Computer checkpoints: list, restore, delete

### Usage

```bash
steel checkpoint
```

### Subcommands

- `list`: List checkpoints
- `get`: Get one checkpoint
- `delete`: Delete a checkpoint
- `restore`: Start a new computer from a checkpoint

## steel checkpoint list

List checkpoints

### Usage

```bash
steel checkpoint list
```

## steel checkpoint get

Get one checkpoint

### Usage

```bash
steel checkpoint get
```

### Parameters

- `checkpoint_id` (string, required): Checkpoint ID

## steel checkpoint delete

Delete a checkpoint

### Usage

```bash
steel checkpoint delete
```

### Parameters

- `checkpoint_id` (string, required): Checkpoint ID

## steel checkpoint restore

Start a new computer from a checkpoint

### Usage

```bash
steel checkpoint restore
```

### Parameters

- `checkpoint_id` (string, required): Checkpoint ID
- `--timeout` (string, optional): Stop the computer after this many seconds of running time
- `--auto-pause` (boolean, optional): Pause instead of stopping when the timeout is reached
- `--wait` (boolean, optional): Wait until the computer is running
- `--use` (boolean, optional): Make the new computer the default for other commands

## steel init

One-command onboarding: login + verify + install agent skills
Expand Down
7 changes: 7 additions & 0 deletions docs/references/steel-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ For generated flags and argument schemas, use [../cli-reference.md](../cli-refer
- `steel computer use`: remember a default computer so other commands need no id.
- `steel computer exec -- <command>`: run one command; output streams and the exit code is returned.
- `steel computer ssh`: open an SSH shell, or run a command over SSH with `-- <command>`.
- `steel computer checkpoint`: save a computer's disk and memory as a checkpoint.
- `steel computer quota`: show how many computers and checkpoints the account can have.

### Checkpoint Commands

- `steel checkpoint list`, `steel checkpoint get`, `steel checkpoint delete`: inspect and remove checkpoints.
- `steel checkpoint restore`: start a new computer from a ready checkpoint.

### Credentials Commands

Expand Down
149 changes: 149 additions & 0 deletions src/api/checkpoints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
use serde_json::{Value, json};

use crate::api::client::{ApiError, SteelClient};
use crate::api::computers::computer_path;
use crate::config::auth::Auth;
use crate::config::settings::ApiMode;

pub fn checkpoint_path(id: &str) -> String {
format!("/checkpoints/{}", urlencoding::encode(id))
}

#[derive(Debug, Default, Clone)]
pub struct RestoreCheckpoint {
pub timeout_seconds: Option<u32>,
pub auto_pause: Option<bool>,
}

impl RestoreCheckpoint {
pub fn body(&self) -> Value {
let mut body = json!({});
if let Some(timeout) = self.timeout_seconds {
body["timeoutSeconds"] = json!(timeout);
}
if let Some(auto_pause) = self.auto_pause {
body["autoPause"] = json!(auto_pause);
}
body
}
}

impl SteelClient {
pub async fn create_checkpoint(
&self,
base_url: &str,
mode: ApiMode,
auth: &Auth,
computer_id: &str,
name: Option<&str>,
) -> Result<Value, ApiError> {
let mut body = json!({});
if let Some(name) = name {
body["name"] = json!(name);
}
self.request(
base_url,
mode,
reqwest::Method::POST,
&format!("{}/checkpoints", computer_path(computer_id)),
Some(body),
auth,
)
.await
}

pub async fn list_checkpoints(
&self,
base_url: &str,
mode: ApiMode,
auth: &Auth,
) -> Result<Value, ApiError> {
self.request(
base_url,
mode,
reqwest::Method::GET,
"/checkpoints",
None,
auth,
)
.await
}

pub async fn get_checkpoint(
&self,
base_url: &str,
mode: ApiMode,
auth: &Auth,
id: &str,
) -> Result<Value, ApiError> {
self.request(
base_url,
mode,
reqwest::Method::GET,
&checkpoint_path(id),
None,
auth,
)
.await
}

pub async fn delete_checkpoint(
&self,
base_url: &str,
mode: ApiMode,
auth: &Auth,
id: &str,
) -> Result<Value, ApiError> {
self.request(
base_url,
mode,
reqwest::Method::DELETE,
&checkpoint_path(id),
None,
auth,
)
.await
}

pub async fn restore_checkpoint(
&self,
base_url: &str,
mode: ApiMode,
auth: &Auth,
id: &str,
request: &RestoreCheckpoint,
) -> Result<Value, ApiError> {
self.request(
base_url,
mode,
reqwest::Method::POST,
&format!("{}/computers", checkpoint_path(id)),
Some(request.body()),
auth,
)
.await
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn paths_are_encoded() {
assert_eq!(checkpoint_path("ckpt a"), "/checkpoints/ckpt%20a");
}

#[test]
fn restore_body_only_carries_given_options() {
assert_eq!(RestoreCheckpoint::default().body(), json!({}));
let request = RestoreCheckpoint {
timeout_seconds: Some(120),
auto_pause: Some(true),
};
assert_eq!(
request.body(),
json!({ "timeoutSeconds": 120, "autoPause": true })
);
}
}
17 changes: 17 additions & 0 deletions src/api/computers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ impl SteelClient {
.await
}

pub async fn get_computer_quota(
&self,
base_url: &str,
mode: ApiMode,
auth: &Auth,
) -> Result<Value, ApiError> {
self.request(
base_url,
mode,
reqwest::Method::GET,
"/computers/quota",
None,
auth,
)
.await
}

pub async fn get_computer(
&self,
base_url: &str,
Expand Down
1 change: 1 addition & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod checkpoints;
pub mod client;
pub mod computers;
pub mod generated;
Expand Down
Loading
Loading