code-data-ark 2.0.4__tar.gz → 2.0.5__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 (35) hide show
  1. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/PKG-INFO +39 -20
  2. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/ui/cli.py +202 -3
  3. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/changelog.md +11 -0
  4. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/pyproject.toml +1 -1
  5. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/readme.md +38 -19
  6. code_data_ark-2.0.5/version +1 -0
  7. code_data_ark-2.0.4/version +0 -1
  8. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/.flake8 +0 -0
  9. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/.github/workflows/ci.yml +0 -0
  10. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/.gitignore +0 -0
  11. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/bin/release.py +0 -0
  12. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/__init__.py +0 -0
  13. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/kernel/__init__.py +0 -0
  14. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/kernel/control_db.py +0 -0
  15. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/kernel/paths.py +0 -0
  16. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/kernel/pmf_kernel.py +0 -0
  17. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/kernel/selfcheck.py +0 -0
  18. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/pipeline/__init__.py +0 -0
  19. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/pipeline/embed.py +0 -0
  20. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/pipeline/extract.py +0 -0
  21. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/pipeline/ingest.py +0 -0
  22. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/pipeline/parse_edits.py +0 -0
  23. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/pipeline/reconstruct.py +0 -0
  24. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/pipeline/watcher.py +0 -0
  25. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/ui/__init__.py +0 -0
  26. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/cda/ui/web.py +0 -0
  27. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/contributing.md +0 -0
  28. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/docs/architecture.md +0 -0
  29. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/docs/examples/usage.md +0 -0
  30. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/docs/pmf_kernel.md +0 -0
  31. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/docs/roadmap.md +0 -0
  32. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/license +0 -0
  33. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/makefile +0 -0
  34. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/tests/test_basic.py +0 -0
  35. {code_data_ark-2.0.4 → code_data_ark-2.0.5}/tests/test_selfcheck.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-data-ark
3
- Version: 2.0.4
3
+ Version: 2.0.5
4
4
  Summary: Code Data Ark — local observability and intelligence platform for VS Code + Copilot Chat sessions
5
5
  Project-URL: Homepage, https://github.com/goCosmix/cda
6
6
  Project-URL: Repository, https://github.com/goCosmix/cda.git
@@ -121,48 +121,67 @@ make install-dev
121
121
 
122
122
  ## ⚡ Quick Start
123
123
 
124
- 1. **Install**
125
-
126
124
  ```bash
127
125
  pip install code-data-ark
126
+ cda setup
128
127
  ```
129
128
 
130
- 2. **Initialize — create `~/.cda/` and validate your VS Code data path**
129
+ That's it. `cda setup` runs four steps in sequence:
131
130
 
132
- ```bash
133
- cda init
134
- ```
131
+ | Step | What it does |
132
+ |------|-------------|
133
+ | **1. Init** | Creates `~/.cda/` directory tree, validates your VS Code data path |
134
+ | **2. PMF install** | Registers a macOS LaunchAgent — CDA starts automatically on every login |
135
+ | **3. Sync** | Ingests all VS Code + Copilot session data into `~/.cda/data/cda.db` |
136
+ | **4. Up** | Starts the watcher daemon and web UI via the PMF kernel, opens browser |
137
+
138
+ After setup, everything is managed by the **PMF kernel**. On every login, `launchd` calls `cda pmf up` which starts the watcher and web UI. No terminal interaction required.
135
139
 
136
- 3. **Ingest all VS Code session data**
140
+ ### Options
137
141
 
138
142
  ```bash
139
- cda sync
143
+ cda setup --skip-sync # Skip initial ingest (run `cda sync` manually later)
144
+ cda setup --no-browser # Don't open browser when the UI starts
140
145
  ```
141
146
 
142
- 4. **Start the live watcher daemon**
147
+ ### After setup
143
148
 
144
149
  ```bash
145
- cda watch start
150
+ cda check # Full system health diagnostic
151
+ cda sync # Re-ingest after significant new session activity
152
+ cda pmf services # View all running services and their status
153
+ cda pmf uninstall # Remove the auto-start LaunchAgent registration
146
154
  ```
