teammate-sync 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.
- teammate_sync-0.1.0/PKG-INFO +151 -0
- teammate_sync-0.1.0/README.md +127 -0
- teammate_sync-0.1.0/pyproject.toml +48 -0
- teammate_sync-0.1.0/setup.cfg +4 -0
- teammate_sync-0.1.0/teammate_sync/__init__.py +0 -0
- teammate_sync-0.1.0/teammate_sync/auth.py +51 -0
- teammate_sync-0.1.0/teammate_sync/backend.py +375 -0
- teammate_sync-0.1.0/teammate_sync/cli.py +461 -0
- teammate_sync-0.1.0/teammate_sync/daemon.py +433 -0
- teammate_sync-0.1.0/teammate_sync/hook.py +183 -0
- teammate_sync-0.1.0/teammate_sync/server.py +400 -0
- teammate_sync-0.1.0/teammate_sync/share_cli.py +180 -0
- teammate_sync-0.1.0/teammate_sync.egg-info/PKG-INFO +151 -0
- teammate_sync-0.1.0/teammate_sync.egg-info/SOURCES.txt +16 -0
- teammate_sync-0.1.0/teammate_sync.egg-info/dependency_links.txt +1 -0
- teammate_sync-0.1.0/teammate_sync.egg-info/entry_points.txt +2 -0
- teammate_sync-0.1.0/teammate_sync.egg-info/requires.txt +4 -0
- teammate_sync-0.1.0/teammate_sync.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: teammate-sync
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Cross-engineer Claude Code context sharing — type /share, your teammate queries your context.
|
|
5
|
+
Author-email: Om Divyatej <om@turgon.ai>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://omdivyatej.github.io/teammate-sync-site/
|
|
8
|
+
Project-URL: Source, https://github.com/omdivyatej/teammate-sync
|
|
9
|
+
Keywords: claude,claude-code,mcp,team,context,sharing
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: mcp>=1.0.0
|
|
21
|
+
Requires-Dist: anthropic>=0.40.0
|
|
22
|
+
Requires-Dist: watchdog>=4.0.0
|
|
23
|
+
Requires-Dist: httpx>=0.27
|
|
24
|
+
|
|
25
|
+
# teammate-sync
|
|
26
|
+
|
|
27
|
+
**Cross-engineer Claude Code context sharing.** Your teammate types `/share`
|
|
28
|
+
in their Claude Code session. From your own terminal, your Claude can ask
|
|
29
|
+
theirs anything and gets back a cited answer in seconds.
|
|
30
|
+
|
|
31
|
+
No pasted transcripts. No GitHub pushes. No shared bucket setup.
|
|
32
|
+
|
|
33
|
+
- Landing: https://omdivyatej.github.io/teammate-sync-site/
|
|
34
|
+
- Source: https://github.com/omdivyatej/teammate-sync
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## The problem
|
|
39
|
+
|
|
40
|
+
You and your teammate are both using Claude Code on the same project. You
|
|
41
|
+
need to know what they decided about the database schema, or which file
|
|
42
|
+
they touched, or why they picked one library over another.
|
|
43
|
+
|
|
44
|
+
Today, two bad options:
|
|
45
|
+
|
|
46
|
+
1. **Ping them on Slack and wait.** Forty-five minutes of context-switching.
|
|
47
|
+
2. **Get them to send their session transcript.** Their `.jsonl` is 50k
|
|
48
|
+
lines. You paste it into your Claude and immediately blow past the
|
|
49
|
+
200k token context window.
|
|
50
|
+
|
|
51
|
+
`teammate-sync` is the third option: their Claude becomes a queryable
|
|
52
|
+
context server. Your Claude calls it, gets back a cited synthesis, your
|
|
53
|
+
context window stays clean.
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
pip install teammate-sync
|
|
59
|
+
teammate-sync init
|
|
60
|
+
teammate-sync daemon
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
That's it. Full setup walkthrough: [INSTALL.md](INSTALL.md).
|
|
64
|
+
|
|
65
|
+
`init` opens GitHub OAuth (your workspace = your GitHub org, no separate
|
|
66
|
+
account), installs the `/share` slash commands into `~/.claude/commands/`,
|
|
67
|
+
wires session lifecycle hooks into `~/.claude/settings.json`, and registers
|
|
68
|
+
the MCP server. `daemon` runs in the foreground in a terminal you leave open.
|
|
69
|
+
|
|
70
|
+
## How sharing works
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
/share in any Claude Code session
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Daemon log immediately prints `share-mode ACTIVATED -> uploading`. That
|
|
77
|
+
session's `.jsonl` plus your `CLAUDE.md` start syncing to your team's
|
|
78
|
+
backend in real time as you work.
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
/unshare same session
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Daemon wipes that session's content from the backend immediately.
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
/shared any session
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Lists which sessions are currently shared.
|
|
91
|
+
|
|
92
|
+
## How teammates query you
|
|
93
|
+
|
|
94
|
+
From any Claude Code session in your org, your teammate types:
|
|
95
|
+
|
|
96
|
+
> Use `mcp__teammate-sync__query_teammate_context` with
|
|
97
|
+
> `teammate=<your-github-handle>` and `question="..."`
|
|
98
|
+
|
|
99
|
+
The MCP server pulls your active-session state + your shared session
|
|
100
|
+
transcripts, hands them to a Claude Sonnet synthesis call, and returns a
|
|
101
|
+
cited answer. Citations point to specific session IDs and file names so
|
|
102
|
+
they can verify.
|
|
103
|
+
|
|
104
|
+
## Privacy model
|
|
105
|
+
|
|
106
|
+
Default: **nothing is shared.** The daemon is running but idle.
|
|
107
|
+
|
|
108
|
+
- **Sessions** are opted in one at a time via `/share`. Unshared sessions
|
|
109
|
+
never leave your machine, no matter how many you have running.
|
|
110
|
+
- **Your GitHub OAuth token** sits in `~/.teammate-sync/auth.json` (mode
|
|
111
|
+
0600) and is **never** in the synced tree.
|
|
112
|
+
- **Your org** is the unit of trust. Only members of your GitHub org can
|
|
113
|
+
query you. Discovery happens via the GitHub API, no manual invites.
|
|
114
|
+
|
|
115
|
+
## What syncs where
|
|
116
|
+
|
|
117
|
+
| Path | What it holds | Synced to cloud? |
|
|
118
|
+
| ---- | ------------- | --------------- |
|
|
119
|
+
| `~/.teammate-sync/auth.json` | Your GitHub OAuth token | **NEVER** (local only) |
|
|
120
|
+
| `~/.teammate-sync/state/.shared-sessions.json` | List of currently-shared session IDs | No (local gate) |
|
|
121
|
+
| `~/.teammate-sync/state/.active-sessions.json` | Which sessions are active right now (cwd, last activity) | Yes |
|
|
122
|
+
| `~/.claude/projects/<encoded-cwd>/<sid>.jsonl` | Claude Code session transcripts | Only `/share`'d ones |
|
|
123
|
+
|
|
124
|
+
## CLI
|
|
125
|
+
|
|
126
|
+
| | |
|
|
127
|
+
|---|---|
|
|
128
|
+
| `teammate-sync init` | First-run setup. Re-runnable to refresh hooks / slash commands. |
|
|
129
|
+
| `teammate-sync daemon` | Run the sync daemon (foreground). |
|
|
130
|
+
| `teammate-sync share` / `unshare` / `shared` | Same as the slash commands, from any shell. |
|
|
131
|
+
| `teammate-sync whoami` | Show your identity + workspace. |
|
|
132
|
+
| `teammate-sync teammates` | List members of your workspace org. |
|
|
133
|
+
| `teammate-sync logout` | Delete `~/.teammate-sync/auth.json`. |
|
|
134
|
+
|
|
135
|
+
## Requirements
|
|
136
|
+
|
|
137
|
+
- Python 3.11+
|
|
138
|
+
- [Claude Code](https://docs.claude.com/en/docs/claude-code) CLI
|
|
139
|
+
- `ANTHROPIC_API_KEY` exported in your shell (used by the MCP server's
|
|
140
|
+
synthesis calls)
|
|
141
|
+
|
|
142
|
+
## Status
|
|
143
|
+
|
|
144
|
+
Public beta. Backend runs on Fly.io (Singapore region, single-region by
|
|
145
|
+
design — synthesis latency is dominated by Anthropic API not by storage).
|
|
146
|
+
Per-session opt-in (`/share` / `/unshare`) is the privacy model; there is
|
|
147
|
+
no "everything sync" mode and there won't be.
|
|
148
|
+
|
|
149
|
+
## License
|
|
150
|
+
|
|
151
|
+
MIT — see [LICENSE](LICENSE) if present, or `pyproject.toml`.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# teammate-sync
|
|
2
|
+
|
|
3
|
+
**Cross-engineer Claude Code context sharing.** Your teammate types `/share`
|
|
4
|
+
in their Claude Code session. From your own terminal, your Claude can ask
|
|
5
|
+
theirs anything and gets back a cited answer in seconds.
|
|
6
|
+
|
|
7
|
+
No pasted transcripts. No GitHub pushes. No shared bucket setup.
|
|
8
|
+
|
|
9
|
+
- Landing: https://omdivyatej.github.io/teammate-sync-site/
|
|
10
|
+
- Source: https://github.com/omdivyatej/teammate-sync
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## The problem
|
|
15
|
+
|
|
16
|
+
You and your teammate are both using Claude Code on the same project. You
|
|
17
|
+
need to know what they decided about the database schema, or which file
|
|
18
|
+
they touched, or why they picked one library over another.
|
|
19
|
+
|
|
20
|
+
Today, two bad options:
|
|
21
|
+
|
|
22
|
+
1. **Ping them on Slack and wait.** Forty-five minutes of context-switching.
|
|
23
|
+
2. **Get them to send their session transcript.** Their `.jsonl` is 50k
|
|
24
|
+
lines. You paste it into your Claude and immediately blow past the
|
|
25
|
+
200k token context window.
|
|
26
|
+
|
|
27
|
+
`teammate-sync` is the third option: their Claude becomes a queryable
|
|
28
|
+
context server. Your Claude calls it, gets back a cited synthesis, your
|
|
29
|
+
context window stays clean.
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
pip install teammate-sync
|
|
35
|
+
teammate-sync init
|
|
36
|
+
teammate-sync daemon
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
That's it. Full setup walkthrough: [INSTALL.md](INSTALL.md).
|
|
40
|
+
|
|
41
|
+
`init` opens GitHub OAuth (your workspace = your GitHub org, no separate
|
|
42
|
+
account), installs the `/share` slash commands into `~/.claude/commands/`,
|
|
43
|
+
wires session lifecycle hooks into `~/.claude/settings.json`, and registers
|
|
44
|
+
the MCP server. `daemon` runs in the foreground in a terminal you leave open.
|
|
45
|
+
|
|
46
|
+
## How sharing works
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
/share in any Claude Code session
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Daemon log immediately prints `share-mode ACTIVATED -> uploading`. That
|
|
53
|
+
session's `.jsonl` plus your `CLAUDE.md` start syncing to your team's
|
|
54
|
+
backend in real time as you work.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
/unshare same session
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Daemon wipes that session's content from the backend immediately.
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
/shared any session
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Lists which sessions are currently shared.
|
|
67
|
+
|
|
68
|
+
## How teammates query you
|
|
69
|
+
|
|
70
|
+
From any Claude Code session in your org, your teammate types:
|
|
71
|
+
|
|
72
|
+
> Use `mcp__teammate-sync__query_teammate_context` with
|
|
73
|
+
> `teammate=<your-github-handle>` and `question="..."`
|
|
74
|
+
|
|
75
|
+
The MCP server pulls your active-session state + your shared session
|
|
76
|
+
transcripts, hands them to a Claude Sonnet synthesis call, and returns a
|
|
77
|
+
cited answer. Citations point to specific session IDs and file names so
|
|
78
|
+
they can verify.
|
|
79
|
+
|
|
80
|
+
## Privacy model
|
|
81
|
+
|
|
82
|
+
Default: **nothing is shared.** The daemon is running but idle.
|
|
83
|
+
|
|
84
|
+
- **Sessions** are opted in one at a time via `/share`. Unshared sessions
|
|
85
|
+
never leave your machine, no matter how many you have running.
|
|
86
|
+
- **Your GitHub OAuth token** sits in `~/.teammate-sync/auth.json` (mode
|
|
87
|
+
0600) and is **never** in the synced tree.
|
|
88
|
+
- **Your org** is the unit of trust. Only members of your GitHub org can
|
|
89
|
+
query you. Discovery happens via the GitHub API, no manual invites.
|
|
90
|
+
|
|
91
|
+
## What syncs where
|
|
92
|
+
|
|
93
|
+
| Path | What it holds | Synced to cloud? |
|
|
94
|
+
| ---- | ------------- | --------------- |
|
|
95
|
+
| `~/.teammate-sync/auth.json` | Your GitHub OAuth token | **NEVER** (local only) |
|
|
96
|
+
| `~/.teammate-sync/state/.shared-sessions.json` | List of currently-shared session IDs | No (local gate) |
|
|
97
|
+
| `~/.teammate-sync/state/.active-sessions.json` | Which sessions are active right now (cwd, last activity) | Yes |
|
|
98
|
+
| `~/.claude/projects/<encoded-cwd>/<sid>.jsonl` | Claude Code session transcripts | Only `/share`'d ones |
|
|
99
|
+
|
|
100
|
+
## CLI
|
|
101
|
+
|
|
102
|
+
| | |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `teammate-sync init` | First-run setup. Re-runnable to refresh hooks / slash commands. |
|
|
105
|
+
| `teammate-sync daemon` | Run the sync daemon (foreground). |
|
|
106
|
+
| `teammate-sync share` / `unshare` / `shared` | Same as the slash commands, from any shell. |
|
|
107
|
+
| `teammate-sync whoami` | Show your identity + workspace. |
|
|
108
|
+
| `teammate-sync teammates` | List members of your workspace org. |
|
|
109
|
+
| `teammate-sync logout` | Delete `~/.teammate-sync/auth.json`. |
|
|
110
|
+
|
|
111
|
+
## Requirements
|
|
112
|
+
|
|
113
|
+
- Python 3.11+
|
|
114
|
+
- [Claude Code](https://docs.claude.com/en/docs/claude-code) CLI
|
|
115
|
+
- `ANTHROPIC_API_KEY` exported in your shell (used by the MCP server's
|
|
116
|
+
synthesis calls)
|
|
117
|
+
|
|
118
|
+
## Status
|
|
119
|
+
|
|
120
|
+
Public beta. Backend runs on Fly.io (Singapore region, single-region by
|
|
121
|
+
design — synthesis latency is dominated by Anthropic API not by storage).
|
|
122
|
+
Per-session opt-in (`/share` / `/unshare`) is the privacy model; there is
|
|
123
|
+
no "everything sync" mode and there won't be.
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT — see [LICENSE](LICENSE) if present, or `pyproject.toml`.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "teammate-sync"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Cross-engineer Claude Code context sharing — type /share, your teammate queries your context."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Om Divyatej", email = "om@turgon.ai" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["claude", "claude-code", "mcp", "team", "context", "sharing"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Topic :: Software Development",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"mcp>=1.0.0",
|
|
28
|
+
"anthropic>=0.40.0",
|
|
29
|
+
"watchdog>=4.0.0",
|
|
30
|
+
"httpx>=0.27",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://omdivyatej.github.io/teammate-sync-site/"
|
|
35
|
+
Source = "https://github.com/omdivyatej/teammate-sync"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
# `pip install` puts this on the user's PATH. All functionality is reachable
|
|
39
|
+
# via subcommands: init, daemon, share, unshare, shared, whoami, teammates,
|
|
40
|
+
# install-commands, logout.
|
|
41
|
+
teammate-sync = "teammate_sync.cli:main"
|
|
42
|
+
|
|
43
|
+
[tool.setuptools]
|
|
44
|
+
# Single flat module layout under teammate_sync/.
|
|
45
|
+
packages = ["teammate_sync"]
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.package-dir]
|
|
48
|
+
teammate_sync = "teammate_sync"
|
|
File without changes
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Auth helper for teammate-sync clients (daemon + MCP).
|
|
3
|
+
|
|
4
|
+
Reads ~/.teammate-sync/auth.json, written by `teammate-sync init` (Phase 5c).
|
|
5
|
+
Format:
|
|
6
|
+
{
|
|
7
|
+
"token": "gho_...", # GitHub OAuth access token
|
|
8
|
+
"org": "SolarCheckr", # workspace = GitHub org name
|
|
9
|
+
"backend_url": "https://teammate-sync-backend.fly.dev"
|
|
10
|
+
}
|
|
11
|
+
"""
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
DEFAULT_AUTH_FILE = "~/.teammate-sync/auth.json"
|
|
18
|
+
DEFAULT_BACKEND_URL = "https://teammate-sync-backend.fly.dev"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def auth_file_path() -> Path:
|
|
22
|
+
return Path(os.environ.get("TEAMMATE_AUTH_FILE", DEFAULT_AUTH_FILE)).expanduser()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def read_auth() -> dict:
|
|
26
|
+
"""Read the auth file. Raises with a clear message if missing or malformed."""
|
|
27
|
+
path = auth_file_path()
|
|
28
|
+
if not path.exists():
|
|
29
|
+
raise FileNotFoundError(
|
|
30
|
+
f"teammate-sync auth file not found at {path}.\n"
|
|
31
|
+
f"Run `teammate-sync init` to sign in with GitHub and create it."
|
|
32
|
+
)
|
|
33
|
+
try:
|
|
34
|
+
data = json.loads(path.read_text())
|
|
35
|
+
except json.JSONDecodeError as e:
|
|
36
|
+
raise ValueError(f"Auth file {path} is not valid JSON: {e}")
|
|
37
|
+
for required in ("token", "org"):
|
|
38
|
+
if not data.get(required):
|
|
39
|
+
raise ValueError(f"Auth file {path} missing required field: {required!r}")
|
|
40
|
+
data.setdefault("backend_url", DEFAULT_BACKEND_URL)
|
|
41
|
+
return data
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def write_auth(token: str, org: str, backend_url: str = DEFAULT_BACKEND_URL) -> Path:
|
|
45
|
+
"""Persist the auth file with restrictive permissions (0600)."""
|
|
46
|
+
path = auth_file_path()
|
|
47
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
48
|
+
payload = {"token": token, "org": org, "backend_url": backend_url}
|
|
49
|
+
path.write_text(json.dumps(payload, indent=2))
|
|
50
|
+
path.chmod(0o600)
|
|
51
|
+
return path
|