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
Metadata
Release files for workshop-client 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| workshop_client-0.1.0.tar.gz | 16.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| workshop_client-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.1 kB
Release files / workshop_client-0.1.0.tar.gz
| Download URL | workshop_client-0.1.0.tar.gz |
|---|---|
| Size | 16.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
49131c7b82a4ebebd139c51ffaaac14b5d00f7083aef0ff31a2066ad15356cca
|
|
BLAKE2b-256 checksum How to use checksums |
ee779537684c459b9cef662d0ec01a5fc0177b27e3c420f23841c36bf830c0a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|
Release files / workshop_client-0.1.0-py3-none-any.whl
| Download URL | workshop_client-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c86bc553afe59f866271b843d0c7f80a8d83b99daf25fdc516c40f163370f5b2
|
|
BLAKE2b-256 checksum How to use checksums |
7530934a484dd784c355a5bae1c77f310471bb8f20f328762cdd0eb6e007dc5f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|