Python client library for Workshop Cloud API
Project description
workshop-client
Python client library for Workshop Cloud API
Clean, type-safe Python interface to Workshop Cloud - persistent context and memory for Claude Code.
Features
- ✅ Type-safe: Full Pydantic models for all API entities
- ✅ Mock backend: Develop and test without real API
- ✅ Async-ready: Built on httpx (async support coming soon)
- ✅ Well-tested: Comprehensive test coverage
- ✅ Python 3.8+: Wide compatibility
Installation
pip install workshop-client
For E2EE (zero-knowledge encryption) support:
pip install workshop-client[crypto]
Quick Start
Using Mock Backend (No API Required)
Perfect for development and testing:
from workshop_client import WorkshopClient
# Mock mode - no network requests
client = WorkshopClient(api_key="wks_mock", mock=True)
# Create a project
project = client.create_project(
name="my-app",
display_name="My App",
description="Mobile app project"
)
# Add entries
client.create_entry(
project="my-app",
type="decision",
content="Use PostgreSQL for database",
reasoning="Better ACID guarantees",
tags=["database", "architecture"]
)
client.create_entry(
project="my-app",
type="gotcha",
content="API rate limit is 300 req/min",
tags=["api", "performance"]
)
# Search
results = client.search("my-app", "PostgreSQL")
print(f"Found {results.total} results")
# Smart 'why' query (prioritizes decisions)
why = client.why("my-app", "PostgreSQL")
if why.primary_answer:
print(f"Why PostgreSQL? {why.primary_answer.reasoning}")
# Get context summary
context = client.get_context("my-app")
print(f"Goals: {len(context.active_goals)}")
print(f"Next steps: {len(context.next_steps)}")
Using Real API
from workshop_client import WorkshopClient
# Real API mode
client = WorkshopClient(api_key="wks_your_api_key_here")
# Same API as mock mode
project = client.create_project(...)
entry = client.create_entry(...)
API Overview
Projects
# List all projects
projects = client.list_projects()
# Get project details
project = client.get_project("my-app")
# Create project
project = client.create_project(
name="my-app",
display_name="My App",
description="Optional description"
)
# Update project
project = client.update_project(
"my-app",
display_name="My Awesome App"
)
# Delete project
result = client.delete_project("my-app")
Entries
from workshop_client import EntryType
# Create entry
entry = client.create_entry(
project="my-app",
type=EntryType.NOTE, # or "note"
content="Important note",
tags=["tag1", "tag2"]
)
# Create decision with reasoning
entry = client.create_entry(
project="my-app",
type=EntryType.DECISION,
content="Use FastAPI for backend",
reasoning="Better async support and auto-docs",
tags=["backend"]
)
# List entries
entries = client.list_entries("my-app")
# Filter by type
decisions = client.list_entries("my-app", type=EntryType.DECISION)
# Filter by tags
tagged = client.list_entries("my-app", tags=["backend", "api"])
# Get specific entry
entry = client.get_entry("my-app", entry_id)
# Update entry
updated = client.update_entry(
"my-app",
entry_id,
content="Updated content",
tags=["new-tag"]
)
# Delete entry
result = client.delete_entry("my-app", entry_id)
Search & Context
# Full-text search
results = client.search(
"my-app",
query="authentication",
type=EntryType.DECISION,
limit=10
)
for result in results.results:
print(f"[{result.score:.2f}] {result.content}")
# Smart 'why' query (prioritizes decisions with reasoning)
why = client.why("my-app", "JWT")
if why.primary_answer:
print(f"Decision: {why.primary_answer.content}")
print(f"Reasoning: {why.primary_answer.reasoning}")
# Get context summary
context = client.get_context("my-app", days=30)
print(f"Last activity: {context.last_activity}")
print(f"Summary: {context.summary}")
print(f"Active goals: {len(context.active_goals)}")
User
# Get current user
user = client.get_user()
print(f"Email: {user.email}")
print(f"Tier: {user.subscription['tier']}")
print(f"API calls today: {user.usage['api_calls_today']}")
# Update user
user = client.update_user(
name="John Doe",
preferences={"timezone": "America/Los_Angeles"}
)
# Get audit log
audit = client.get_audit_log()
for log in audit.logs:
print(f"{log.timestamp}: {log.action} {log.resource}")
Entry Types
from workshop_client import EntryType
EntryType.NOTE # General notes
EntryType.DECISION # Architectural decisions (use with reasoning)
EntryType.GOTCHA # Constraints, limitations, things to avoid
EntryType.PREFERENCE # User/team preferences
EntryType.ANTIPATTERN # Patterns to avoid
EntryType.GOAL # Active goals
EntryType.NEXT # Next steps, TODOs
Error Handling
from workshop_client import (
WorkshopClient,
AuthenticationError,
NotFoundError,
ValidationError,
RateLimitError,
)
client = WorkshopClient(api_key="wks_...")
try:
entry = client.create_entry("my-app", "note", "Content")
except AuthenticationError:
print("Invalid API key")
except NotFoundError as e:
print(f"Not found: {e.message}")
except ValidationError as e:
print(f"Invalid input: {e.details}")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.details['retry_after']}s")
Context Manager
with WorkshopClient(api_key="wks_...") as client:
projects = client.list_projects()
# Client automatically closes on exit
Development
Run Tests
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# With coverage
pytest --cov=workshop_client --cov-report=term-missing
Mock Backend
The mock backend provides realistic API responses without requiring a real backend:
- In-memory storage (resets on restart)
- Pre-populated sample project with entries
- Full API support (projects, entries, search, context)
- Perfect for testing and development
client = WorkshopClient(api_key="anything", mock=True)
# All API calls work, but use in-memory storage
Roadmap
- E2EE (zero-knowledge encryption) support
- Async client (
AsyncWorkshopClient) - Batch operations
- Webhooks support
- Team management APIs
Links
- Homepage: https://workshop.cloud
- API Docs: https://docs.workshop.cloud
- GitHub: https://github.com/zachswift615/workshop-cloud
- PyPI: https://pypi.org/project/workshop-client
License
MIT License - see LICENSE file for details.
Contributing
Contributions welcome! Please open an issue or PR on GitHub.
Built with ❤️ for the Workshop Cloud community
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file workshop_client-0.1.0.tar.gz.
File metadata
- Download URL: workshop_client-0.1.0.tar.gz
- Upload date:
- Size: 16.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
49131c7b82a4ebebd139c51ffaaac14b5d00f7083aef0ff31a2066ad15356cca
|
|
| MD5 |
65a2fa4134823482cb18d9b246070aae
|
|
| BLAKE2b-256 |
ee779537684c459b9cef662d0ec01a5fc0177b27e3c420f23841c36bf830c0a7
|
File details
Details for the file workshop_client-0.1.0-py3-none-any.whl.
File metadata
- Download URL: workshop_client-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c86bc553afe59f866271b843d0c7f80a8d83b99daf25fdc516c40f163370f5b2
|
|
| MD5 |
fbb451fab4b0bcfd6b80a6b8f29fe631
|
|
| BLAKE2b-256 |
7530934a484dd784c355a5bae1c77f310471bb8f20f328762cdd0eb6e007dc5f
|