nazar-bridge 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 (31) hide show
  1. nazar_bridge-0.1.0/LICENSE +21 -0
  2. nazar_bridge-0.1.0/PKG-INFO +240 -0
  3. nazar_bridge-0.1.0/README.md +207 -0
  4. nazar_bridge-0.1.0/nazar_bridge/__init__.py +21 -0
  5. nazar_bridge-0.1.0/nazar_bridge/__main__.py +13 -0
  6. nazar_bridge-0.1.0/nazar_bridge/claude_runner.py +534 -0
  7. nazar_bridge-0.1.0/nazar_bridge/cli.py +595 -0
  8. nazar_bridge-0.1.0/nazar_bridge/client.py +213 -0
  9. nazar_bridge-0.1.0/nazar_bridge/config.py +286 -0
  10. nazar_bridge-0.1.0/nazar_bridge/desk.py +328 -0
  11. nazar_bridge-0.1.0/nazar_bridge/exceptions.py +68 -0
  12. nazar_bridge-0.1.0/nazar_bridge/py.typed +0 -0
  13. nazar_bridge-0.1.0/nazar_bridge/runner.py +609 -0
  14. nazar_bridge-0.1.0/nazar_bridge/service.py +356 -0
  15. nazar_bridge-0.1.0/nazar_bridge/wire.py +170 -0
  16. nazar_bridge-0.1.0/nazar_bridge.egg-info/PKG-INFO +240 -0
  17. nazar_bridge-0.1.0/nazar_bridge.egg-info/SOURCES.txt +29 -0
  18. nazar_bridge-0.1.0/nazar_bridge.egg-info/dependency_links.txt +1 -0
  19. nazar_bridge-0.1.0/nazar_bridge.egg-info/entry_points.txt +2 -0
  20. nazar_bridge-0.1.0/nazar_bridge.egg-info/requires.txt +8 -0
  21. nazar_bridge-0.1.0/nazar_bridge.egg-info/top_level.txt +1 -0
  22. nazar_bridge-0.1.0/pyproject.toml +103 -0
  23. nazar_bridge-0.1.0/setup.cfg +4 -0
  24. nazar_bridge-0.1.0/tests/test_claude_runner.py +417 -0
  25. nazar_bridge-0.1.0/tests/test_cli.py +643 -0
  26. nazar_bridge-0.1.0/tests/test_client_handshake.py +147 -0
  27. nazar_bridge-0.1.0/tests/test_config.py +135 -0
  28. nazar_bridge-0.1.0/tests/test_desk.py +200 -0
  29. nazar_bridge-0.1.0/tests/test_runner_loop.py +832 -0
  30. nazar_bridge-0.1.0/tests/test_service.py +78 -0
  31. nazar_bridge-0.1.0/tests/test_wire.py +53 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,240 @@
