letswork 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(git -C /Users/saicharanrajoju/Desktop/LetsWork diff --name-only HEAD)",
5
+ "Bash(git -C /Users/saicharanrajoju/Desktop/LetsWork status)",
6
+ "Bash(git -C /Users/saicharanrajoju/Desktop/LetsWork diff docs/spec.md)",
7
+ "Bash(git -C /Users/saicharanrajoju/Desktop/LetsWork diff tests/__init__.py)",
8
+ "Bash(git -C /Users/saicharanrajoju/Desktop/LetsWork diff src/server.py)"
9
+ ]
10
+ }
11
+ }
@@ -0,0 +1,29 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ branches: [main]
7
+ jobs:
8
+ test:
9
+ runs-on: ${{ matrix.os }}
10
+ strategy:
11
+ matrix:
12
+ os: [ubuntu-latest, macos-latest, windows-latest]
13
+ python-version: ["3.10", "3.11", "3.12"]
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python ${{ matrix.python-version }}
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+
23
+ - name: Install dependencies
24
+ run: |
25
+ python -m pip install --upgrade pip
26
+ pip install -e ".[dev]"
27
+
28
+ - name: Run tests
29
+ run: pytest tests/ -v
@@ -0,0 +1,29 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Set up Python
15
+ uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+
19
+ - name: Install build tools
20
+ run: pip install build twine
21
+
22
+ - name: Build package
23
+ run: python -m build
24
+
25
+ - name: Publish to PyPI
26
+ env:
27
+ TWINE_USERNAME: __token__
28
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
29
+ run: twine upload dist/*
@@ -0,0 +1,35 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg-info/
7
+ *.egg
8
+ dist/
9
+ build/
10
+ eggs/
11
+
12
+ # Virtual environments
13
+ venv/
14
+ .venv/
15
+ env/
16
+
17
+ # IDE
18
+ .vscode/
19
+ .idea/
20
+ *.swp
21
+ *.swo
22
+ *~
23
+
24
+ # OS
25
+ .DS_Store
26
+ Thumbs.db
27
+
28
+ # Testing
29
+ .pytest_cache/
30
+ .coverage
31
+ htmlcov/
32
+
33
+ # Distribution
34
+ *.tar.gz
35
+ *.whl
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: letswork
3
+ Version: 0.1.0
4
+ Summary: Real-time collaborative coding via MCP — two developers, one codebase
5
+ Author: Sai Charan Rajoju
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: click>=8.1.0
9
+ Requires-Dist: mcp[cli]>=1.0.0
10
+ Requires-Dist: requests>=2.28.0
11
+ Requires-Dist: textual[syntax]>=0.50.0
12
+ Requires-Dist: websockets>=12.0
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest>=7.0; extra == 'dev'
15
+ Description-Content-Type: text/markdown
16
+
17
+ # LetsWork
18
+
19
+ **Google Docs for AI-assisted coding** — real-time collaboration on a local codebase using two independent Claude subscriptions.
20
+
21
+ ## What is LetsWork?
22
+
23
+ LetsWork is an MCP (Model Context Protocol) server that lets two developers work on the same local codebase simultaneously, each using their own Claude. One developer hosts, the other connects — with file-level locking to prevent conflicts.
24
+
25
+ ## How It Works
26
+
27
+ 1. Developer A (Host) runs `letswork start` in their project folder
28
+ 2. A secure HTTPS tunnel is created automatically via Cloudflare
29
+ 3. A one-time URL + secret token is generated
30
+ 4. Developer A shares both with Developer B (Guest)
31
+ 5. Developer B connects: `claude mcp add letswork --transport http <url>`
32
+ 6. Both can now read, write, and list files — with lock protection
33
+
34
+ ## Quick Start
35
+
36
+ ### Install
37
+ ```bash
38
+ pip install letswork
39
+ ```
40
+
41
+ ### Requirements
42
+
43
+ - Python >= 3.10
44
+ - [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) installed and available in PATH
45
+ - Git (recommended for conflict safety)
46
+
47
+ ### Host (Developer A)
48
+ ```bash
49
+ cd /path/to/your/project
50
+ letswork start
51
+ ```
52
+
53
+ You'll see:
54
+ ╔══════════════════════════════════════════════════╗
55
+ ║ LetsWork Session Active ║
56
+ ║ ║
57
+ ║ URL: https://abc123.trycloudflare.com ║
58
+ ║ Token: a1b2c3d4e5f6... ║
59
+ ║ ║
60
+ ║ Share both with your collaborator. ║
61
+ ║ Press Ctrl+C to end session. ║
62
+ ╚══════════════════════════════════════════════════╝
63
+
64
+ Share the URL and token with your collaborator via Slack, Discord, or text.
65
+
66
+ ### Guest (Developer B)
67
+ ```bash
68
+ claude mcp add letswork --transport http <URL_FROM_HOST>
69
+ ```
70
+
71
+ Use the token when prompted. You now have full access to the shared codebase through your own Claude.
72
+
73
+ ## MCP Tools Available
74
+
75
+ | Tool | Description |
76
+ |------|-------------|
77
+ | `list_files` | List files and directories with lock status |
78
+ | `read_file` | Read file contents (1MB limit) |
79
+ | `write_file` | Write to a file (auto-locks if needed) |
80
+ | `lock_file` | Lock a file for exclusive editing |
81
+ | `unlock_file` | Release a file lock |
82
+ | `get_status` | Show session info and active locks |
83
+
84
+ ## Security
85
+
86
+ - Unguessable tunnel URL (random Cloudflare subdomain)
87
+ - Cryptographic secret token (second auth layer)
88
+ - All traffic encrypted via HTTPS
89
+ - Path traversal prevention (no access outside project root)
90
+ - No accounts, no signup, no persistent credentials
91
+
92
+ ## CLI Commands
93
+
94
+ | Command | Description |
95
+ |---------|-------------|
96
+ | `letswork start [--port PORT]` | Start session (default port: 8000) |
97
+ | `letswork stop` | Stop instructions (use Ctrl+C in v1) |
98
+ | `letswork status` | Status instructions (use get_status tool in v1) |
99
+
100
+ ## Architecture
101
+ Developer A's Machine:
102
+ [Local Codebase] ← [MCP Server] ← [Cloudflare Tunnel] ← HTTPS URL
103
+
104
+ Developer B connects here
105
+ with secret token
106
+
107
+ ## Constraints (v1)
108
+
109
+ - Maximum 2 users per session (Host + Guest)
110
+ - Text files only (no binary support)
111
+ - 1MB file size limit per operation
112
+ - File operations only (no shell access for Guest)
113
+
114
+ ## License
115
+
116
+ MIT
117
+
118
+ ---
119
+
120
+ Built with the [Model Context Protocol](https://modelcontextprotocol.io).
@@ -0,0 +1,104 @@
1
+ # LetsWork
2
+
3
+ **Google Docs for AI-assisted coding** — real-time collaboration on a local codebase using two independent Claude subscriptions.
4
+
5
+ ## What is LetsWork?
6
+
7
+ LetsWork is an MCP (Model Context Protocol) server that lets two developers work on the same local codebase simultaneously, each using their own Claude. One developer hosts, the other connects — with file-level locking to prevent conflicts.
8
+
9
+ ## How It Works
10
+
11
+ 1. Developer A (Host) runs `letswork start` in their project folder
12
+ 2. A secure HTTPS tunnel is created automatically via Cloudflare
13
+ 3. A one-time URL + secret token is generated
14
+ 4. Developer A shares both with Developer B (Guest)
15
+ 5. Developer B connects: `claude mcp add letswork --transport http <url>`
16
+ 6. Both can now read, write, and list files — with lock protection
17
+
18
+ ## Quick Start
19
+
20
+ ### Install
21
+ ```bash
22
+ pip install letswork
23
+ ```
24
+
25
+ ### Requirements
26
+
27
+ - Python >= 3.10
28
+ - [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) installed and available in PATH
29
+ - Git (recommended for conflict safety)
30
+
31
+ ### Host (Developer A)
32
+ ```bash
33
+ cd /path/to/your/project
34
+ letswork start
35
+ ```
36
+
37
+ You'll see:
38
+ ╔══════════════════════════════════════════════════╗
39
+ ║ LetsWork Session Active ║
40
+ ║ ║
41
+ ║ URL: https://abc123.trycloudflare.com ║
42
+ ║ Token: a1b2c3d4e5f6... ║
43
+ ║ ║
44
+ ║ Share both with your collaborator. ║
45
+ ║ Press Ctrl+C to end session. ║
46
+ ╚══════════════════════════════════════════════════╝
47
+
48
+ Share the URL and token with your collaborator via Slack, Discord, or text.
49
+
50
+ ### Guest (Developer B)
51
+ ```bash
52
+ claude mcp add letswork --transport http <URL_FROM_HOST>
53
+ ```
54
+
55
+ Use the token when prompted. You now have full access to the shared codebase through your own Claude.
56
+
57
+ ## MCP Tools Available
58
+
59
+ | Tool | Description |
60
+ |------|-------------|
61
+ | `list_files` | List files and directories with lock status |
62
+ | `read_file` | Read file contents (1MB limit) |
63
+ | `write_file` | Write to a file (auto-locks if needed) |
64
+ | `lock_file` | Lock a file for exclusive editing |
65
+ | `unlock_file` | Release a file lock |
66
+ | `get_status` | Show session info and active locks |
67
+
68
+ ## Security
69
+
70
+ - Unguessable tunnel URL (random Cloudflare subdomain)
71
+ - Cryptographic secret token (second auth layer)
72
+ - All traffic encrypted via HTTPS
73
+ - Path traversal prevention (no access outside project root)
74
+ - No accounts, no signup, no persistent credentials
75
+
76
+ ## CLI Commands
77
+
78
+ | Command | Description |
79
+ |---------|-------------|
80
+ | `letswork start [--port PORT]` | Start session (default port: 8000) |
81
+ | `letswork stop` | Stop instructions (use Ctrl+C in v1) |
82
+ | `letswork status` | Status instructions (use get_status tool in v1) |
83
+
84
+ ## Architecture
85
+ Developer A's Machine:
86
+ [Local Codebase] ← [MCP Server] ← [Cloudflare Tunnel] ← HTTPS URL
87
+
88
+ Developer B connects here
89
+ with secret token
90
+
91
+ ## Constraints (v1)
92
+
93
+ - Maximum 2 users per session (Host + Guest)
94
+ - Text files only (no binary support)
95
+ - 1MB file size limit per operation
96
+ - File operations only (no shell access for Guest)
97
+
98
+ ## License
99
+
100
+ MIT
101
+
102
+ ---
103
+
104
+ Built with the [Model Context Protocol](https://modelcontextprotocol.io).
@@ -0,0 +1,73 @@
1
+ # LetsWork — Architecture Decisions
2
+
3
+ *Record of every architectural decision made during development.
4
+ Read this at the start of every session to avoid contradicting past decisions.*
5
+
6
+ ---
7
+
8
+ ## Decision: Python as Implementation Language
9
+ Date: Session 1
10
+ Decision: Use Python for the entire project
11
+ Reasoning: The official Anthropic MCP SDK is Python-first with the best documentation and examples. The target audience (developers using Claude) overwhelmingly uses Python. Click provides excellent CLI tooling in Python.
12
+ Alternatives rejected: TypeScript (MCP SDK exists but Python SDK is more mature), Rust (no official MCP SDK), Go (no official MCP SDK)
13
+ Impact: All source files are .py, packaging via PyPI, dependencies are Python packages
14
+
15
+ ## Decision: FastMCP as Server Framework
16
+ Date: Session 1
17
+ Decision: Use FastMCP from the official mcp Python SDK
18
+ Reasoning: FastMCP is the high-level API provided by Anthropic's own MCP SDK. It handles protocol details, tool registration, and transport layers. Using the official SDK ensures compatibility with Claude Code and other MCP clients.
19
+ Alternatives rejected: Building raw MCP protocol handling manually (unnecessary complexity), third-party MCP libraries (less maintained than official SDK)
20
+ Impact: Server defined in src/server.py using @app.tool() decorators, transport handled by FastMCP
21
+
22
+ ## Decision: Cloudflare Tunnel for Networking
23
+ Date: Session 1
24
+ Decision: Use cloudflared (Cloudflare Tunnel) to expose the local MCP server
25
+ Reasoning: Free tier sufficient, no port forwarding needed, no VPN needed, no DNS configuration, works behind NATs and firewalls, HTTPS by default. The tunnel creates a random subdomain on trycloudflare.com.
26
+ Alternatives rejected: ngrok (requires account, has rate limits on free tier), localtunnel (less reliable), direct port forwarding (requires router config, not user-friendly), Tailscale (requires both users to install and configure)
27
+ Impact: cloudflared is an external dependency that must be pre-installed. src/tunnel.py manages the subprocess lifecycle.
28
+
29
+ ## Decision: In-Memory File Locking
30
+ Date: Session 1
31
+ Decision: Use a Python dictionary for file lock tracking (path -> user_id)
32
+ Reasoning: Simple, fast, no external dependencies. Locks only need to persist for the duration of a session. When the session ends, all locks are released automatically since the process exits.
33
+ Alternatives rejected: File-system level locks with fcntl/msvcrt (cross-platform complexity, doesn't track user identity), Redis (overkill external dependency), SQLite (unnecessary persistence)
34
+ Impact: LockManager class in src/filelock.py with a dict. Locks are lost if the process crashes — acceptable for v1 since Git is the safety net.
35
+
36
+ ## Decision: Secret Token Authentication
37
+ Date: Session 1
38
+ Decision: Generate a cryptographic random token per session using secrets.token_urlsafe
39
+ Reasoning: Simple, no accounts needed, no persistent credentials. Combined with the unguessable tunnel URL, this provides two layers of security. Token is shared out-of-band (Slack, Discord, text).
40
+ Alternatives rejected: OAuth (massive complexity for a CLI tool), API keys (requires persistent storage), mutual TLS (complex setup for end users)
41
+ Impact: src/auth.py generates and validates tokens. Token is set once at session start and checked on every request.
42
+
43
+ ## Decision: Centralized Path Safety via safe_resolve
44
+ Date: Session 4
45
+ Decision: Create a single safe_resolve(path) function used by all MCP tools for path resolution and traversal prevention
46
+ Reasoning: Initially each tool had inline path resolution logic (os.path.join, os.path.abspath, startswith check). This was duplicated across 5 tools. Extracting it into safe_resolve eliminates duplication and ensures a single point of security enforcement.
47
+ Alternatives rejected: Keeping inline checks per tool (duplication, risk of inconsistency), middleware-level path check (FastMCP doesn't natively support pre-tool middleware)
48
+ Impact: All tools call safe_resolve(path) first. Any path outside project_root raises ValueError.
49
+
50
+ ## Decision: Click for CLI Framework
51
+ Date: Session 1
52
+ Decision: Use Click for the command-line interface
53
+ Reasoning: Click is the standard Python CLI library — well-documented, widely used, supports groups, commands, options, and help text out of the box. Minimal code for a professional CLI.
54
+ Alternatives rejected: argparse (more verbose, less elegant), Typer (adds a dependency on top of Click), fire (too magic, less control)
55
+ Impact: src/cli.py defines a Click group with start, stop, and status commands
56
+
57
+ ## Decision: Streamable HTTP Transport
58
+ Date: Session 4
59
+ Decision: Run the MCP server with transport="streamable-http"
60
+ Reasoning: This is the transport mode required for remote MCP connections over HTTPS tunnels. The Guest connects via HTTP to the Cloudflare tunnel URL, which forwards to the local server.
61
+ Alternatives rejected: stdio transport (only works for local connections, not over network), SSE transport (older protocol, streamable-http is the current standard)
62
+ Impact: app.run() in cli.py uses transport="streamable-http" with host="127.0.0.1"
63
+
64
+ ## Decision: v1 Scope Boundaries
65
+ Date: Session 1
66
+ Decision: Limit v1 to exactly 2 users, text files only, 1MB limit, no directory creation/deletion, no shell access for Guest
67
+ Reasoning: Shipping a focused, working tool is more important than feature completeness. Every constraint can be relaxed in v2 based on real user feedback. The core value proposition (two developers, one codebase, real-time) works within these constraints.
68
+ Alternatives rejected: Building multi-user support from the start (complexity), supporting binary files (encoding complexity), adding shell access (security risk)
69
+ Impact: All tools enforce these limits. Future scope documented in spec.md Section 9.
70
+
71
+ ---
72
+
73
+ *Last updated: Session 5 — All architecture decisions documented*
@@ -0,0 +1,247 @@
1
+ # LetsWork — Product Specification
2
+ *Version 1.0 — Source of truth for what LetsWork does and how.*
3
+
4
+ ---
5
+
6
+ ## 1. Product Summary
7
+
8
+ LetsWork is an MCP (Model Context Protocol) server that enables
9
+ two developers to collaborate on the same local codebase in
10
+ real time, each using their own Claude subscription independently.
11
+
12
+ One developer (the Host) runs LetsWork in their project folder.
13
+ It starts an MCP server, creates a secure Cloudflare tunnel,
14
+ and generates a one-time URL + secret token. A second developer
15
+ (the Guest) adds that URL as an MCP server in their Claude Code.
16
+ Both can now read and write files in the same codebase with
17
+ file-level locking to prevent conflicts.
18
+
19
+ ---
20
+
21
+ ## 2. Users
22
+
23
+ ### Host (Developer A)
24
+ - Has the codebase on their local machine
25
+ - Runs `letswork start` to begin a session
26
+ - Shares the generated URL + token with the Guest
27
+ - Can read, write, list, and lock files
28
+ - Can see which files the Guest has locked
29
+ - Can end the session at any time
30
+
31
+ ### Guest (Developer B)
32
+ - Does NOT have the codebase locally
33
+ - Receives the URL + token from the Host
34
+ - Connects via `claude mcp add letswork --transport http <url>`
35
+ - Can read, write, list, and lock files
36
+ - Can see which files the Host has locked
37
+ - Connection ends when the Host stops the session
38
+
39
+ ---
40
+
41
+ ## 3. Core Features
42
+
43
+ ### 3.1 Session Management
44
+ - Host runs `letswork start` in any project directory
45
+ - A local MCP server starts on a random available port
46
+ - A Cloudflare tunnel is created automatically (no config needed)
47
+ - A unique session URL (HTTPS) is generated
48
+ - A one-time secret token is generated for authentication
49
+ - Host sees: URL, token, and session status in terminal
50
+ - Session ends when Host runs `letswork stop` or Ctrl+C
51
+
52
+ ### 3.2 File Operations (MCP Tools)
53
+ LetsWork exposes these MCP tools to both Host and Guest Claude:
54
+
55
+ | Tool Name | Parameters | Description |
56
+ |-----------------|-------------------------|-------------------------------------|
57
+ | `read_file` | `path: str` | Read contents of a file |
58
+ | `write_file` | `path: str, content: str` | Write content to a file |
59
+ | `list_files` | `path: str` (optional) | List files in directory (default: root) |
60
+ | `lock_file` | `path: str` | Lock a file for exclusive editing |
61
+ | `unlock_file` | `path: str` | Release lock on a file |
62
+ | `get_locks` | (none) | Show all currently locked files |
63
+ | `get_status` | (none) | Show session info and connected users |
64
+
65
+ ### 3.3 File Locking
66
+ - Before writing, a developer must lock the file
67
+ - Only one developer can lock a file at a time
68
+ - Attempting to lock an already-locked file returns an error
69
+ with the name of the holder
70
+ - Locks are released explicitly via `unlock_file` or
71
+ automatically when the session ends
72
+ - `get_locks` shows all active locks with holder identity
73
+ - `write_file` automatically checks lock ownership before writing
74
+
75
+ ### 3.4 Authentication
76
+ - On session start, a random secret token is generated
77
+ (cryptographically secure, 32 characters)
78
+ - Every request from the Guest must include this token
79
+ - Invalid tokens are rejected with 401 Unauthorized
80
+ - Token is single-use per session (new token each `letswork start`)
81
+ - No accounts, no signup, no persistent credentials
82
+
83
+ ### 3.5 Tunneling
84
+ - Cloudflare Tunnel (via `cloudflared`) creates a public
85
+ HTTPS URL for the local MCP server
86
+ - No port forwarding required
87
+ - No VPN required
88
+ - No DNS configuration required
89
+ - Works behind NATs and firewalls
90
+ - Free tier is sufficient
91
+ - If `cloudflared` is not installed, LetsWork prints
92
+ clear installation instructions and exits
93
+
94
+ ---
95
+
96
+ ## 4. CLI Interface
97
+
98
+ ### Commands:
99
+ ```
100
+ letswork start [--port PORT]
101
+ ```
102
+ - Starts MCP server + tunnel in current directory
103
+ - Optional: specify port (default: auto-select available port)
104
+ - Outputs: session URL, secret token, status
105
+ ```
106
+ letswork stop
107
+ ```
108
+ - Stops the MCP server and closes the tunnel
109
+ - Releases all file locks
110
+ - Ends the session cleanly
111
+ ```
112
+ letswork status
113
+ ```
114
+ - Shows: running/stopped, connected users, active locks,
115
+ session duration, tunnel URL
116
+
117
+ ### Terminal Output on Start:
118
+ ```
119
+ ╔══════════════════════════════════════════════════╗
120
+ ║ LetsWork Session Active ║
121
+ ║ ║
122
+ ║ URL: https://abc123.trycloudflare.com ║
123
+ ║ Token: a1b2c3d4e5f6... ║
124
+ ║ ║
125
+ ║ Share both with your collaborator. ║
126
+ ║ Press Ctrl+C to end session. ║
127
+ ╚══════════════════════════════════════════════════╝
128
+ ```
129
+
130
+ ---
131
+
132
+ ## 5. Security Model
133
+
134
+ ### Threat Model:
135
+ - The tunnel URL is unguessable (random subdomain from Cloudflare)
136
+ - The secret token adds a second layer of authentication
137
+ - Both are required — URL alone is not enough
138
+ - Token is transmitted out-of-band (Host sends it via
139
+ Slack/Discord/text, not through the tunnel itself)
140
+ - All traffic is encrypted via HTTPS (Cloudflare handles TLS)
141
+
142
+ ### What LetsWork does NOT protect against:
143
+ - A malicious Guest who has the valid token
144
+ (they have full read/write access by design)
145
+ - Network-level attacks on Cloudflare's infrastructure
146
+ - Files outside the project directory
147
+ (LetsWork restricts paths to project root — see Section 6)
148
+
149
+ ### Path Traversal Prevention:
150
+ - All file paths are resolved relative to the project root
151
+ - Any path containing `..` or resolving outside the project
152
+ directory is rejected with 403 Forbidden
153
+ - Symlinks pointing outside the project directory are rejected
154
+
155
+ ---
156
+
157
+ ## 6. Constraints & Boundaries
158
+
159
+ ### What LetsWork IS:
160
+ - A real-time file collaboration tool for two developers
161
+ - An MCP server that any MCP-compatible client can connect to
162
+ - A lightweight CLI tool with zero configuration
163
+
164
+ ### What LetsWork is NOT:
165
+ - Not a version control system (use Git for that)
166
+ - Not a code editor or IDE
167
+ - Not a cloud storage service
168
+ - Not a deployment tool
169
+ - Not a multi-tenant platform (one Host, one Guest per session)
170
+
171
+ ### Technical Constraints:
172
+ - Maximum 2 concurrent users per session (Host + Guest)
173
+ - File operations only (no terminal/shell access for Guest)
174
+ - No directory creation/deletion via MCP tools
175
+ (only file read/write/list)
176
+ - No binary file support in v1 (text files only)
177
+ - Maximum file size: 1MB per read/write operation
178
+ - Project root is the directory where `letswork start` was run
179
+
180
+ ---
181
+
182
+ ## 7. Dependencies
183
+
184
+ | Dependency | Purpose | Required? |
185
+ |------------------|----------------------------|-----------|
186
+ | Python >= 3.10 | Runtime | Yes |
187
+ | mcp SDK | MCP server implementation | Yes |
188
+ | cloudflared | Tunnel creation | Yes (external) |
189
+ | click | CLI framework | Yes |
190
+ | secrets (stdlib) | Token generation | Yes (built-in) |
191
+ | fcntl / msvcrt | File locking | Yes (built-in) |
192
+ | pathlib (stdlib) | Path resolution & safety | Yes (built-in) |
193
+ | git | Conflict safety net | Recommended |
194
+
195
+ ---
196
+
197
+ ## 8. Error Handling Summary
198
+
199
+ | Situation | Behavior |
200
+ |----------------------------------|---------------------------------------|
201
+ | `cloudflared` not installed | Print install instructions, exit |
202
+ | Port already in use | Auto-select next available port |
203
+ | Invalid token from Guest | Reject with 401 Unauthorized |
204
+ | File not found on read | Return clear error message |
205
+ | Path traversal attempt | Reject with 403 Forbidden |
206
+ | File locked by other user | Return error with lock holder info |
207
+ | Write without holding lock | Reject with error |
208
+ | Tunnel connection drops | Attempt reconnect, notify Host |
209
+ | Host stops session | All locks released, Guest disconnected|
210
+ | File exceeds 1MB | Reject with size limit error |
211
+
212
+ ---
213
+
214
+ ## 9. Future Scope (v2+, Not for Current Build)
215
+
216
+ These are explicitly NOT part of v1. Listed here only to
217
+ acknowledge them and prevent scope creep:
218
+
219
+ - Multi-guest support (3+ developers)
220
+ - Directory creation/deletion tools
221
+ - Binary file support
222
+ - Built-in diff/merge viewer
223
+ - Chat between Host and Guest
224
+ - Persistent sessions (survive restarts)
225
+ - Web UI dashboard
226
+ - Access control per file/directory
227
+ - Audit log of all operations
228
+
229
+ ---
230
+
231
+ ## 10. Success Criteria for v1
232
+
233
+ LetsWork v1 is complete when:
234
+ 1. `pip install letswork` works
235
+ 2. `letswork start` creates a working MCP server + tunnel
236
+ 3. A second developer can connect via the URL + token
237
+ 4. Both can read, write, list files through their Claude
238
+ 5. File locking prevents simultaneous edits
239
+ 6. Path traversal is blocked
240
+ 7. Session starts and stops cleanly
241
+ 8. Published on PyPI
242
+ 9. Listed on the official MCP Registry
243
+
244
+ ---
245
+
246
+ *Last updated: Session 2 — Full specification written*
247
+ #this is a comment