147
155
 
148
- 5. **Open the web dashboard**
156
+ ## 🔧 Process Management (PMF)
149
157
 
150
- ```bash
151
- cda serve # → http://127.0.0.1:10001
158
+ All background processes run through the embedded PMF kernel. The LaunchAgent is the entry point — nothing starts directly on the host outside of PMF.
159
+
160
+ ```
161
+ launchd (login)
162
+ └─ cda pmf up
163
+ ├─ PMF kernel → watcher daemon (cda.pipeline.watcher)
164
+ └─ PMF kernel → web UI server (cda.ui.web)
152
165
  ```
153
166
 
154
- 6. **Build semantic intelligence** (optional, requires `sentence-transformers`)
167
+ ### PMF commands
155
168
 
156
169
  ```bash
157
- cda embed build
170
+ cda pmf services # List all services with status and PID
171
+ cda pmf start <service> # Start a service (watcher, ui, sync, reconstruct, embed-build)
172
+ cda pmf stop <service> # Stop a service
173
+ cda pmf restart <service> # Restart a service
174
+ cda pmf logs <service> # Tail the service log
175
+ cda pmf up # Start watcher + UI (opens browser) — same as launchd trigger
176
+ cda pmf install # Register LaunchAgent (done automatically by cda setup)
177
+ cda pmf uninstall # Remove LaunchAgent
158
178
  ```
159
179
 
160
180
  ## 🌐 Web UI
161
181
 
162
- - **Background service**: `cda ui start`
163
- - **Stop service**: `cda ui stop`
164
- - **Service status**: `cda ui status`
165
- - **Foreground mode**: `cda serve`
182
+ - **Background service** (default after setup): managed by PMF, starts on login
183
+ - **Foreground mode**: `cda serve` — runs in the terminal, opens browser, Ctrl+C to stop
184
+ - **Access**: `http://127.0.0.1:10001`
166
185
 
167
186
  The web UI includes:
168
187
 
@@ -29,6 +29,7 @@ Commands:
29
29
  cda pmf uninstall Remove the LaunchAgent registration
30
30
  cda check Run a full self-diagnostic. The system checks itself.
31
31
  cda init First-run setup — create ~/.cda/ and validate environment
32
+ cda setup Full onboarding: init → pmf install → sync → up (browser opens)
32
33
  cda serve Start the local web UI on port 10001
33
34
  cda sync Full re-ingest from disk (rebuilds entire DB)
34
35
  cda reconstruct Re-run reconstruction and FTS rebuild only
@@ -80,6 +81,14 @@ import click
80
81
  # Ensure runtime dirs exist on every CLI invocation
81
82
  ensure_dirs()
82
83
 
84
+
85
+ def _pmf_warn_if_not_installed():
86
+ """Emit a one-time advisory if the LaunchAgent is not registered."""
87
+ if not plist_path().exists():
88
+ click.echo(yellow(" Note: LaunchAgent not installed — services won't auto-start on login."))
89
+ click.echo(yellow(" Run `cda setup` to register, or `cda pmf install` to add just the plist."))
90
+
91
+
83
92
  kernel = PMFKernel()
84
93
 
85
94
 
@@ -408,7 +417,8 @@ def _ui_is_running():
408
417
  @click.option("--port", default=10001, show_default=True, help="Local port for the web UI")
409
418
  @click.option("--no-browser", "no_browser", is_flag=True, default=False, help="Don't open browser automatically")
410
419
  def ui_start(host, port, no_browser):
411
- """Start the web UI as a background service."""
420
+ """Start the web UI as a background service (via PMF kernel)."""
421
+ _pmf_warn_if_not_installed()
412
422
  try:
413
423
  result = kernel.start_service("ui", options={"host": host, "port": port})
414
424
  url = f"http://{host}:{port}"
@@ -788,10 +798,11 @@ def watch():
788
798
 
