workshop-client 0.1.0
Python client library for Workshop Cloud API
License: MIT
Requires Python: >=3.8
Keywords: workshop, claude, ai, context, memory, api

# workshop-client

**Python client library for Workshop Cloud API**

Clean, type-safe Python interface to [Workshop Cloud](https://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

```bash
pip install workshop-client
```

For E2EE (zero-knowledge encryption) support:
```bash
pip install workshop-client[crypto]
```

## Quick Start

### Using Mock Backend (No API Required)

Perfect for development and testing:

```python
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

```python
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

```python
# 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

```python
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

```python
# 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

```python
# 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

```python
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

```python
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

```python
with WorkshopClient(api_key="wks_...") as client:
    projects = client.list_projects()
    # Client automatically closes on exit
```

## Development

### Run Tests

```bash
# 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

```python
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](LICENSE) file for details.

## Contributing

Contributions welcome! Please open an issue or PR on GitHub.

---

Built with ❤️ for the Workshop Cloud community