collabmark 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.
Files changed (49) hide show
  1. collabmark-0.1.0/.gitignore +33 -0
  2. collabmark-0.1.0/PKG-INFO +286 -0
  3. collabmark-0.1.0/README.md +266 -0
  4. collabmark-0.1.0/pyproject.toml +46 -0
  5. collabmark-0.1.0/src/collabmark/__init__.py +3 -0
  6. collabmark-0.1.0/src/collabmark/__main__.py +5 -0
  7. collabmark-0.1.0/src/collabmark/commands/__init__.py +1 -0
  8. collabmark-0.1.0/src/collabmark/commands/clean.py +106 -0
  9. collabmark-0.1.0/src/collabmark/commands/init.py +83 -0
  10. collabmark-0.1.0/src/collabmark/commands/list_syncs.py +21 -0
  11. collabmark-0.1.0/src/collabmark/commands/login.py +110 -0
  12. collabmark-0.1.0/src/collabmark/commands/logout.py +20 -0
  13. collabmark-0.1.0/src/collabmark/commands/logs.py +183 -0
  14. collabmark-0.1.0/src/collabmark/commands/start.py +345 -0
  15. collabmark-0.1.0/src/collabmark/commands/status.py +177 -0
  16. collabmark-0.1.0/src/collabmark/commands/stop.py +141 -0
  17. collabmark-0.1.0/src/collabmark/lib/__init__.py +1 -0
  18. collabmark-0.1.0/src/collabmark/lib/api.py +400 -0
  19. collabmark-0.1.0/src/collabmark/lib/auth.py +220 -0
  20. collabmark-0.1.0/src/collabmark/lib/browser_auth.py +162 -0
  21. collabmark-0.1.0/src/collabmark/lib/config.py +225 -0
  22. collabmark-0.1.0/src/collabmark/lib/crdt_sync.py +264 -0
  23. collabmark-0.1.0/src/collabmark/lib/daemon.py +149 -0
  24. collabmark-0.1.0/src/collabmark/lib/logger.py +135 -0
  25. collabmark-0.1.0/src/collabmark/lib/registry.py +252 -0
  26. collabmark-0.1.0/src/collabmark/lib/sync_engine.py +596 -0
  27. collabmark-0.1.0/src/collabmark/lib/watcher.py +147 -0
  28. collabmark-0.1.0/src/collabmark/main.py +71 -0
  29. collabmark-0.1.0/src/collabmark/types.py +128 -0
  30. collabmark-0.1.0/tests/__init__.py +0 -0
  31. collabmark-0.1.0/tests/conftest.py +12 -0
  32. collabmark-0.1.0/tests/test_api.py +586 -0
  33. collabmark-0.1.0/tests/test_auth.py +309 -0
  34. collabmark-0.1.0/tests/test_browser_auth.py +249 -0
  35. collabmark-0.1.0/tests/test_clean.py +116 -0
  36. collabmark-0.1.0/tests/test_config.py +318 -0
  37. collabmark-0.1.0/tests/test_crdt_sync.py +212 -0
  38. collabmark-0.1.0/tests/test_daemon.py +140 -0
  39. collabmark-0.1.0/tests/test_integration.py +369 -0
  40. collabmark-0.1.0/tests/test_list_syncs.py +31 -0
  41. collabmark-0.1.0/tests/test_logger.py +104 -0
  42. collabmark-0.1.0/tests/test_logs.py +108 -0
  43. collabmark-0.1.0/tests/test_main.py +77 -0
  44. collabmark-0.1.0/tests/test_registry.py +226 -0
  45. collabmark-0.1.0/tests/test_start.py +164 -0
  46. collabmark-0.1.0/tests/test_status.py +68 -0
  47. collabmark-0.1.0/tests/test_stop.py +76 -0
  48. collabmark-0.1.0/tests/test_sync_engine.py +577 -0
  49. collabmark-0.1.0/tests/test_watcher.py +173 -0