789
799
  @watch.command("start")
790
800
  def watch_start():
791
- """Start the live sync watcher daemon."""
801
+ """Start the live sync watcher daemon (via PMF kernel)."""
802
+ _pmf_warn_if_not_installed()
792
803
  try:
793
804
  result = kernel.start_service("watcher")
794
- click.echo(green(f" Watcher started pid={result['pid']}"))
805
+ click.echo(green(f" Watcher started pid={result['pid']} (via PMF)"))
795
806
  except PMFKernelError as exc:
796
807
  click.echo(red(f" {exc}"))
797
808
 
@@ -2646,6 +2657,194 @@ def check(as_json, fail_fast):
2646
2657
  sys.exit(0 if passed_all else 1)
2647
2658
 
2648
2659
 
2660
+ # ─────────────────────────────────────────────
2661
+ # SETUP
2662
+ # ─────────────────────────────────────────────
2663
+
2664
+ @cli.command("setup")
2665
+ @click.option("--skip-sync", "skip_sync", is_flag=True, default=False,
2666
+ help="Skip initial data ingest (run `cda sync` manually later)")
2667
+ @click.option("--no-browser", "no_browser", is_flag=True, default=False,
2668
+ help="Don't open browser when the web UI starts")
2669
+ def setup(skip_sync, no_browser):
2670
+ """
2671
+ Full onboarding in four steps: init → pmf install → sync → up.
2672
+
2673
+ \b
2674
+ Run this once after `pip install code-data-ark`:
2675
+
2676
+ cda setup
2677
+
2678
+ \b
2679
+ What each step does:
2680
+ 1. Init — create ~/.cda/ directory tree, validate VS Code data path
2681
+ 2. Install — register a macOS LaunchAgent so CDA starts on every login
2682
+ 3. Sync — ingest all VS Code + Copilot session data into cda.db
2683
+ 4. Up — start the watcher daemon and web UI via PMF, open browser
2684
+
2685
+ All processes are managed by the PMF kernel. The LaunchAgent calls
2686
+ `cda pmf up` on every login — no manual interaction needed after setup.
2687
+ """
2688
+ from cda.kernel.paths import (
2689
+ CDA_HOME, DATA_DIR, RUN_DIR, LOG_DIR, QUEUE_DIR,
2690
+ PMF_DIR, PMF_LOG_DIR, CONFIG_DIR, POLICY_FILE,
2691
+ )
2692
+ import os as _os
2693
+
2694
+ W = 52
2695
+ BAR = "═" * W
2696
+ bar = "─" * W
2697
+ host, port = "127.0.0.1", 10001
2698
+ url = f"http://{host}:{port}"
2699
+
2700
+ click.echo()
2701
+ click.echo(bold(BAR))
2702
+ click.echo(bold(" Code Data Ark — setup"))
2703
+ click.echo(bold(BAR))
2704
+ click.echo()
2705
+ click.echo(dim(" Four steps to a fully operational CDA installation:"))
2706
+ click.echo(dim(f" 1. Init — create {CDA_HOME}"))
2707
+ click.echo(dim(" 2. Install — register macOS LaunchAgent (auto-start on login)"))
2708
+ click.echo(dim(" 3. Sync — first-run data ingest") + (dim(" [skipped]") if skip_sync else ""))
2709
+ click.echo(dim(" 4. Up — start watcher + web UI via PMF, open browser"))
2710
+ click.echo()
2711
+
2712
+ # ── Step 1: Init ─────────────────────────────────────────────
2713
+ click.echo(bold(bar))
2714
+ click.echo(bold(" Step 1/4 — Init"))
2715
+ click.echo(bold(bar))
2716
+ click.echo()
2717
+
2718
+ dirs = [DATA_DIR, RUN_DIR, LOG_DIR, QUEUE_DIR, PMF_DIR, PMF_LOG_DIR, CONFIG_DIR]
2719
+ for d in dirs:
2720
+ d.mkdir(parents=True, exist_ok=True)
2721
+ click.echo(f" {green('✓')} {d}")
2722
+
2723
+ if not POLICY_FILE.exists():
2724
+ POLICY_FILE.write_text("# CDA access policy\n# ALLOW <pattern>\n# DENY <pattern>\n")
2725
+
2726
+ vscode_data = Path(_os.environ.get(
2727
+ "VSCODE_DATA_DIR",
2728
+ Path.home() / "Library/Application Support/Code/User",
2729
+ ))
2730
+ if vscode_data.exists():
2731
+ click.echo(f" {green('✓')} VS Code data dir found")
2732
+ else:
2733
+ click.echo(f" {yellow('⚠')} VS Code data dir not found: {vscode_data}")
2734
+ click.echo(yellow(" Set VSCODE_DATA_DIR if your data is elsewhere."))
2735
+
2736
+ click.echo()
2737
+ click.echo(f" {green('✓')} CDA_HOME: {CDA_HOME}")
2738
+ click.echo()
2739
+
2740
+ # ── Step 2: PMF install ──────────────────────────────────────
2741
+ click.echo(bold(bar))
2742
+ click.echo(bold(" Step 2/4 — PMF install"))
2743
+ click.echo(bold(bar))
2744
+ click.echo()
2745
+ click.echo(dim(" The LaunchAgent registers CDA with macOS launchd. On every login,"))
2746
+ click.echo(dim(" launchd calls `cda pmf up` which starts the watcher daemon and"))
2747
+ click.echo(dim(" web UI via the PMF kernel — no terminal required."))
2748
+ click.echo()
2749
+
2750
+ pmf_ok = False
2751
+ try:
2752
+ target = install_launchd(CDA_HOME)
2753
+ click.echo(f" {green('✓')} LaunchAgent: {target}")
2754
+ click.echo(f" {green('✓')} Loaded — CDA will start automatically on every login")
2755
+ pmf_ok = True
2756
+ except PMFKernelError as exc:
2757
+ click.echo(f" {yellow('⚠')} LaunchAgent registration failed: {exc}")
2758
+ click.echo(yellow(" Ensure `cda` is on PATH, then run `cda pmf install` to retry."))
2759
+ click.echo()
2760
+
2761
+ # ── Step 3: Sync ─────────────────────────────────────────────
2762
+ click.echo(bold(bar))
2763
+ click.echo(bold(" Step 3/4 — Sync"))
2764
+ click.echo(bold(bar))
2765
+ click.echo()
2766
+
2767
+ if skip_sync:
2768
+ click.echo(f" {yellow('↳')} Skipped (--skip-sync). Run `cda sync` when ready.")
2769
+ click.echo()
2770
+ else:
2771
+ click.echo(dim(" Scanning VS Code workspaceStorage and building cda.db."))
2772
+ click.echo(dim(" First run may take several minutes depending on session history."))
2773
+ click.echo()
2774
+
2775
+ sync_failed = False
2776
+ stages = [
2777
+ ("cda.pipeline.ingest", "Ingest — reading VS Code storage"),
2778
+ ("cda.pipeline.reconstruct", "Reconstruct — building exchanges + FTS"),
2779
+ ("cda.pipeline.extract", "Extract — behavioral signals + tokens"),
2780
+ ("cda.pipeline.embed", "Embed — semantic intelligence layer"),
2781
+ ]
2782
+ for module, label in stages:
2783
+ click.echo(yellow(f" → {label}"))
2784
+ result = subprocess.run([sys.executable, "-m", module], capture_output=False)
2785
+ if result.returncode != 0:
2786
+ click.echo(red(" ✗ Failed — sync incomplete"))
2787
+ sync_failed = True
2788
+ break
2789
+ click.echo(green(" ✓ Done"))
2790
+ click.echo()
2791
+
2792
+ if not sync_failed:
2793
+ click.echo(green(" ✓ Sync complete"))
2794
+ click.echo()
2795
+
2796
+ # ── Step 4: Up ───────────────────────────────────────────────
2797
+ click.echo(bold(bar))
2798
+ click.echo(bold(" Step 4/4 — Up"))
2799
+ click.echo(bold(bar))
2800
+ click.echo()
2801
+ click.echo(dim(" Starting all services through the PMF kernel."))
2802
+ click.echo(dim(" Each process is tracked, logged, and restartable via `cda pmf`."))
2803
+ click.echo()
2804
+
2805
+ for svc_id, opts, label in [
2806
+ ("watcher", None, "Watcher daemon"),
2807
+ ("ui", {"host": host, "port": port}, f"Web UI → {url}"),
2808
+ ]:
2809
+ try:
2810
+ result = kernel.start_service(svc_id, options=opts)
2811
+ click.echo(f" {green('✓')} {label} pid={result['pid']}")
2812
+ except PMFKernelError as exc:
2813
+ msg = str(exc)
2814
+ if "already running" in msg.lower():
2815
+ click.echo(f" {green('✓')} {label} (already running)")
2816
+ else:
2817
+ click.echo(f" {yellow('⚠')} {label} {msg}")
2818
+
2819
+ click.echo()
2820
+
2821
+ if not no_browser:
2822
+ click.echo(dim(" Waiting for web UI..."))
2823
+ opened = wait_for_port_and_open_browser(url, host, port)
2824
+ if opened:
2825
+ click.echo(f" {green('✓')} Browser opened: {url}")
2826
+ else:
2827
+ click.echo(f" {yellow('⚠')} Server not responding yet — visit {url} manually")
2828
+ click.echo()
2829
+
2830
+ # ── Done ─────────────────────────────────────────────────────
2831
+ click.echo(bold(BAR))
2832
+ click.echo(bold(" Setup complete."))
2833
+ click.echo(bold(BAR))
2834
+ click.echo()
2835
+ if pmf_ok:
2836
+ click.echo(dim(" CDA will start automatically on every login via launchd."))
2837
+ click.echo(dim(" The watcher daemon stays in sync with your VS Code sessions."))
2838
+ click.echo(dim(f" Visit {url} any time to explore your data."))
2839
+ click.echo()
2840
+ click.echo(dim(" Useful commands:"))
2841
+ click.echo(dim(" cda check — full system health diagnostic"))
2842
+ click.echo(dim(" cda sync — re-ingest after significant new session activity"))
2843
+ click.echo(dim(" cda pmf services — view running services and their status"))
2844
+ click.echo(dim(" cda pmf uninstall — remove auto-start LaunchAgent registration"))
2845
+ click.echo()
2846
+
2847
+
2649
2848
  # ─────────────────────────────────────────────
