Projects, Workspaces & Volumes
Organize work into projects, spin up development environments, and manage persistent storage.
Overview
Three resources work together:
- Projects (
client.projects) -- Top-level containers that group workspaces, volumes, and collaborators. - Workspaces (
client.workspaces) -- On-demand development environments with configurable images and resources. - Volumes (
client.volumes) -- Persistent storage that survives workspace restarts, attachable to projects and workspaces.
Projects
Basic Usage
from strongly import Strongly
client = Strongly()
# List all projects
for project in client.projects.list():
print(f"{project.name} — {project.status}")
# Get a specific project
project = client.projects.retrieve("proj-abc123")
print(f"{project.name}: {project.description}")
Creating a Project
from strongly import Strongly
client = Strongly()
project = client.projects.create({
"name": "customer-churn-analysis",
"description": "Predict and analyze customer churn patterns",
"category": "machine-learning",
"visibility": "organization",
"tags": ["ml", "churn", "production"],
})
print(f"Project ID: {project.id}")
print(f"Status: {project.status}")
Create Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | str | Yes | Project name |
description | str | Yes | Human-readable description |
category | str | No | Project category for organization |
visibility | str | No | Visibility level (e.g., private, organization) |
tags | list | No | Tags for filtering and search |
Updating a Project
from strongly import Strongly
client = Strongly()
updated = client.projects.update("proj-abc123", {
"description": "Updated churn analysis with new features",
"tags": ["ml", "churn", "production", "v2"],
})
print(f"Updated: {updated.name}")
Archiving and Restoring
from strongly import Strongly
client = Strongly()
# Archive a project
client.projects.archive("proj-abc123")
# Restore it later
client.projects.restore("proj-abc123")
Project Statistics
from strongly import Strongly
client = Strongly()
stats = client.projects.stats("proj-abc123")
print(f"Workspaces: {stats.workspace_count} ({stats.active_workspaces} active)")
print(f"Volumes: {stats.volume_count}")
print(f"Total storage: {stats.total_storage_gb} GB")
ProjectStats Fields
| Field | Type | Description |
|---|---|---|
workspace_count | int | Total number of workspaces in the project |
volume_count | int | Total number of volumes attached |
total_storage_gb | float | Total storage consumed in GB |
active_workspaces | int | Number of currently running workspaces |
Activity Feed
from strongly import Strongly
client = Strongly()
for event in client.projects.activity("proj-abc123", limit=20):
print(f"{event.created_at} — {event.action}")
Collaborators
Manage who has access to a project and their roles:
from strongly import Strongly
client = Strongly()
project_id = "proj-abc123"
# List collaborators
collabs = client.projects.collaborators(project_id)
for c in collabs:
role_label = "Owner" if c.is_owner else c.role
print(f" {c.email} — {role_label}")
# Add a collaborator
client.projects.add_collaborator(
project_id,
email="teammate@company.com",
role="editor",
)
# Change a collaborator's role
client.projects.update_collaborator_role(
project_id,
"user-xyz789",
role="viewer",
)
# Remove a collaborator
client.projects.remove_collaborator(project_id, "user-xyz789")
ProjectCollaborator Fields
| Field | Type | Description |
|---|---|---|
user_id | str | User identifier |
email | str | User email address |
role | str | Role within the project (e.g., editor, viewer) |
is_owner | bool | Whether this user is the project owner |
granted_at | str | When access was granted |
granted_by | str | Who granted access |
Project Volumes and Workspaces
List the volumes and workspaces that belong to a project:
from strongly import Strongly
client = Strongly()
project_id = "proj-abc123"
# List volumes attached to the project
volumes = client.projects.volumes(project_id)
for v in volumes:
print(f" {v.label} — {v.size_gb} GB ({v.status})")
# List workspaces in the project
for ws in client.projects.workspaces(project_id):
print(f" {ws.name} — {ws.status}")
Filtering and Searching
from strongly import Strongly
client = Strongly()
# Search by name
for p in client.projects.list(search="churn"):
print(p.name)
# Filter by status
for p in client.projects.list(status="active"):
print(f"{p.name} — {p.status}")
# Filter by category
for p in client.projects.list(category="machine-learning"):
print(p.name)
# Filter by tag
for p in client.projects.list(tag="production"):
print(p.name)
# Get all as a list
all_projects = client.projects.list().to_list()
Project Model
| Field | Type | Description |
|---|---|---|
id | str | Unique project identifier |
name | str | Project name |
description | str | Human-readable description |
status | str | Current status |
category | str | Project category |
visibility | str | Visibility level |
organization_id | str | Owning organization |
owner | str | Owner name |
owner_id | str | Owner user ID |
collaborators | list | List of collaborators |
shared_with | list | User IDs the project is shared with |
tags | list | Tags for filtering |
archived | bool | Whether the project is archived |
default_data_volume_id | str | Default volume for data storage |
attached_volume_ids | list | All attached volume IDs |
created_at | str | Creation timestamp |
updated_at | str | Last update timestamp |
Projects Method Reference
| Method | Description | Returns |
|---|---|---|
list(*, search=None, status=None, category=None, tag=None, limit=50) | List projects with optional filters | SyncPaginator[Project] |
create(body) | Create a new project | Project |
retrieve(project_id) | Get a project by ID | Project |
update(project_id, body) | Update project fields | Project |
delete(project_id) | Delete a project | dict |
archive(project_id) | Archive a project | dict |
restore(project_id) | Restore an archived project | dict |
stats(project_id) | Get project statistics | ProjectStats |
activity(project_id, *, limit=50, offset=0) | Get project activity feed | SyncPaginator[ProjectActivity] |
collaborators(project_id) | List project collaborators | List[ProjectCollaborator] |
add_collaborator(project_id, *, email, role, user_id=None) | Add a collaborator | dict |
remove_collaborator(project_id, user_id) | Remove a collaborator | dict |
update_collaborator_role(project_id, user_id, *, role) | Change a collaborator's role | dict |
volumes(project_id) | List project volumes | List[Volume] |
workspaces(project_id, *, limit=50) | List project workspaces | SyncPaginator[Workspace] |
Workspaces
Basic Usage
from strongly import Strongly
client = Strongly()
# List all workspaces
for ws in client.workspaces.list():
print(f"{ws.name} ({ws.environment_type}) — {ws.status}")
# Get a specific workspace
ws = client.workspaces.retrieve("ws-abc123")
print(f"{ws.name}: {ws.url}")
Creating a Workspace
from strongly import Strongly
client = Strongly()
ws = client.workspaces.create({
"name": "model-training",
"description": "GPU workspace for training churn models",
"environment_type": "jupyter",
"image": "strongly/pytorch:2.1-cuda",
"project_id": "proj-abc123",
"resources": {
"cpu": "4",
"memory": "16Gi",
"gpu": "1",
},
})
print(f"Workspace ID: {ws.id}")
print(f"Status: {ws.status}")
Create Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | str | Yes | Workspace name |
description | str | Yes | Human-readable description |
environment_type | str | Yes | Environment type (e.g., jupyter, vscode, rstudio) |
image | str | No | Container image to use |
resources | dict | No | Resource requests (cpu, memory, gpu) |
project_id | str | No | Project to attach the workspace to |
Lifecycle Management
from strongly import Strongly
client = Strongly()
ws_id = "ws-abc123"
# Start a stopped workspace
client.workspaces.start(ws_id)
# Stop a running workspace
client.workspaces.stop(ws_id)
# Restart a workspace
client.workspaces.restart(ws_id)
# Sync workspace files
client.workspaces.sync(ws_id)
Status and Monitoring
from strongly import Strongly
client = Strongly()
ws_id = "ws-abc123"
# Check readiness
status = client.workspaces.status(ws_id)
print(f"Phase: {status.phase}")
print(f"Ready: {status.ready}")
print(f"Message: {status.message}")
# View resource usage
metrics = client.workspaces.metrics(ws_id)
print(f"CPU: {metrics.cpu_usage}%")
print(f"Memory: {metrics.memory_usage}%")
print(f"GPU: {metrics.gpu_usage}%")
print(f"Disk: {metrics.disk_usage}%")
# Retrieve logs
logs = client.workspaces.logs(ws_id)
print(logs.content)
WorkspaceStatus Fields
| Field | Type | Description |
|---|---|---|
phase | str | Current phase (e.g., Running, Pending, Stopped) |
ready | bool | Whether the workspace is ready to use |
message | str | Human-readable status message |
conditions | list | Detailed condition entries |
WorkspaceMetrics Fields
| Field | Type | Description |
|---|---|---|
cpu_usage | float | CPU usage percentage |
memory_usage | float | Memory usage percentage |
gpu_usage | float | GPU usage percentage |
disk_usage | float | Disk usage percentage |
WorkspaceLogs Fields
| Field | Type | Description |
|---|---|---|
log_type | str | Type of log returned |
lines | list | Individual log lines |
content | str | Full log content as a string |
Waiting for a Workspace to Start
from strongly import Strongly
import time
client = Strongly()
ws = client.workspaces.create({
"name": "analysis-env",
"description": "Data analysis workspace",
"environment_type": "jupyter",
})
print(f"Workspace {ws.id} created. Waiting for it to start...")
while True:
status = client.workspaces.status(ws.id)
if status.ready:
ws_detail = client.workspaces.retrieve(ws.id)
print(f"Workspace is ready at {ws_detail.url}")
break
print(f" Phase: {status.phase} — {status.message}")
time.sleep(5)
Filtering and Searching
from strongly import Strongly
client = Strongly()
# Search by name
for ws in client.workspaces.list(search="training"):
print(ws.name)
# Filter by status
for ws in client.workspaces.list(status="running"):
print(f"{ws.name} — {ws.url}")
# Filter by project
for ws in client.workspaces.list(project_id="proj-abc123"):
print(f"{ws.name} — {ws.status}")
Workspace Model
| Field | Type | Description |
|---|---|---|
id | str | Unique workspace identifier |
name | str | Workspace name |
description | str | Human-readable description |
status | str | Current status |
environment_type | str | Environment type (jupyter, vscode, etc.) |
image | str | Container image |
resources | dict | Resource allocations |
organization_id | str | Owning organization |
owner | str | Owner name |
owner_id | str | Owner user ID |
url | str | Access URL when running |
project_id | str | Parent project ID |
volume_ids | list | Attached volume IDs |
created_at | str | Creation timestamp |
updated_at | str | Last update timestamp |
Workspaces Method Reference
| Method | Description | Returns |
|---|---|---|
list(*, search=None, status=None, project_id=None, limit=50) | List workspaces with optional filters | SyncPaginator[Workspace] |
create(body) | Create a new workspace | Workspace |
retrieve(workspace_id) | Get a workspace by ID | Workspace |
update(workspace_id, body) | Update workspace fields | Workspace |
delete(workspace_id) | Delete a workspace | dict |
start(workspace_id) | Start a stopped workspace | dict |
stop(workspace_id) | Stop a running workspace | dict |
restart(workspace_id) | Restart a workspace | dict |
status(workspace_id) | Get workspace status | WorkspaceStatus |
metrics(workspace_id) | Get resource usage metrics | WorkspaceMetrics |
logs(workspace_id, *, type=None) | Retrieve workspace logs | WorkspaceLogs |
sync(workspace_id) | Sync workspace files | dict |
Volumes
Basic Usage
from strongly import Strongly
client = Strongly()
# List all volumes
for vol in client.volumes.list():
print(f"{vol.label} — {vol.size_gb} GB ({vol.status})")
# Get a specific volume
vol = client.volumes.retrieve("vol-abc123")
print(f"{vol.label}: {vol.mount_path}")
Creating a Volume
from strongly import Strongly
client = Strongly()
vol = client.volumes.create({
"project_id": "proj-abc123",
"label": "training-data",
"size_gb": 50.0,
"description": "Training datasets for churn models",
"type": "data",
"mount_path": "/data/training",
})
print(f"Volume ID: {vol.id}")
print(f"Status: {vol.status}")
Create Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
project_id | str | Yes | Project to attach the volume to |
label | str | Yes | Display name |
size_gb | float | Yes | Storage size in gigabytes |
description | str | No | Human-readable description |
type | str | No | Volume type (e.g., data, model, scratch) |
mount_path | str | No | Mount path inside workspaces |
Syncing and Sharing
from strongly import Strongly
client = Strongly()
vol_id = "vol-abc123"
# Sync volume contents
client.volumes.sync(vol_id)
# Make a volume available to the entire organization
client.volumes.make_shared(vol_id)
# Browse shared volumes
for vol in client.volumes.list_shared():
print(f"{vol.label} — {vol.size_gb} GB (owner: {vol.owner})")
Filtering and Searching
from strongly import Strongly
client = Strongly()
# Search by name
for vol in client.volumes.list(search="training"):
print(vol.label)
# Filter by type
for vol in client.volumes.list(type="data"):
print(f"{vol.label} — {vol.size_gb} GB")
# Filter by project
for vol in client.volumes.list(project_id="proj-abc123"):
print(f"{vol.label} — {vol.mount_path}")
# List shared volumes with search
for vol in client.volumes.list_shared(search="datasets"):
print(f"{vol.label} — shared by {vol.owner}")
Volume Model
| Field | Type | Description |
|---|---|---|
id | str | Unique volume identifier |
label | str | Display name |
name | str | System name |
description | str | Human-readable description |
status | str | Current status |
type | str | Volume type |
volume_type | str | Underlying volume type |
size_gb | float | Storage size in GB |
mount_path | str | Mount path inside workspaces |
organization_id | str | Owning organization |
owner | str | Owner name |
owner_id | str | Owner user ID |
project_id | str | Parent project ID |
is_shared | bool | Whether the volume is shared |
shared | bool | Sharing flag |
shared_with | list | Users the volume is shared with |
created_at | str | Creation timestamp |
updated_at | str | Last update timestamp |
Volumes Method Reference
| Method | Description | Returns |
|---|---|---|
list(*, search=None, type=None, project_id=None, limit=50) | List volumes with optional filters | SyncPaginator[Volume] |
create(body) | Create a new volume | Volume |
retrieve(volume_id) | Get a volume by ID | Volume |
update(volume_id, body) | Update volume fields | Volume |
delete(volume_id) | Delete a volume | dict |
sync(volume_id) | Sync volume contents | dict |
make_shared(volume_id) | Share volume with the organization | dict |
list_shared(*, search=None, limit=50) | List shared volumes | SyncPaginator[Volume] |
Complete Example
from strongly import Strongly
import time
def main():
client = Strongly()
# --- Create a project ---
print("Creating project...")
project = client.projects.create({
"name": "fraud-detection",
"description": "ML pipeline for detecting fraudulent transactions",
"category": "machine-learning",
"visibility": "organization",
"tags": ["ml", "fraud", "production"],
})
project_id = project.id
print(f"Project ID: {project_id}")
# --- Add a collaborator ---
print("\nAdding collaborator...")
client.projects.add_collaborator(
project_id,
email="data-scientist@company.com",
role="editor",
)
collabs = client.projects.collaborators(project_id)
for c in collabs:
print(f" {c.email} — {c.role}")
# --- Create a data volume ---
print("\nCreating volume...")
vol = client.volumes.create({
"project_id": project_id,
"label": "fraud-datasets",
"size_gb": 100.0,
"description": "Transaction datasets for training",
"type": "data",
"mount_path": "/data/fraud",
})
print(f"Volume ID: {vol.id} ({vol.size_gb} GB)")
# --- Create a workspace ---
print("\nCreating workspace...")
ws = client.workspaces.create({
"name": "fraud-training",
"description": "GPU environment for model training",
"environment_type": "jupyter",
"project_id": project_id,
"resources": {
"cpu": "8",
"memory": "32Gi",
"gpu": "1",
},
})
print(f"Workspace ID: {ws.id}")
# Wait for workspace to be ready
while True:
status = client.workspaces.status(ws.id)
if status.ready:
ws_detail = client.workspaces.retrieve(ws.id)
print(f"Workspace ready at {ws_detail.url}")
break
print(f" Phase: {status.phase}...")
time.sleep(5)
# --- Check project stats ---
stats = client.projects.stats(project_id)
print(f"\nProject stats:")
print(f" Workspaces: {stats.workspace_count} ({stats.active_workspaces} active)")
print(f" Volumes: {stats.volume_count}")
print(f" Storage: {stats.total_storage_gb} GB")
# --- Monitor workspace resources ---
metrics = client.workspaces.metrics(ws.id)
print(f"\nWorkspace metrics:")
print(f" CPU: {metrics.cpu_usage}%")
print(f" Memory: {metrics.memory_usage}%")
print(f" GPU: {metrics.gpu_usage}%")
# --- View activity ---
print("\nRecent activity:")
for event in client.projects.activity(project_id, limit=10):
print(f" {event.created_at} — {event.action}")
# --- Cleanup ---
print("\nStopping workspace...")
client.workspaces.stop(ws.id)
if __name__ == "__main__":
main()