@@ -0,0 +1,33 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ .env
5
+ .env.local
6
+ .env.*.local
7
+
8
+ .venv/
9
+ venv/
10
+ node_modules/
11
+ frontend/dist/
12
+ *.egg-info/
13
+ .pytest_cache/
14
+ .mypy_cache/
15
+ .ruff_cache/
16
+ dist/
17
+ build/
18
+
19
+ # OS
20
+ .DS_Store
21
+ Thumbs.db
22
+
23
+ # IDE
24
+ .idea/
25
+ .vscode/
26
+ *.swp
27
+ *.swo
28
+ *~
29
+
30
+ # Logs
31
+ *.log
32
+ backend/.coverage
33
+ frontend/coverage/
@@ -0,0 +1,286 @@
1
+ Metadata-Version: 2.4
2
+ Name: collabmark
3
+ Version: 0.1.0
4
+ Summary: Sync markdown files with CollabMark cloud
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: click>=8.1
8
+ Requires-Dist: httpx>=0.27
9
+ Requires-Dist: keyring>=25.0
10
+ Requires-Dist: pycrdt>=0.12
11
+ Requires-Dist: rich>=13.0
12
+ Requires-Dist: watchdog>=4.0
13
+ Requires-Dist: websockets>=14.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
16
+ Requires-Dist: pytest>=8.0; extra == 'dev'
17
+ Requires-Dist: respx>=0.22; extra == 'dev'
18
+ Requires-Dist: ruff>=0.8; extra == 'dev'
19
+ Description-Content-Type: text/markdown
20
+
21
+ # CollabMark CLI
22
+
23
+ Keep your local markdown files in sync with your team's CollabMark cloud
24
+ workspace -- bidirectionally and in real time, powered by CRDTs.
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install collabmark
30
+ collabmark --version
31
+ ```
32
+
33
+ For development:
34
+
35
+ ```bash
36
+ cd cli
37
+ pip install -e ".[dev]"
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```bash
43
+ # Step 1: Log in (opens your browser for one-click authentication)
44
+ collabmark login
45
+
46
+ # Step 2: Start syncing the current directory
47
+ collabmark start
48
+
49
+ # That's it! Your .md files are now synced with CollabMark.
50
+ ```
51
+
52
+ Run `collabmark` with no arguments for a friendly getting-started guide.
53
+
54
+ ## Commands
55
+
56
+ ### `collabmark login`
57
+
58
+ Authenticate with CollabMark. Opens your browser for a one-click Google/SSO
59
+ login. Credentials are stored securely in your OS keychain via `keyring`.
60
+
61
+ ```bash
62
+ collabmark login # Browser login (recommended)
63
+ collabmark login --api-key <KEY> # API key fallback (headless environments)
64
+ ```
65
+
66
+ ### `collabmark logout`
67
+
68
+ Remove stored credentials from the OS keychain.
69
+
70
+ ```bash
71
+ collabmark logout
72
+ ```
73
+
74
+ ### `collabmark init`
75
+
76
+ Set up the current directory for syncing. Creates a `.collabmark/` config folder
77
+ and links to a cloud folder. After init, use `start` to begin syncing.
78
+
79
+ ```bash
80
+ collabmark init # Interactive folder picker
81
+ collabmark init <share-link> # Join a shared folder by link
82
+ ```
83
+
84
+ ### `collabmark start`
85
+
86
+ Begin syncing markdown files. Performs an initial sync, then watches for
87
+ changes on both sides. Content is synced via CRDT WebSocket for real-time
88
+ bidirectional updates; REST is used only for metadata and authentication.
89
+
90
+ ```bash
91
+ collabmark start # Sync current dir, choose folder interactively
92
+ collabmark start <share-link> # Join a shared folder by link
93
+ collabmark start -d # Run as a background daemon
94
+ collabmark start -p ~/notes # Sync a specific directory
95
+ collabmark start --interval 30 # Poll every 30 seconds (default: 10s)
96
+ ```
97
+
98
+ ### `collabmark status`
99
+
100
+ Show the current sync state. When run from a project directory, shows detailed
101
+ project info. When run without a project, shows a global overview of all syncs.
102
+
103
+ ```bash
104
+ collabmark status # Project-specific or global view
105
+ collabmark status -p ~/notes # Check a specific project
106
+ ```
107
+
108
+ ### `collabmark list`
109
+
110
+ List all registered syncs across all projects with status, PID, last sync
111
+ time, and cloud folder info.
112
+
113
+ ```bash
114
+ collabmark list
115
+ ```
116
+
117
+ ### `collabmark stop`
118
+
119
+ Gracefully stop sync processes. Supports interactive selection when multiple
120
+ syncs are running.
121
+
122
+ ```bash
123
+ collabmark stop # Stop current project or choose interactively
124
+ collabmark stop --all # Stop all running syncs
125
+ collabmark stop --path ~/notes # Stop a specific project's sync
126
+ ```
127
+
128
+ ### `collabmark logs`
129
+
130
+ View structured sync log output. Each sync project has its own log file.
131
+
132
+ ```bash
133
+ collabmark logs # Current project logs (last 50 entries)
134
+ collabmark logs -n 100 # Last 100 entries
135
+ collabmark logs -f # Follow in real time (like tail -f)
136
+ collabmark logs --folder <id> # Logs for a specific cloud folder
137
+ collabmark logs --all-syncs # Interleaved logs from all syncs
138
+ ```
139
+
140
+ ### `collabmark clean`
141
+
142
+ Remove stale entries from the sync registry (stopped syncs, missing directories).
143
+
144
+ ```bash
145
+ collabmark clean # Interactive selection of stale entries
146
+ collabmark clean --all # Remove all stopped entries
147
+ collabmark clean --force # Remove all entries (including running)
148
+ ```
149
+
150
+ ## How Sync Works
151
+
152
+ 1. **Local scan** -- finds all `.md` files recursively (ignoring `.collabmark/`).
153
+ 2. **Cloud scan** -- fetches the full folder tree from CollabMark in one API call.
154
+ 3. **Three-way reconciliation** -- compares local files, the last-known sync state
155
+ (`.collabmark/sync.json`), and cloud documents to determine what changed where.
156
+ 4. **CRDT sync** -- content is pushed/pulled via WebSocket using pycrdt (the same
157
+ CRDT library the server uses), so edits merge correctly with concurrent web users.
158
+ 5. **Continuous watch** -- uses OS filesystem events (debounced) plus periodic
159
+ cloud polling to keep both sides in sync.
160
+
161
+ ### Conflict Resolution
162
+
163
+ When the same file changes both locally and on the cloud between sync cycles,
164
+ it is flagged as a **conflict**. Neither side is overwritten. The conflict is
165
+ logged and shown in `collabmark logs`.
166
+
167
+ ## Monitoring & Observability
168
+
169
+ CollabMark CLI uses a centralized registry at `~/.collabmark/registry.json`
170
+ to track all active and stopped syncs. This enables:
171
+
172
+ - **Global visibility**: `collabmark list` shows all syncs at a glance
173
+ - **Per-project logs**: each sync writes to `~/.collabmark/logs/{folder_id}.log`
174
+ - **Heartbeat tracking**: last sync time, action count, and error status
175
+ - **Dead process detection**: `collabmark status` prunes crashed processes
176
+ - **Stale cleanup**: `collabmark clean` removes orphaned registry entries
177
+
178
+ ## Configuration
179
+
180
+ All per-project configuration lives in `.collabmark/` at the root of your
181
+ synced directory:
182
+
183
+ | File | Purpose |
184
+ |-------------------|----------------------------------------------|
185
+ | `config.json` | Linked cloud folder, server URL, user info |
186
+ | `sync.json` | Per-file sync state (hashes, doc IDs) |
187
+ | `trash/` | Files removed by cloud-side deletions |
188
+
189
+ Global state is stored under `~/.collabmark/`:
190
+
191
+ | Path | Purpose |
192
+ |-----------------------------------|------------------------------------------|
193
+ | `~/.collabmark/registry.json` | Centralized sync registry (all projects) |
194
+ | `~/.collabmark/logs/{id}.log` | Per-project structured JSON logs |
195
+ | `~/.collabmark/pids/{id}.pid` | Per-project PID files (daemon mode) |
196
+ | `~/.collabmark/credentials.json` | Non-sensitive login metadata |
197
+ | OS keychain | API key (encrypted, via `keyring`) |
198
+
199
+ ### Environment Variables
200
+
201
+ | Variable | Purpose | Default |
202
+ |---------------------------|------------------------------------|--------------------------------------------------|
203
+ | `COLLABMARK_API_URL` | Override API server URL | `https://web-production-5e1bc.up.railway.app` |
204
+ | `COLLABMARK_FRONTEND_URL` | Override frontend URL | `https://web-production-5e1bc.up.railway.app` |
205
+ | `COLLABMARK_HOME` | Override global config directory | `~/.collabmark` |
206
+
207
+ ## Development
208
+
209
+ ```bash
210
+ cd cli
211
+
212
+ # Install with dev dependencies
213
+ pip install -e ".[dev]"
214
+
215
+ # Run all tests (313 tests)
216
+ python -m pytest -v
217
+
218
+ # Run tests with coverage
219
+ pytest --cov=collabmark
220
+
221
+ # Lint and format
222
+ ruff check src/ tests/
223
+ ruff format src/ tests/
224
+ ```
225
+
226
+ ## Releasing to PyPI
227
+
228
+ Releases are automated via GitHub Actions. To publish a new version:
229
+
230
+ 1. Update the version in `cli/src/collabmark/__init__.py` and `cli/pyproject.toml`
231
+ 2. Commit and push to `main`
232
+ 3. Create and push a tag: `git tag cli-v0.1.0 && git push origin cli-v0.1.0`
233
+ 4. The `cli-release.yml` workflow runs lint, tests, builds, and publishes to PyPI
234
+
235
+ ## Project Structure
236
+
237
+ ```
238
+ cli/
239
+ src/collabmark/
240
+ __init__.py Package version
241
+ __main__.py python -m collabmark entry point
242
+ main.py Root CLI group, welcome banner
243
+ types.py Shared dataclasses (SyncConfig, DocumentInfo, etc.)
244
+ commands/
245
+ init.py collabmark init
246
+ login.py collabmark login
247
+ logout.py collabmark logout
248
+ start.py collabmark start (with registry + heartbeat)
249
+ status.py collabmark status (global + project views)
250
+ stop.py collabmark stop (interactive + --all + --path)
251
+ logs.py collabmark logs (per-project + --all-syncs)
252
+ list_syncs.py collabmark list (global sync overview)
253
+ clean.py collabmark clean (stale entry removal)
254
+ lib/
255
+ api.py Async REST client with retry/backoff
256
+ auth.py Keychain credential management
257
+ browser_auth.py Browser-based OAuth flow
258
+ config.py .collabmark/ config and state management
259
+ crdt_sync.py CRDT WebSocket sync (pycrdt)
260
+ daemon.py Per-project PID file and process management
261
+ logger.py Per-project structured JSON logging
262
+ registry.py Centralized sync registry (~/.collabmark/registry.json)
263
+ sync_engine.py Three-way reconciliation and sync actions
264
+ watcher.py Debounced filesystem watcher
265
+ tests/ 313 tests
266
+ conftest.py Shared fixtures
267
+ test_api.py API client tests
268
+ test_auth.py Auth and keychain tests
269
+ test_browser_auth.py Browser OAuth flow tests
270
+ test_clean.py Clean command tests
271
+ test_config.py Config/state management tests
272
+ test_crdt_sync.py CRDT sync tests
273
+ test_daemon.py Per-project daemon PID tests
274
+ test_integration.py End-to-end sync flow tests
275
+ test_list_syncs.py List command tests
276
+ test_logger.py Logging tests
277
+ test_logs.py Logs command tests
278
+ test_main.py CLI entry point tests
279
+ test_registry.py Sync registry tests
280
+ test_start.py Start command tests
281
+ test_status.py Status command tests
282
+ test_stop.py Stop command tests
283
+ test_sync_engine.py Reconciliation logic tests
284
+ test_watcher.py File watcher tests
285
+ pyproject.toml hatchling build config + CLI entry point
286
+ ```
@@ -0,0 +1,266 @@
1
+ # CollabMark CLI
2
+
3
+ Keep your local markdown files in sync with your team's CollabMark cloud
4
+ workspace -- bidirectionally and in real time, powered by CRDTs.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ pip install collabmark
10
+ collabmark --version
11
+ ```
12
+
13
+ For development:
14
+
15
+ ```bash
16
+ cd cli
17
+ pip install -e ".[dev]"
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```bash
23
+ # Step 1: Log in (opens your browser for one-click authentication)
24
+ collabmark login
25
+
26
+ # Step 2: Start syncing the current directory
27
+ collabmark start
28
+
29
+ # That's it! Your .md files are now synced with CollabMark.
30
+ ```
31
+
32
+ Run `collabmark` with no arguments for a friendly getting-started guide.
33
+
34
+ ## Commands
35
+
36
+ ### `collabmark login`
37
+
38
+ Authenticate with CollabMark. Opens your browser for a one-click Google/SSO
39
+ login. Credentials are stored securely in your OS keychain via `keyring`.
40
+
41
+ ```bash
42
+ collabmark login # Browser login (recommended)
43
+ collabmark login --api-key <KEY> # API key fallback (headless environments)
44
+ ```
45
+
46
+ ### `collabmark logout`
47
+
48
+ Remove stored credentials from the OS keychain.
49
+
50
+ ```bash
51
+ collabmark logout
52
+ ```
53
+
54
+ ### `collabmark init`
55
+
56
+ Set up the current directory for syncing. Creates a `.collabmark/` config folder
57
+ and links to a cloud folder. After init, use `start` to begin syncing.
58
+
59
+ ```bash
60
+ collabmark init # Interactive folder picker
61
+ collabmark init <share-link> # Join a shared folder by link
62
+ ```
63
+
64
+ ### `collabmark start`
65
+
66
+ Begin syncing markdown files. Performs an initial sync, then watches for
67
+ changes on both sides. Content is synced via CRDT WebSocket for real-time
68
+ bidirectional updates; REST is used only for metadata and authentication.
69
+
70
+ ```bash
71
+ collabmark start # Sync current dir, choose folder interactively
72
+ collabmark start <share-link> # Join a shared folder by link
73
+ collabmark start -d # Run as a background daemon
74
+ collabmark start -p ~/notes # Sync a specific directory
75
+ collabmark start --interval 30 # Poll every 30 seconds (default: 10s)
76
+ ```
77
+
78
+ ### `collabmark status`
79
+
80
+ Show the current sync state. When run from a project directory, shows detailed
81
+ project info. When run without a project, shows a global overview of all syncs.
82
+
83
+ ```bash
84
+ collabmark status # Project-specific or global view
85
+ collabmark status -p ~/notes # Check a specific project
86
+ ```
87
+
88
+ ### `collabmark list`
89
+
90
+ List all registered syncs across all projects with status, PID, last sync
91
+ time, and cloud folder info.
92
+
93
+ ```bash
94
+ collabmark list
95
+ ```
96
+
97
+ ### `collabmark stop`
98
+
99
+ Gracefully stop sync processes. Supports interactive selection when multiple
100
+ syncs are running.
101
+
102
+ ```bash
103
+ collabmark stop # Stop current project or choose interactively
104
+ collabmark stop --all # Stop all running syncs
105
+ collabmark stop --path ~/notes # Stop a specific project's sync
106
+ ```
107
+
108
+ ### `collabmark logs`
109
+
110
+ View structured sync log output. Each sync project has its own log file.
111
+
112
+ ```bash
113
+ collabmark logs # Current project logs (last 50 entries)
114
+ collabmark logs -n 100 # Last 100 entries
115
+ collabmark logs -f # Follow in real time (like tail -f)
116
+ collabmark logs --folder <id> # Logs for a specific cloud folder
117
+ collabmark logs --all-syncs # Interleaved logs from all syncs
118
+ ```
119
+
120
+ ### `collabmark clean`
121
+
122
+ Remove stale entries from the sync registry (stopped syncs, missing directories).
123
+
124
+ ```bash
125
+ collabmark clean # Interactive selection of stale entries
126
+ collabmark clean --all # Remove all stopped entries
127
+ collabmark clean --force # Remove all entries (including running)
128
+ ```
129
+
130
+ ## How Sync Works
131
+
132
+ 1. **Local scan** -- finds all `.md` files recursively (ignoring `.collabmark/`).
133
+ 2. **Cloud scan** -- fetches the full folder tree from CollabMark in one API call.
134
+ 3. **Three-way reconciliation** -- compares local files, the last-known sync state
135
+ (`.collabmark/sync.json`), and cloud documents to determine what changed where.
136
+ 4. **CRDT sync** -- content is pushed/pulled via WebSocket using pycrdt (the same
137
+ CRDT library the server uses), so edits merge correctly with concurrent web users.
138
+ 5. **Continuous watch** -- uses OS filesystem events (debounced) plus periodic
139
+ cloud polling to keep both sides in sync.
140
+
141
+ ### Conflict Resolution
142
+
143
+ When the same file changes both locally and on the cloud between sync cycles,
144
+ it is flagged as a **conflict**. Neither side is overwritten. The conflict is
145
+ logged and shown in `collabmark logs`.
146
+
147
+ ## Monitoring & Observability
148
+
149
+ CollabMark CLI uses a centralized registry at `~/.collabmark/registry.json`
150
+ to track all active and stopped syncs. This enables:
151
+
152
+ - **Global visibility**: `collabmark list` shows all syncs at a glance
153
+ - **Per-project logs**: each sync writes to `~/.collabmark/logs/{folder_id}.log`
154
+ - **Heartbeat tracking**: last sync time, action count, and error status
155
+ - **Dead process detection**: `collabmark status` prunes crashed processes
156
+ - **Stale cleanup**: `collabmark clean` removes orphaned registry entries
157
+
158
+ ## Configuration
159
+
160
+ All per-project configuration lives in `.collabmark/` at the root of your
161
+ synced directory:
162
+
163
+ | File | Purpose |
164
+ |-------------------|----------------------------------------------|
165
+ | `config.json` | Linked cloud folder, server URL, user info |
166
+ | `sync.json` | Per-file sync state (hashes, doc IDs) |
167
+ | `trash/` | Files removed by cloud-side deletions |
168
+
169
+ Global state is stored under `~/.collabmark/`:
170
+
171
+ | Path | Purpose |
172
+ |-----------------------------------|------------------------------------------|
173
+ | `~/.collabmark/registry.json` | Centralized sync registry (all projects) |
174
+ | `~/.collabmark/logs/{id}.log` | Per-project structured JSON logs |
175
+ | `~/.collabmark/pids/{id}.pid` | Per-project PID files (daemon mode) |
176
+ | `~/.collabmark/credentials.json` | Non-sensitive login metadata |
177
+ | OS keychain | API key (encrypted, via `keyring`) |
178
+
179
+ ### Environment Variables
180
+
181
+ | Variable | Purpose | Default |
182
+ |---------------------------|------------------------------------|--------------------------------------------------|
183
+ | `COLLABMARK_API_URL` | Override API server URL | `https://web-production-5e1bc.up.railway.app` |
184
+ | `COLLABMARK_FRONTEND_URL` | Override frontend URL | `https://web-production-5e1bc.up.railway.app` |
185
+ | `COLLABMARK_HOME` | Override global config directory | `~/.collabmark` |
186
+
187
+ ## Development
188
+
189
+ ```bash
190
+ cd cli
191
+
192
+ # Install with dev dependencies
193
+ pip install -e ".[dev]"
194
+
195
+ # Run all tests (313 tests)
196
+ python -m pytest -v
197
+
198
+ # Run tests with coverage
199
+ pytest --cov=collabmark
200
+
201
+ # Lint and format
202
+ ruff check src/ tests/
203
+ ruff format src/ tests/
204
+ ```
205
+
206
+ ## Releasing to PyPI
207
+
208
+ Releases are automated via GitHub Actions. To publish a new version:
209
+
210
+ 1. Update the version in `cli/src/collabmark/__init__.py` and `cli/pyproject.toml`
211
+ 2. Commit and push to `main`
212
+ 3. Create and push a tag: `git tag cli-v0.1.0 && git push origin cli-v0.1.0`
213
+ 4. The `cli-release.yml` workflow runs lint, tests, builds, and publishes to PyPI
214
+
215
+ ## Project Structure
216
+
217
+ ```
218
+ cli/
219
+ src/collabmark/
220
+ __init__.py Package version
221
+ __main__.py python -m collabmark entry point
222
+ main.py Root CLI group, welcome banner
223
+ types.py Shared dataclasses (SyncConfig, DocumentInfo, etc.)
224
+ commands/
225
+ init.py collabmark init
226
+ login.py collabmark login
227
+ logout.py collabmark logout
228
+ start.py collabmark start (with registry + heartbeat)
229
+ status.py collabmark status (global + project views)
230
+ stop.py collabmark stop (interactive + --all + --path)
231
+ logs.py collabmark logs (per-project + --all-syncs)
232
+ list_syncs.py collabmark list (global sync overview)
233
+ clean.py collabmark clean (stale entry removal)
234
+ lib/
235
+ api.py Async REST client with retry/backoff
236
+ auth.py Keychain credential management
237
+ browser_auth.py Browser-based OAuth flow
238
+ config.py .collabmark/ config and state management
239
+ crdt_sync.py CRDT WebSocket sync (pycrdt)
240
+ daemon.py Per-project PID file and process management
241
+ logger.py Per-project structured JSON logging
242
+ registry.py Centralized sync registry (~/.collabmark/registry.json)
243
+ sync_engine.py Three-way reconciliation and sync actions
244
+ watcher.py Debounced filesystem watcher
245
+ tests/ 313 tests
246
+ conftest.py Shared fixtures
247
+ test_api.py API client tests
248
+ test_auth.py Auth and keychain tests
249
+ test_browser_auth.py Browser OAuth flow tests
250
+ test_clean.py Clean command tests
251
+ test_config.py Config/state management tests
252
+ test_crdt_sync.py CRDT sync tests
253
+ test_daemon.py Per-project daemon PID tests
254
+ test_integration.py End-to-end sync flow tests
255
+ test_list_syncs.py List command tests
256
+ test_logger.py Logging tests
257
+ test_logs.py Logs command tests
258
+ test_main.py CLI entry point tests
259
+ test_registry.py Sync registry tests
260
+ test_start.py Start command tests
261
+ test_status.py Status command tests
262
+ test_stop.py Stop command tests
263
+ test_sync_engine.py Reconciliation logic tests
264
+ test_watcher.py File watcher tests
265
+ pyproject.toml hatchling build config + CLI entry point
266
+ ```
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "collabmark"
7
+ version = "0.1.0"
8
+ description = "Sync markdown files with CollabMark cloud"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license = "MIT"
12
+
13
+ dependencies = [
14
+ "click>=8.1",
15
+ "rich>=13.0",
16
+ "httpx>=0.27",
17
+ "watchdog>=4.0",
18
+ "keyring>=25.0",
19
+ "pycrdt>=0.12",
20
+ "websockets>=14.0",
21
+ ]
22
+
23
+ [project.optional-dependencies]
24
+ dev = [
25
+ "pytest>=8.0",
26
+ "pytest-asyncio>=0.24",
27
+ "respx>=0.22",
28
+ "ruff>=0.8",
29
+ ]
30
+
31
+ [project.scripts]
32
+ collabmark = "collabmark.main:cli"
33
+
34
+ [tool.hatch.build.targets.wheel]
35
+ packages = ["src/collabmark"]
36
+
37
+ [tool.pytest.ini_options]
38
+ testpaths = ["tests"]
39
+ asyncio_mode = "auto"
40
+
41
+ [tool.ruff]
42
+ target-version = "py312"
43
+ line-length = 120
44
+
45
+ [tool.ruff.lint]
46
+ select = ["E", "F", "I", "W", "RUF"]
@@ -0,0 +1,3 @@
1
+ """CollabMark CLI — sync markdown files with CollabMark cloud."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,5 @@
1
+ """Allow ``python -m collabmark`` invocation."""
2
+
3
+ from collabmark.main import cli
4
+
5
+ cli()
@@ -0,0 +1 @@
1
+ """CLI command implementations."""