2650
2849
  # INIT
2651
2850
  # ─────────────────────────────────────────────
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.0.5] - 2026-05-11
9
+
10
+ ### Added
11
+ - **`cda setup`** — master onboarding command: init → pmf install → sync → up. Replaces the four-step manual process with a single command. Idempotent, safe to re-run. Accepts `--skip-sync` and `--no-browser`.
12
+ - **PMF-first architecture**: all background processes (watcher, web UI) start exclusively through the PMF kernel. `cda watch start` and `cda ui start` now display an advisory if the LaunchAgent is not installed.
13
+ - `_pmf_warn_if_not_installed()` helper — emitted before any background service start when the LaunchAgent plist is absent.
14
+
15
+ ### Changed
16
+ - README quickstart simplified to two commands: `pip install code-data-ark` + `cda setup`
17
+ - Added PMF architecture diagram and process management reference to README
18
+
8
19
  ## [2.0.4] - 2026-05-11
9
20
 
10
21
  ### Added
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "code-data-ark"
7
- version = "2.0.4"
7
+ version = "2.0.5"
8
8
  description = "Code Data Ark — local observability and intelligence platform for VS Code + Copilot Chat sessions"
9
9
  readme = "readme.md"
10
10
  license = "MIT"
@@ -78,48 +78,67 @@ make install-dev
78
78
 