1
+ Metadata-Version: 2.4
2
+ Name: nazar-bridge
3
+ Version: 0.1.0
4
+ Summary: Nazar bridge daemon — relays phone prompts to local `claude -p` over a long-lived WebSocket.
5
+ Author: Arman
6
+ Maintainer: Arman
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/arm-yan/nazar
9
+ Project-URL: Repository, https://github.com/arm-yan/nazar
10
+ Project-URL: Issues, https://github.com/arm-yan/nazar/issues
11
+ Keywords: nazar,claude,claude-code,daemon,websocket,bridge,ai-assistant,remote-control
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Build Tools
20
+ Classifier: Topic :: Utilities
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.12
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: websockets<17,>=15
26
+ Requires-Dist: pydantic<3,>=2
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest==9.0.3; extra == "dev"
29
+ Requires-Dist: pytest-asyncio==1.3.0; extra == "dev"
30
+ Requires-Dist: ruff==0.15.12; extra == "dev"
31
+ Requires-Dist: mypy==2.1.0; extra == "dev"
32
+ Dynamic: license-file
33
+
34
+ # nazar-bridge
35
+
36
+ `nazar-bridge` is a small, open-source daemon that lets you drive
37
+ [Claude Code](https://claude.com/claude-code) on your own machine from the
38
+ [Nazar](https://github.com/arm-yan/nazar) phone dashboard.
39
+
40
+ It holds a single long-lived **outbound** WebSocket connection to the Nazar
41
+ API, registers your local Claude-Code project directories, and — when you send
42
+ a prompt from your phone — spawns `claude -p` in the matching project and
43
+ streams the output back. Nothing listens for inbound connections on your
44
+ machine; the daemon dials out, so there are no ports to open.
45
+
46
+ The source is intentionally small and auditable — read it before you install
47
+ it. That's the whole trust model (see [Trust & supply chain](#trust--supply-chain)).
48
+
49
+ ---
50
+
51
+ ## Prerequisites
52
+
53
+ - **Python 3.12+** on your machine.
54
+ - **[Claude Code](https://claude.com/claude-code) installed and authenticated.**
55
+ The daemon shells out to the `claude` CLI using *your* logged-in session, so
56
+ `claude` must be on your `PATH` and already signed in.
57
+ - **A Nazar account on a Pro or Unlimited plan.** The bridge is a paid-tier
58
+ feature — **the Free plan has no bridge** and cannot mint daemon tokens.
59
+
60
+ ---
61
+
62
+ ## Install
63
+
64
+ Recommended (isolated tool install via [uv](https://docs.astral.sh/uv/)):
65
+
66
+ ```bash
67
+ uv tool install nazar-bridge
68
+ ```
69
+
70
+ Alternative (via [pipx](https://pipx.pypa.io/)):
71
+
72
+ ```bash
73
+ pipx install nazar-bridge
74
+ ```
75
+
76
+ Upgrade later:
77
+
78
+ ```bash
79
+ uv tool upgrade nazar-bridge # or: pipx upgrade nazar-bridge
80
+ ```
81
+
82
+ Both put a `nazar-bridge` command on your `PATH`.
83
+
84
+ ---
85
+
86
+ ## Connect
87
+
88
+ 1. **Get a daemon token.** In the Nazar dashboard, open **/code → Bridge
89
+ tokens** and create one. It looks like `nazar_bridge_xxxxxxxxxxxxxxxx`.
90
+ Copy it now — it's shown only once.
91
+
92
+ 2. **Configure the daemon** with the token (and, if your API host differs from
93
+ the default, the WebSocket URL):
94
+
95
+ ```bash
96
+ nazar-bridge configure --token nazar_bridge_xxxxxxxxxxxxxxxx
97
+ # to point at a self-hosted / dev API instead of the default:
98
+ nazar-bridge configure --token nazar_bridge_xxxx --api-url wss://your-host/api/bridge/ws
99
+ ```
100
+
101
+ 3. **Register the project directories** you want reachable from your phone:
102
+
103
+ ```bash
104
+ nazar-bridge add /path/to/your/project
105
+ nazar-bridge add /path/to/another/project
106
+ nazar-bridge list
107
+ ```
108
+
109
+ 4. **Run it.** Either start it once in a terminal:
110
+
111
+ ```bash
112
+ nazar-bridge run # add --debug for verbose logs
113
+ ```
114
+
115
+ …or install it as a login autostart service (recommended — see below) so it
116
+ reconnects automatically after a reboot.
117
+
118
+ `run --once` exits right after the first successful register — handy for
119
+ smoke-testing a freshly-configured daemon.
120
+
121
+ ---
122
+
123
+ ## Autostart at login (recommended)
124
+
125
+ Instead of leaving a terminal open, register the daemon to start at login and
126
+ restart on failure. One cross-platform command detects your OS and writes the
127
+ right unit:
128
+
129
+ ```bash
130
+ nazar-bridge service install # Windows / macOS / Linux
131
+ nazar-bridge service status # is it installed / running?
132
+ nazar-bridge service uninstall # remove it
133
+ ```
134
+
135
+ | OS | What `service install` creates |
136
+ | ------- | ------------------------------------------------------------------------- |
137
+ | Windows | A Task Scheduler task **"Nazar Bridge"** that runs at logon (windowless). |
138
+ | macOS | A launchd LaunchAgent `app.nazar.bridge` in `~/Library/LaunchAgents`. |
139
+ | Linux | A systemd `--user` unit `nazar-bridge.service` (enabled + started). |
140
+
141
+ The service always runs **as your own user** (never root/SYSTEM) because the
142
+ daemon spawns `claude` with your personal Claude Code login — `service install`
143
+ refuses to run as root. On Linux, run `loginctl enable-linger $USER` if you
144
+ want the daemon up even when you're not logged in interactively.
145
+
146
+ Logs go to the daemon's rotating log file (see below) regardless of how it's
147
+ started. For live debugging, run `nazar-bridge run` in a terminal to watch
148
+ output directly.
149
+
150
+ > **Windows note:** earlier releases shipped
151
+ > `scripts/install-windows-startup.ps1`. That script still works and adds a
152
+ > richer restart policy, but `nazar-bridge service install` is now the
153
+ > recommended, cross-platform path.
154
+
155
+ ---
156
+
157
+ ## Where config & logs live
158
+
159
+ | OS | Config file | Daemon log |
160
+ | ------- | ---------------------------------------------------- | --------------------------- |
161
+ | Windows | `%APPDATA%\nazar-bridge\config.toml` | `%APPDATA%\nazar-bridge\daemon.log` |
162
+ | macOS | `~/.config/nazar-bridge/config.toml` | `~/.config/nazar-bridge/daemon.log` |
163
+ | Linux | `$XDG_CONFIG_HOME/nazar-bridge/config.toml` or | `…/nazar-bridge/daemon.log` |
164
+ | | `~/.config/nazar-bridge/config.toml` | |
165
+
166
+ The token is stored **plaintext** in `config.toml` — it's the daemon's only
167
+ credential. Protect it with filesystem permissions:
168
+
169
+ - **Windows:** `icacls "%APPDATA%\nazar-bridge\config.toml" /inheritance:r /grant:r "%USERNAME%:F"`
170
+ - **macOS / Linux:** `chmod 600 ~/.config/nazar-bridge/config.toml`
171
+
172
+ Rotating the token is two commands: `nazar-bridge configure --force --token <new>`
173
+ (your project list is preserved).
174
+
175
+ ---
176
+
177
+ ## Trust & supply chain
178
+
179
+ The bridge runs on your machine and runs Claude Code with full permissions, so
180
+ its trustworthiness matters. The design keeps that auditable:
181
+
182
+ - **Open source.** Every line is on GitHub:
183
+ [arm-yan/nazar](https://github.com/arm-yan/nazar) under `apps/bridge`. Read it
184
+ before installing.
185
+ - **Published from PyPI, not a private host.** `uv tool install nazar-bridge`
186
+ pulls the package and its only two runtime dependencies (`websockets`,
187
+ `pydantic`) from PyPI. Nothing is downloaded from a private or vendor server.
188
+ - **Signed provenance.** Releases are published to PyPI via GitHub Actions
189
+ **Trusted Publishing (OIDC)** with attestations — no long-lived upload token
190
+ exists, and each artifact carries signed build provenance you can verify back
191
+ to the tagged commit.
192
+
193
+ ---
194
+
195
+ ## Security model
196
+
197
+ Be deliberate about what this daemon does:
198
+
199
+ - When a prompt arrives from your authenticated Nazar dashboard, the daemon
200
+ spawns Claude Code **with `--dangerously-skip-permissions`** — Claude can read,
201
+ write, and run commands in the registered project directory without per-action
202
+ prompts. This is intentional: it's *your* machine, *your* Claude login, and
203
+ *your* token, and the point of the bridge is hands-off remote execution.
204
+ - The **trust boundary is your daemon token plus your single-user host.** Anyone
205
+ who holds the token can drive Claude on your machine through the Nazar API.
206
+ Treat the token like an SSH key: keep `config.toml` locked down, and
207
+ rotate/revoke the token (from the dashboard) if it leaks.
208
+ - The daemon only ever makes an **outbound** WebSocket connection — it opens no
209
+ listening port on your machine.
210
+
211
+ If that posture isn't acceptable for a given machine, don't install the bridge
212
+ there.
213
+
214
+ ---
215
+
216
+ ## Wire protocol
217
+
218
+ The daemon and API speak JSON text frames over the WebSocket. The source of
219
+ truth for the schemas is `apps/api/nazar_api/schemas/bridge.py`; the daemon's
220
+ `nazar_bridge/wire.py` mirrors the relevant subset so the daemon stays
221
+ installable independently of the API package.
222
+
223
+ ---
224
+
225
+ ## Develop / test
226
+
227
+ ```bash
228
+ cd apps/bridge
229
+ python -m pip install -e ".[dev]"
230
+ pytest
231
+ ruff check nazar_bridge tests
232
+ mypy nazar_bridge
233
+ ```
234
+
235
+ Build the distributables locally:
236
+
237
+ ```bash
238
+ python -m build # produces dist/*.whl and dist/*.tar.gz
239
+ twine check dist/*
240
+ ```
@@ -0,0 +1,207 @@
1
+ # nazar-bridge
2
+
3
+ `nazar-bridge` is a small, open-source daemon that lets you drive
4
+ [Claude Code](https://claude.com/claude-code) on your own machine from the
5
+ [Nazar](https://github.com/arm-yan/nazar) phone dashboard.
6
+
7
+ It holds a single long-lived **outbound** WebSocket connection to the Nazar
8
+ API, registers your local Claude-Code project directories, and — when you send
9
+ a prompt from your phone — spawns `claude -p` in the matching project and
10
+ streams the output back. Nothing listens for inbound connections on your
11
+ machine; the daemon dials out, so there are no ports to open.
12
+
13
+ The source is intentionally small and auditable — read it before you install
14
+ it. That's the whole trust model (see [Trust & supply chain](#trust--supply-chain)).
15
+
16
+ ---
17
+
18
+ ## Prerequisites
19
+
20
+ - **Python 3.12+** on your machine.
21
+ - **[Claude Code](https://claude.com/claude-code) installed and authenticated.**
22
+ The daemon shells out to the `claude` CLI using *your* logged-in session, so
23
+ `claude` must be on your `PATH` and already signed in.
24
+ - **A Nazar account on a Pro or Unlimited plan.** The bridge is a paid-tier
25
+ feature — **the Free plan has no bridge** and cannot mint daemon tokens.
26
+
27
+ ---
28
+
29
+ ## Install
30
+
31
+ Recommended (isolated tool install via [uv](https://docs.astral.sh/uv/)):
32
+
33
+ ```bash
34
+ uv tool install nazar-bridge
35
+ ```
36
+
37
+ Alternative (via [pipx](https://pipx.pypa.io/)):
38
+
39
+ ```bash
40
+ pipx install nazar-bridge
41
+ ```
42
+
43
+ Upgrade later:
44
+
45
+ ```bash
46
+ uv tool upgrade nazar-bridge # or: pipx upgrade nazar-bridge
47
+ ```
48
+
49
+ Both put a `nazar-bridge` command on your `PATH`.
50
+
51
+ ---
52
+
53
+ ## Connect
54
+
55
+ 1. **Get a daemon token.** In the Nazar dashboard, open **/code → Bridge
56
+ tokens** and create one. It looks like `nazar_bridge_xxxxxxxxxxxxxxxx`.
57
+ Copy it now — it's shown only once.
58
+
59
+ 2. **Configure the daemon** with the token (and, if your API host differs from
60
+ the default, the WebSocket URL):
61
+
62
+ ```bash
63
+ nazar-bridge configure --token nazar_bridge_xxxxxxxxxxxxxxxx
64
+ # to point at a self-hosted / dev API instead of the default:
65
+ nazar-bridge configure --token nazar_bridge_xxxx --api-url wss://your-host/api/bridge/ws
66
+ ```
67
+
68
+ 3. **Register the project directories** you want reachable from your phone:
69
+
70
+ ```bash
71
+ nazar-bridge add /path/to/your/project
72
+ nazar-bridge add /path/to/another/project
73
+ nazar-bridge list
74
+ ```
75
+
76
+ 4. **Run it.** Either start it once in a terminal:
77
+
78
+ ```bash
79
+ nazar-bridge run # add --debug for verbose logs
80
+ ```
81
+
82
+ …or install it as a login autostart service (recommended — see below) so it
83
+ reconnects automatically after a reboot.
84
+
85
+ `run --once` exits right after the first successful register — handy for
86
+ smoke-testing a freshly-configured daemon.
87
+
88
+ ---
89
+
90
+ ## Autostart at login (recommended)
91
+
92
+ Instead of leaving a terminal open, register the daemon to start at login and
93
+ restart on failure. One cross-platform command detects your OS and writes the
94
+ right unit:
95
+
96
+ ```bash
97
+ nazar-bridge service install # Windows / macOS / Linux
98
+ nazar-bridge service status # is it installed / running?
99
+ nazar-bridge service uninstall # remove it
100
+ ```
101
+
102
+ | OS | What `service install` creates |
103
+ | ------- | ------------------------------------------------------------------------- |
104
+ | Windows | A Task Scheduler task **"Nazar Bridge"** that runs at logon (windowless). |
105
+ | macOS | A launchd LaunchAgent `app.nazar.bridge` in `~/Library/LaunchAgents`. |
106
+ | Linux | A systemd `--user` unit `nazar-bridge.service` (enabled + started). |
107
+
108
+ The service always runs **as your own user** (never root/SYSTEM) because the
109
+ daemon spawns `claude` with your personal Claude Code login — `service install`
110
+ refuses to run as root. On Linux, run `loginctl enable-linger $USER` if you
111
+ want the daemon up even when you're not logged in interactively.
112
+
113
+ Logs go to the daemon's rotating log file (see below) regardless of how it's
114
+ started. For live debugging, run `nazar-bridge run` in a terminal to watch
115
+ output directly.
116
+
117
+ > **Windows note:** earlier releases shipped
118
+ > `scripts/install-windows-startup.ps1`. That script still works and adds a
119
+ > richer restart policy, but `nazar-bridge service install` is now the
120
+ > recommended, cross-platform path.
121
+
122
+ ---
123
+
124
+ ## Where config & logs live
125
+
126
+ | OS | Config file | Daemon log |
127
+ | ------- | ---------------------------------------------------- | --------------------------- |
128
+ | Windows | `%APPDATA%\nazar-bridge\config.toml` | `%APPDATA%\nazar-bridge\daemon.log` |
129
+ | macOS | `~/.config/nazar-bridge/config.toml` | `~/.config/nazar-bridge/daemon.log` |
130
+ | Linux | `$XDG_CONFIG_HOME/nazar-bridge/config.toml` or | `…/nazar-bridge/daemon.log` |
131
+ | | `~/.config/nazar-bridge/config.toml` | |
132
+
133
+ The token is stored **plaintext** in `config.toml` — it's the daemon's only
134
+ credential. Protect it with filesystem permissions:
135
+
136
+ - **Windows:** `icacls "%APPDATA%\nazar-bridge\config.toml" /inheritance:r /grant:r "%USERNAME%:F"`
137
+ - **macOS / Linux:** `chmod 600 ~/.config/nazar-bridge/config.toml`
138
+
139
+ Rotating the token is two commands: `nazar-bridge configure --force --token <new>`
140
+ (your project list is preserved).
141
+
142
+ ---
143
+
144
+ ## Trust & supply chain
145
+
146
+ The bridge runs on your machine and runs Claude Code with full permissions, so
147
+ its trustworthiness matters. The design keeps that auditable:
148
+
149
+ - **Open source.** Every line is on GitHub:
150
+ [arm-yan/nazar](https://github.com/arm-yan/nazar) under `apps/bridge`. Read it
151
+ before installing.
152
+ - **Published from PyPI, not a private host.** `uv tool install nazar-bridge`
153
+ pulls the package and its only two runtime dependencies (`websockets`,
154
+ `pydantic`) from PyPI. Nothing is downloaded from a private or vendor server.
155
+ - **Signed provenance.** Releases are published to PyPI via GitHub Actions
156
+ **Trusted Publishing (OIDC)** with attestations — no long-lived upload token
157
+ exists, and each artifact carries signed build provenance you can verify back
158
+ to the tagged commit.
159
+
160
+ ---
161
+
162
+ ## Security model
163
+
164
+ Be deliberate about what this daemon does:
165
+
166
+ - When a prompt arrives from your authenticated Nazar dashboard, the daemon
167
+ spawns Claude Code **with `--dangerously-skip-permissions`** — Claude can read,
168
+ write, and run commands in the registered project directory without per-action
169
+ prompts. This is intentional: it's *your* machine, *your* Claude login, and
170
+ *your* token, and the point of the bridge is hands-off remote execution.
171
+ - The **trust boundary is your daemon token plus your single-user host.** Anyone
172
+ who holds the token can drive Claude on your machine through the Nazar API.
173
+ Treat the token like an SSH key: keep `config.toml` locked down, and
174
+ rotate/revoke the token (from the dashboard) if it leaks.
175
+ - The daemon only ever makes an **outbound** WebSocket connection — it opens no
176
+ listening port on your machine.
177
+
178
+ If that posture isn't acceptable for a given machine, don't install the bridge
179
+ there.
180
+
181
+ ---
182
+
183
+ ## Wire protocol
184
+
185
+ The daemon and API speak JSON text frames over the WebSocket. The source of
186
+ truth for the schemas is `apps/api/nazar_api/schemas/bridge.py`; the daemon's
187
+ `nazar_bridge/wire.py` mirrors the relevant subset so the daemon stays
188
+ installable independently of the API package.
189
+
190
+ ---
191
+
192
+ ## Develop / test
193
+
194
+ ```bash
195
+ cd apps/bridge
196
+ python -m pip install -e ".[dev]"
197
+ pytest
198
+ ruff check nazar_bridge tests
199
+ mypy nazar_bridge
200
+ ```
201
+
202
+ Build the distributables locally:
203
+
204
+ ```bash
205
+ python -m build # produces dist/*.whl and dist/*.tar.gz
206
+ twine check dist/*
207
+ ```
@@ -0,0 +1,21 @@
1
+ """nazar-bridge — daemon that relays phone-prompts to local ``claude -p``.
2
+
3
+ The daemon maintains a persistent outbound WebSocket connection to the
4
+ Nazar API, registers the founder's local Claude Code project
5
+ directories, and (in a follow-up ticket #26) shells out to
6
+ ``claude -p`` to execute prompts pushed from the dashboard.
7
+
8
+ This module is intentionally tiny — every concern is split into a
9
+ dedicated submodule:
10
+
11
+ * :mod:`nazar_bridge.config` — TOML config file load/save.
12
+ * :mod:`nazar_bridge.client` — async WebSocket client + reconnect.
13
+ * :mod:`nazar_bridge.runner` — long-running ``run()`` entrypoint.
14
+ * :mod:`nazar_bridge.cli` — argparse-based console script.
15
+ * :mod:`nazar_bridge.wire` — Pydantic wire-protocol schemas.
16
+ * :mod:`nazar_bridge.exceptions` — typed errors surfaced to the CLI.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ __version__ = "0.1.0"
@@ -0,0 +1,13 @@
1
+ """Allow ``python -m nazar_bridge`` as an equivalent to the console script.
2
+
3
+ Useful when the package is installed but the ``nazar-bridge`` script
4
+ isn't on the ``PATH`` (e.g. a venv that's been activated by absolute
5
+ ``python`` path).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from nazar_bridge.cli import main
11
+
12
+ if __name__ == "__main__":
13
+ raise SystemExit(main())