79
79
  ## ⚡ Quick Start
80
80
 
81
- 1. **Install**
82
-
83
81
  ```bash
84
82
  pip install code-data-ark
83
+ cda setup
85
84
  ```
86
85
 
87
- 2. **Initialize — create `~/.cda/` and validate your VS Code data path**
86
+ That's it. `cda setup` runs four steps in sequence:
88
87
 
89
- ```bash
90
- cda init
91
- ```
88
+ | Step | What it does |
89
+ |------|-------------|
90
+ | **1. Init** | Creates `~/.cda/` directory tree, validates your VS Code data path |
91
+ | **2. PMF install** | Registers a macOS LaunchAgent — CDA starts automatically on every login |
92
+ | **3. Sync** | Ingests all VS Code + Copilot session data into `~/.cda/data/cda.db` |
93
+ | **4. Up** | Starts the watcher daemon and web UI via the PMF kernel, opens browser |
94
+
95
+ After setup, everything is managed by the **PMF kernel**. On every login, `launchd` calls `cda pmf up` which starts the watcher and web UI. No terminal interaction required.
92
96
 
93
- 3. **Ingest all VS Code session data**
97
+ ### Options
94
98
 
95
99
  ```bash
96
- cda sync
100
+ cda setup --skip-sync # Skip initial ingest (run `cda sync` manually later)
101
+ cda setup --no-browser # Don't open browser when the UI starts
97
102
  ```
98
103
 
99
- 4. **Start the live watcher daemon**
104
+ ### After setup
100
105
 
101
106
  ```bash
102
- cda watch start
107
+ cda check # Full system health diagnostic
108
+ cda sync # Re-ingest after significant new session activity
109
+ cda pmf services # View all running services and their status
110
+ cda pmf uninstall # Remove the auto-start LaunchAgent registration
103
111
  ```
104
112
 
105
- 5. **Open the web dashboard**
113
+ ## 🔧 Process Management (PMF)
106
114
 
107
- ```bash
108
- cda serve # → http://127.0.0.1:10001
115
+ All background processes run through the embedded PMF kernel. The LaunchAgent is the entry point — nothing starts directly on the host outside of PMF.
116
+
117
+ ```
118
+ launchd (login)
119
+ └─ cda pmf up
120
+ ├─ PMF kernel → watcher daemon (cda.pipeline.watcher)
121
+ └─ PMF kernel → web UI server (cda.ui.web)
109
122
  ```
110
123
 
111
- 6. **Build semantic intelligence** (optional, requires `sentence-transformers`)
124
+ ### PMF commands
112
125
 
113
126
  ```bash
114
- cda embed build
127
+ cda pmf services # List all services with status and PID
128
+ cda pmf start <service> # Start a service (watcher, ui, sync, reconstruct, embed-build)
129
+ cda pmf stop <service> # Stop a service
130
+ cda pmf restart <service> # Restart a service
131
+ cda pmf logs <service> # Tail the service log
132
+ cda pmf up # Start watcher + UI (opens browser) — same as launchd trigger
133
+ cda pmf install # Register LaunchAgent (done automatically by cda setup)
134
+ cda pmf uninstall # Remove LaunchAgent
115
135
  ```
116
136
 
117
137
  ## 🌐 Web UI
118
138
 
119
- - **Background service**: `cda ui start`
120
- - **Stop service**: `cda ui stop`
121
- - **Service status**: `cda ui status`
122
- - **Foreground mode**: `cda serve`
139
+ - **Background service** (default after setup): managed by PMF, starts on login
140
+ - **Foreground mode**: `cda serve` — runs in the terminal, opens browser, Ctrl+C to stop
141
+ - **Access**: `http://127.0.0.1:10001`
123
142
 
124
143
  The web UI includes:
125
144
 
@@ -0,0 +1 @@
1
+ 2.0.5
@@ -1 +0,0 @@
1
- 2.0.4
File without changes
File without changes
File without changes
File without changes