iDeviceTail 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 (59) hide show
  1. idevicetail-0.1.0/LICENSE +27 -0
  2. idevicetail-0.1.0/MANIFEST.in +8 -0
  3. idevicetail-0.1.0/PKG-INFO +130 -0
  4. idevicetail-0.1.0/README.md +89 -0
  5. idevicetail-0.1.0/desktop/iDeviceTail.egg-info/PKG-INFO +130 -0
  6. idevicetail-0.1.0/desktop/iDeviceTail.egg-info/SOURCES.txt +57 -0
  7. idevicetail-0.1.0/desktop/iDeviceTail.egg-info/dependency_links.txt +1 -0
  8. idevicetail-0.1.0/desktop/iDeviceTail.egg-info/entry_points.txt +2 -0
  9. idevicetail-0.1.0/desktop/iDeviceTail.egg-info/requires.txt +13 -0
  10. idevicetail-0.1.0/desktop/iDeviceTail.egg-info/top_level.txt +1 -0
  11. idevicetail-0.1.0/desktop/idevicetail/__init__.py +15 -0
  12. idevicetail-0.1.0/desktop/idevicetail/__main__.py +4 -0
  13. idevicetail-0.1.0/desktop/idevicetail/bus.py +89 -0
  14. idevicetail-0.1.0/desktop/idevicetail/cli.py +426 -0
  15. idevicetail-0.1.0/desktop/idevicetail/config.py +72 -0
  16. idevicetail-0.1.0/desktop/idevicetail/device_names.py +94 -0
  17. idevicetail-0.1.0/desktop/idevicetail/discovery.py +209 -0
  18. idevicetail-0.1.0/desktop/idevicetail/engine_agent.py +245 -0
  19. idevicetail-0.1.0/desktop/idevicetail/engine_device.py +425 -0
  20. idevicetail-0.1.0/desktop/idevicetail/exporter.py +92 -0
  21. idevicetail-0.1.0/desktop/idevicetail/filesink.py +135 -0
  22. idevicetail-0.1.0/desktop/idevicetail/manager.py +457 -0
  23. idevicetail-0.1.0/desktop/idevicetail/models.py +150 -0
  24. idevicetail-0.1.0/desktop/idevicetail/normalize.py +365 -0
  25. idevicetail-0.1.0/desktop/idevicetail/server.py +574 -0
  26. idevicetail-0.1.0/desktop/idevicetail/store.py +236 -0
  27. idevicetail-0.1.0/desktop/idevicetail/web/app.js +341 -0
  28. idevicetail-0.1.0/desktop/idevicetail/web/index.html +111 -0
  29. idevicetail-0.1.0/desktop/idevicetail/web/styles.css +146 -0
  30. idevicetail-0.1.0/docs/ARCHITECTURE.md +110 -0
  31. idevicetail-0.1.0/docs/COMPATIBILITY.md +52 -0
  32. idevicetail-0.1.0/docs/FEASIBILITY.md +177 -0
  33. idevicetail-0.1.0/docs/GUIDE.md +453 -0
  34. idevicetail-0.1.0/docs/PROTOCOL.md +117 -0
  35. idevicetail-0.1.0/docs/SETUP-DESKTOP.md +93 -0
  36. idevicetail-0.1.0/docs/SETUP-iOS.md +101 -0
  37. idevicetail-0.1.0/docs/TESTPLAN.md +49 -0
  38. idevicetail-0.1.0/docs/TROUBLESHOOTING.md +92 -0
  39. idevicetail-0.1.0/ios/IDeviceTailAgent/Sources/AgentModel.swift +68 -0
  40. idevicetail-0.1.0/ios/IDeviceTailAgent/Sources/ContentView.swift +79 -0
  41. idevicetail-0.1.0/ios/IDeviceTailAgent/Sources/IDeviceTailAgentApp.swift +13 -0
  42. idevicetail-0.1.0/ios/IDeviceTailAgent/Sources/Info.plist +35 -0
  43. idevicetail-0.1.0/ios/IDeviceTailAgent/project.yml +33 -0
  44. idevicetail-0.1.0/ios/IDeviceTailKit/Package.swift +25 -0
  45. idevicetail-0.1.0/ios/IDeviceTailKit/Sources/IDeviceTailKit/FrameCodec.swift +42 -0
  46. idevicetail-0.1.0/ios/IDeviceTailKit/Sources/IDeviceTailKit/HostBrowser.swift +45 -0
  47. idevicetail-0.1.0/ios/IDeviceTailKit/Sources/IDeviceTailKit/LogForwarder.swift +166 -0
  48. idevicetail-0.1.0/ios/IDeviceTailKit/Sources/IDeviceTailKit/LogRecord.swift +75 -0
  49. idevicetail-0.1.0/ios/IDeviceTailKit/Sources/IDeviceTailKit/LogStreamClient.swift +212 -0
  50. idevicetail-0.1.0/ios/IDeviceTailKit/Sources/IDeviceTailKit/OSLogStoreReader.swift +91 -0
  51. idevicetail-0.1.0/ios/IDeviceTailKit/Tests/IDeviceTailKitTests/FrameCodecTests.swift +43 -0
  52. idevicetail-0.1.0/ios/IDeviceTailKit/Tests/IDeviceTailKitTests/LogRecordTests.swift +39 -0
  53. idevicetail-0.1.0/ios/README.md +46 -0
  54. idevicetail-0.1.0/pyproject.toml +69 -0
  55. idevicetail-0.1.0/scripts/provision-device.ps1 +24 -0
  56. idevicetail-0.1.0/scripts/run.ps1 +23 -0
  57. idevicetail-0.1.0/scripts/setup-desktop.ps1 +35 -0
  58. idevicetail-0.1.0/scripts/setup-desktop.sh +24 -0
  59. idevicetail-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,27 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 iDeviceTail contributors
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.
22
+
23
+ ---
24
+
25
+ NOTE: This project optionally invokes `pymobiledevice3` (https://github.com/doronz88/pymobiledevice3),
26
+ which is licensed GPL-3.0. iDeviceTail calls it as a separate process via its public CLI and does not
27
+ link or embed its code. Installing that dependency is the user's choice and subject to its own license.
@@ -0,0 +1,8 @@
1
+ include LICENSE README.md
2
+ recursive-include desktop/idevicetail/web *.html *.js *.css
3
+ recursive-include docs *.md
4
+ recursive-include ios *.swift *.plist *.yml Package.swift README.md
5
+ graft scripts
6
+ global-exclude __pycache__ *.py[cod] *.sqlite *.sqlite-* .DS_Store
7
+ prune data
8
+ prune .venv
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: iDeviceTail
3
+ Version: 0.1.0
4
+ Summary: Wireless log collection from your own iOS/iPadOS devices — system logs via pymobiledevice3 + an app-log agent, in one live web viewer. No cable.
5
+ Author: Rushabh Shah
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Rushabh5000/iDeviceTail
8
+ Project-URL: Repository, https://github.com/Rushabh5000/iDeviceTail
9
+ Project-URL: Documentation, https://github.com/Rushabh5000/iDeviceTail/tree/main/docs
10
+ Project-URL: Issues, https://github.com/Rushabh5000/iDeviceTail/issues
11
+ Keywords: ios,ipados,iphone,ipad,logs,syslog,console,oslog,os_log,logging,pymobiledevice3,wireless,developer-tools,debugging,crash-reports,sysdiagnose,bonjour
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Software Development :: Debuggers
24
+ Classifier: Topic :: System :: Logging
25
+ Classifier: Topic :: System :: Monitoring
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: aiohttp<4,>=3.9
30
+ Requires-Dist: zeroconf>=0.132
31
+ Requires-Dist: aiosqlite>=0.19
32
+ Provides-Extra: device
33
+ Requires-Dist: pymobiledevice3>=4.14; extra == "device"
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest>=8; extra == "dev"
36
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
37
+ Requires-Dist: ruff>=0.5; extra == "dev"
38
+ Requires-Dist: build>=1; extra == "dev"
39
+ Requires-Dist: twine>=5; extra == "dev"
40
+ Dynamic: license-file
41
+
42
+ # iDeviceTail — wireless iOS/iPadOS log collection
43
+
44
+ [![CI](https://github.com/Rushabh5000/iDeviceTail/actions/workflows/ci.yml/badge.svg)](https://github.com/Rushabh5000/iDeviceTail/actions/workflows/ci.yml)
45
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
46
+ [![Python 3.10–3.13](https://img.shields.io/badge/python-3.10–3.13-3776AB.svg?logo=python&logoColor=white)](pyproject.toml)
47
+
48
+ <!-- Add the PyPI badges after the first `v*` tag publishes the package:
49
+ [![PyPI](https://img.shields.io/pypi/v/idevicetail.svg)](https://pypi.org/project/idevicetail/)
50
+ [![Downloads](https://img.shields.io/pypi/dm/idevicetail.svg)](https://pypi.org/project/idevicetail/) -->
51
+
52
+
53
+ Collect and view logs from **your own** iPhones/iPads over Wi‑Fi, with **no cable during normal
54
+ operation**. One desktop app (Python, cross‑platform) fuses two capture engines into a single
55
+ live viewer:
56
+
57
+ | Engine | What it gets | Cable ever? | iOS setup | Works on |
58
+ |--------|--------------|-------------|-----------|----------|
59
+ | **A — Device engine** (`pymobiledevice3`) | Real **system logs** (all processes), crash reports, sysdiagnose | **One‑time USB pair + Trust**, then wireless | Enable Wi‑Fi sync + Developer Mode | macOS = full · Windows/Linux = full for iOS ≤ 17.3, partial (syslog only) for iOS 17.4+ over Wi‑Fi |
60
+ | **B — Agent engine** (Swift app + SDK) | The **agent app's own logs** + logs of any app that links `IDeviceTailKit` | **Never** (cable only to sideload the app once on Windows) | Install the app, tap Start | Any stock iOS, no pairing, no Developer Mode |
61
+
62
+ > **Read [`docs/FEASIBILITY.md`](docs/FEASIBILITY.md) first.** iOS does **not** give third‑party
63
+ > software the system‑log firehose. Engine A uses Apple's *supported* device‑debug channel
64
+ > (lockdown `syslog_relay` / `os_trace_relay`, the same one Console.app and `log stream` use) and
65
+ > therefore inherits Apple's pairing + Developer Mode requirements. Engine B is 100% App‑sandbox
66
+ > legal but only sees its own process. The tool ships both and merges them.
67
+
68
+ > 📖 **Full step‑by‑step setup + run guide (phone *and* desktop): [`docs/GUIDE.md`](docs/GUIDE.md).**
69
+
70
+ ## Quick start
71
+
72
+ **Windows:** double‑click **`start.bat`**. First run makes a venv, installs, launches the
73
+ server and opens the web UI. That's the only "command".
74
+
75
+ **macOS/Linux (or manual):**
76
+ ```bash
77
+ python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
78
+ pip install -e ".[device]" # from a checkout
79
+ # or: pip install "idevicetail[device]" # from PyPI
80
+ python -m idevicetail serve # opens http://localhost:3017 in your browser
81
+ ```
82
+
83
+ > **Use Python 3.10–3.13** (not 3.14 yet — `pymobiledevice3`'s C‑ext deps have no 3.14 wheels).
84
+ > The app‑log agent (Engine B) works on any 3.10+.
85
+
86
+ **Everything else is buttons in the browser** — no more commands:
87
+
88
+ | In the UI | Does |
89
+ |---|---|
90
+ | device card → **▶ Start** / **os_trace** | begin/stop a wireless system‑log stream (Engine A) |
91
+ | toolbar **Keyword filter + OK**, level/process/subsystem/source pickers | live filtering of a huge stream |
92
+ | **⬇ Export view** | save the currently filtered lines |
93
+ | **📂 Open file** | open / reveal / download the always‑on "real‑time file" (`data/sessions/realtime-*.log` + `.ndjson`) |
94
+ | **🗑 Clear** / **Pause** / **follow** | manage the view |
95
+ | device card → **Setup** | one‑time USB provisioning (Pair · Wi‑Fi sync · Developer Mode) without touching a terminal |
96
+ | device card → **Crashes** / **Sysdiag** | pull crash reports / trigger a sysdiagnose |
97
+
98
+ A CLI still exists for scripting (`idevicetail discover | stream | crash-pull | export …`) but you never need it for normal use.
99
+
100
+ ## Repository layout
101
+
102
+ ```
103
+ iDeviceTail/
104
+ ├── docs/ Feasibility report, architecture, protocol, compatibility, setup, troubleshooting, test plan
105
+ ├── desktop/
106
+ │ ├── idevicetail/ Python package: discovery, engines, normalizer, bus, store, aiohttp server, CLI
107
+ │ │ └── web/ Static log‑viewer UI (no build step)
108
+ │ └── tests/ pytest: parsing, framing, dedup, store
109
+ ├── ios/
110
+ │ ├── IDeviceTailKit/ Swift Package: OSLogStore reader, Bonjour, framed TCP client, reconnect
111
+ │ └── IDeviceTailAgent/ SwiftUI app that hosts the SDK (XcodeGen project)
112
+ ├── scripts/ setup / run / pairing helpers (PowerShell + sh)
113
+ ├── start.bat / stop.bat / hub.json project-hub integration
114
+ └── pyproject.toml
115
+ ```
116
+
117
+ ## Platform support
118
+
119
+ ```
120
+ macOS: Full (Engine A wireless incl. iOS 17.4+ firehose via remoted; Engine B; wireless app install)
121
+ Windows: Partial (Engine A: full ≤ iOS 17.3 over Wi-Fi, syslog-only for 17.4+ over Wi-Fi; Engine B full)
122
+ Linux: Partial (same as Windows)
123
+ ```
124
+
125
+ See [`docs/COMPATIBILITY.md`](docs/COMPATIBILITY.md) for the capability matrix.
126
+
127
+ ## License
128
+
129
+ MIT (this project). Engine A shells out to **pymobiledevice3** (GPL‑3.0) as a separate process;
130
+ it is an optional dependency you install yourself.
@@ -0,0 +1,89 @@
1
+ # iDeviceTail — wireless iOS/iPadOS log collection
2
+
3
+ [![CI](https://github.com/Rushabh5000/iDeviceTail/actions/workflows/ci.yml/badge.svg)](https://github.com/Rushabh5000/iDeviceTail/actions/workflows/ci.yml)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
5
+ [![Python 3.10–3.13](https://img.shields.io/badge/python-3.10–3.13-3776AB.svg?logo=python&logoColor=white)](pyproject.toml)
6
+
7
+ <!-- Add the PyPI badges after the first `v*` tag publishes the package:
8
+ [![PyPI](https://img.shields.io/pypi/v/idevicetail.svg)](https://pypi.org/project/idevicetail/)
9
+ [![Downloads](https://img.shields.io/pypi/dm/idevicetail.svg)](https://pypi.org/project/idevicetail/) -->
10
+
11
+
12
+ Collect and view logs from **your own** iPhones/iPads over Wi‑Fi, with **no cable during normal
13
+ operation**. One desktop app (Python, cross‑platform) fuses two capture engines into a single
14
+ live viewer:
15
+
16
+ | Engine | What it gets | Cable ever? | iOS setup | Works on |
17
+ |--------|--------------|-------------|-----------|----------|
18
+ | **A — Device engine** (`pymobiledevice3`) | Real **system logs** (all processes), crash reports, sysdiagnose | **One‑time USB pair + Trust**, then wireless | Enable Wi‑Fi sync + Developer Mode | macOS = full · Windows/Linux = full for iOS ≤ 17.3, partial (syslog only) for iOS 17.4+ over Wi‑Fi |
19
+ | **B — Agent engine** (Swift app + SDK) | The **agent app's own logs** + logs of any app that links `IDeviceTailKit` | **Never** (cable only to sideload the app once on Windows) | Install the app, tap Start | Any stock iOS, no pairing, no Developer Mode |
20
+
21
+ > **Read [`docs/FEASIBILITY.md`](docs/FEASIBILITY.md) first.** iOS does **not** give third‑party
22
+ > software the system‑log firehose. Engine A uses Apple's *supported* device‑debug channel
23
+ > (lockdown `syslog_relay` / `os_trace_relay`, the same one Console.app and `log stream` use) and
24
+ > therefore inherits Apple's pairing + Developer Mode requirements. Engine B is 100% App‑sandbox
25
+ > legal but only sees its own process. The tool ships both and merges them.
26
+
27
+ > 📖 **Full step‑by‑step setup + run guide (phone *and* desktop): [`docs/GUIDE.md`](docs/GUIDE.md).**
28
+
29
+ ## Quick start
30
+
31
+ **Windows:** double‑click **`start.bat`**. First run makes a venv, installs, launches the
32
+ server and opens the web UI. That's the only "command".
33
+
34
+ **macOS/Linux (or manual):**
35
+ ```bash
36
+ python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
37
+ pip install -e ".[device]" # from a checkout
38
+ # or: pip install "idevicetail[device]" # from PyPI
39
+ python -m idevicetail serve # opens http://localhost:3017 in your browser
40
+ ```
41
+
42
+ > **Use Python 3.10–3.13** (not 3.14 yet — `pymobiledevice3`'s C‑ext deps have no 3.14 wheels).
43
+ > The app‑log agent (Engine B) works on any 3.10+.
44
+
45
+ **Everything else is buttons in the browser** — no more commands:
46
+
47
+ | In the UI | Does |
48
+ |---|---|
49
+ | device card → **▶ Start** / **os_trace** | begin/stop a wireless system‑log stream (Engine A) |
50
+ | toolbar **Keyword filter + OK**, level/process/subsystem/source pickers | live filtering of a huge stream |
51
+ | **⬇ Export view** | save the currently filtered lines |
52
+ | **📂 Open file** | open / reveal / download the always‑on "real‑time file" (`data/sessions/realtime-*.log` + `.ndjson`) |
53
+ | **🗑 Clear** / **Pause** / **follow** | manage the view |
54
+ | device card → **Setup** | one‑time USB provisioning (Pair · Wi‑Fi sync · Developer Mode) without touching a terminal |
55
+ | device card → **Crashes** / **Sysdiag** | pull crash reports / trigger a sysdiagnose |
56
+
57
+ A CLI still exists for scripting (`idevicetail discover | stream | crash-pull | export …`) but you never need it for normal use.
58
+
59
+ ## Repository layout
60
+
61
+ ```
62
+ iDeviceTail/
63
+ ├── docs/ Feasibility report, architecture, protocol, compatibility, setup, troubleshooting, test plan
64
+ ├── desktop/
65
+ │ ├── idevicetail/ Python package: discovery, engines, normalizer, bus, store, aiohttp server, CLI
66
+ │ │ └── web/ Static log‑viewer UI (no build step)
67
+ │ └── tests/ pytest: parsing, framing, dedup, store
68
+ ├── ios/
69
+ │ ├── IDeviceTailKit/ Swift Package: OSLogStore reader, Bonjour, framed TCP client, reconnect
70
+ │ └── IDeviceTailAgent/ SwiftUI app that hosts the SDK (XcodeGen project)
71
+ ├── scripts/ setup / run / pairing helpers (PowerShell + sh)
72
+ ├── start.bat / stop.bat / hub.json project-hub integration
73
+ └── pyproject.toml
74
+ ```
75
+
76
+ ## Platform support
77
+
78
+ ```
79
+ macOS: Full (Engine A wireless incl. iOS 17.4+ firehose via remoted; Engine B; wireless app install)
80
+ Windows: Partial (Engine A: full ≤ iOS 17.3 over Wi-Fi, syslog-only for 17.4+ over Wi-Fi; Engine B full)
81
+ Linux: Partial (same as Windows)
82
+ ```
83
+
84
+ See [`docs/COMPATIBILITY.md`](docs/COMPATIBILITY.md) for the capability matrix.
85
+
86
+ ## License
87
+
88
+ MIT (this project). Engine A shells out to **pymobiledevice3** (GPL‑3.0) as a separate process;
89
+ it is an optional dependency you install yourself.
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: iDeviceTail
3
+ Version: 0.1.0
4
+ Summary: Wireless log collection from your own iOS/iPadOS devices — system logs via pymobiledevice3 + an app-log agent, in one live web viewer. No cable.
5
+ Author: Rushabh Shah
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Rushabh5000/iDeviceTail
8
+ Project-URL: Repository, https://github.com/Rushabh5000/iDeviceTail
9
+ Project-URL: Documentation, https://github.com/Rushabh5000/iDeviceTail/tree/main/docs
10
+ Project-URL: Issues, https://github.com/Rushabh5000/iDeviceTail/issues
11
+ Keywords: ios,ipados,iphone,ipad,logs,syslog,console,oslog,os_log,logging,pymobiledevice3,wireless,developer-tools,debugging,crash-reports,sysdiagnose,bonjour
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Software Development :: Debuggers
24
+ Classifier: Topic :: System :: Logging
25
+ Classifier: Topic :: System :: Monitoring
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: aiohttp<4,>=3.9
30
+ Requires-Dist: zeroconf>=0.132
31
+ Requires-Dist: aiosqlite>=0.19
32
+ Provides-Extra: device
33
+ Requires-Dist: pymobiledevice3>=4.14; extra == "device"
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest>=8; extra == "dev"
36
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
37
+ Requires-Dist: ruff>=0.5; extra == "dev"
38
+ Requires-Dist: build>=1; extra == "dev"
39
+ Requires-Dist: twine>=5; extra == "dev"
40
+ Dynamic: license-file
41
+
42
+ # iDeviceTail — wireless iOS/iPadOS log collection
43
+
44
+ [![CI](https://github.com/Rushabh5000/iDeviceTail/actions/workflows/ci.yml/badge.svg)](https://github.com/Rushabh5000/iDeviceTail/actions/workflows/ci.yml)
45
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
46
+ [![Python 3.10–3.13](https://img.shields.io/badge/python-3.10–3.13-3776AB.svg?logo=python&logoColor=white)](pyproject.toml)
47
+
48
+ <!-- Add the PyPI badges after the first `v*` tag publishes the package:
49
+ [![PyPI](https://img.shields.io/pypi/v/idevicetail.svg)](https://pypi.org/project/idevicetail/)
50
+ [![Downloads](https://img.shields.io/pypi/dm/idevicetail.svg)](https://pypi.org/project/idevicetail/) -->
51
+
52
+
53
+ Collect and view logs from **your own** iPhones/iPads over Wi‑Fi, with **no cable during normal
54
+ operation**. One desktop app (Python, cross‑platform) fuses two capture engines into a single
55
+ live viewer:
56
+
57
+ | Engine | What it gets | Cable ever? | iOS setup | Works on |
58
+ |--------|--------------|-------------|-----------|----------|
59
+ | **A — Device engine** (`pymobiledevice3`) | Real **system logs** (all processes), crash reports, sysdiagnose | **One‑time USB pair + Trust**, then wireless | Enable Wi‑Fi sync + Developer Mode | macOS = full · Windows/Linux = full for iOS ≤ 17.3, partial (syslog only) for iOS 17.4+ over Wi‑Fi |
60
+ | **B — Agent engine** (Swift app + SDK) | The **agent app's own logs** + logs of any app that links `IDeviceTailKit` | **Never** (cable only to sideload the app once on Windows) | Install the app, tap Start | Any stock iOS, no pairing, no Developer Mode |
61
+
62
+ > **Read [`docs/FEASIBILITY.md`](docs/FEASIBILITY.md) first.** iOS does **not** give third‑party
63
+ > software the system‑log firehose. Engine A uses Apple's *supported* device‑debug channel
64
+ > (lockdown `syslog_relay` / `os_trace_relay`, the same one Console.app and `log stream` use) and
65
+ > therefore inherits Apple's pairing + Developer Mode requirements. Engine B is 100% App‑sandbox
66
+ > legal but only sees its own process. The tool ships both and merges them.
67
+
68
+ > 📖 **Full step‑by‑step setup + run guide (phone *and* desktop): [`docs/GUIDE.md`](docs/GUIDE.md).**
69
+
70
+ ## Quick start
71
+
72
+ **Windows:** double‑click **`start.bat`**. First run makes a venv, installs, launches the
73
+ server and opens the web UI. That's the only "command".
74
+
75
+ **macOS/Linux (or manual):**
76
+ ```bash
77
+ python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
78
+ pip install -e ".[device]" # from a checkout
79
+ # or: pip install "idevicetail[device]" # from PyPI
80
+ python -m idevicetail serve # opens http://localhost:3017 in your browser
81
+ ```
82
+
83
+ > **Use Python 3.10–3.13** (not 3.14 yet — `pymobiledevice3`'s C‑ext deps have no 3.14 wheels).
84
+ > The app‑log agent (Engine B) works on any 3.10+.
85
+
86
+ **Everything else is buttons in the browser** — no more commands:
87
+
88
+ | In the UI | Does |
89
+ |---|---|
90
+ | device card → **▶ Start** / **os_trace** | begin/stop a wireless system‑log stream (Engine A) |
91
+ | toolbar **Keyword filter + OK**, level/process/subsystem/source pickers | live filtering of a huge stream |
92
+ | **⬇ Export view** | save the currently filtered lines |
93
+ | **📂 Open file** | open / reveal / download the always‑on "real‑time file" (`data/sessions/realtime-*.log` + `.ndjson`) |
94
+ | **🗑 Clear** / **Pause** / **follow** | manage the view |
95
+ | device card → **Setup** | one‑time USB provisioning (Pair · Wi‑Fi sync · Developer Mode) without touching a terminal |
96
+ | device card → **Crashes** / **Sysdiag** | pull crash reports / trigger a sysdiagnose |
97
+
98
+ A CLI still exists for scripting (`idevicetail discover | stream | crash-pull | export …`) but you never need it for normal use.
99
+
100
+ ## Repository layout
101
+
102
+ ```
103
+ iDeviceTail/
104
+ ├── docs/ Feasibility report, architecture, protocol, compatibility, setup, troubleshooting, test plan
105
+ ├── desktop/
106
+ │ ├── idevicetail/ Python package: discovery, engines, normalizer, bus, store, aiohttp server, CLI
107
+ │ │ └── web/ Static log‑viewer UI (no build step)
108
+ │ └── tests/ pytest: parsing, framing, dedup, store
109
+ ├── ios/
110
+ │ ├── IDeviceTailKit/ Swift Package: OSLogStore reader, Bonjour, framed TCP client, reconnect
111
+ │ └── IDeviceTailAgent/ SwiftUI app that hosts the SDK (XcodeGen project)
112
+ ├── scripts/ setup / run / pairing helpers (PowerShell + sh)
113
+ ├── start.bat / stop.bat / hub.json project-hub integration
114
+ └── pyproject.toml
115
+ ```
116
+
117
+ ## Platform support
118
+
119
+ ```
120
+ macOS: Full (Engine A wireless incl. iOS 17.4+ firehose via remoted; Engine B; wireless app install)
121
+ Windows: Partial (Engine A: full ≤ iOS 17.3 over Wi-Fi, syslog-only for 17.4+ over Wi-Fi; Engine B full)
122
+ Linux: Partial (same as Windows)
123
+ ```
124
+
125
+ See [`docs/COMPATIBILITY.md`](docs/COMPATIBILITY.md) for the capability matrix.
126
+
127
+ ## License
128
+
129
+ MIT (this project). Engine A shells out to **pymobiledevice3** (GPL‑3.0) as a separate process;
130
+ it is an optional dependency you install yourself.
@@ -0,0 +1,57 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ desktop/iDeviceTail.egg-info/PKG-INFO
6
+ desktop/iDeviceTail.egg-info/SOURCES.txt
7
+ desktop/iDeviceTail.egg-info/dependency_links.txt
8
+ desktop/iDeviceTail.egg-info/entry_points.txt
9
+ desktop/iDeviceTail.egg-info/requires.txt
10
+ desktop/iDeviceTail.egg-info/top_level.txt
11
+ desktop/idevicetail/__init__.py
12
+ desktop/idevicetail/__main__.py
13
+ desktop/idevicetail/bus.py
14
+ desktop/idevicetail/cli.py
15
+ desktop/idevicetail/config.py
16
+ desktop/idevicetail/device_names.py
17
+ desktop/idevicetail/discovery.py
18
+ desktop/idevicetail/engine_agent.py
19
+ desktop/idevicetail/engine_device.py
20
+ desktop/idevicetail/exporter.py
21
+ desktop/idevicetail/filesink.py
22
+ desktop/idevicetail/manager.py
23
+ desktop/idevicetail/models.py
24
+ desktop/idevicetail/normalize.py
25
+ desktop/idevicetail/server.py
26
+ desktop/idevicetail/store.py
27
+ desktop/idevicetail/web/app.js
28
+ desktop/idevicetail/web/index.html
29
+ desktop/idevicetail/web/styles.css
30
+ docs/ARCHITECTURE.md
31
+ docs/COMPATIBILITY.md
32
+ docs/FEASIBILITY.md
33
+ docs/GUIDE.md
34
+ docs/PROTOCOL.md
35
+ docs/SETUP-DESKTOP.md
36
+ docs/SETUP-iOS.md
37
+ docs/TESTPLAN.md
38
+ docs/TROUBLESHOOTING.md
39
+ ios/README.md
40
+ ios/IDeviceTailAgent/project.yml
41
+ ios/IDeviceTailAgent/Sources/AgentModel.swift
42
+ ios/IDeviceTailAgent/Sources/ContentView.swift
43
+ ios/IDeviceTailAgent/Sources/IDeviceTailAgentApp.swift
44
+ ios/IDeviceTailAgent/Sources/Info.plist
45
+ ios/IDeviceTailKit/Package.swift
46
+ ios/IDeviceTailKit/Sources/IDeviceTailKit/FrameCodec.swift
47
+ ios/IDeviceTailKit/Sources/IDeviceTailKit/HostBrowser.swift
48
+ ios/IDeviceTailKit/Sources/IDeviceTailKit/LogForwarder.swift
49
+ ios/IDeviceTailKit/Sources/IDeviceTailKit/LogRecord.swift
50
+ ios/IDeviceTailKit/Sources/IDeviceTailKit/LogStreamClient.swift
51
+ ios/IDeviceTailKit/Sources/IDeviceTailKit/OSLogStoreReader.swift
52
+ ios/IDeviceTailKit/Tests/IDeviceTailKitTests/FrameCodecTests.swift
53
+ ios/IDeviceTailKit/Tests/IDeviceTailKitTests/LogRecordTests.swift
54
+ scripts/provision-device.ps1
55
+ scripts/run.ps1
56
+ scripts/setup-desktop.ps1
57
+ scripts/setup-desktop.sh
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ idevicetail = idevicetail.cli:main
@@ -0,0 +1,13 @@
1
+ aiohttp<4,>=3.9
2
+ zeroconf>=0.132
3
+ aiosqlite>=0.19
4
+
5
+ [dev]
6
+ pytest>=8
7
+ pytest-asyncio>=0.23
8
+ ruff>=0.5
9
+ build>=1
10
+ twine>=5
11
+
12
+ [device]
13
+ pymobiledevice3>=4.14
@@ -0,0 +1 @@
1
+ idevicetail
@@ -0,0 +1,15 @@
1
+ """iDeviceTail — wireless iOS/iPadOS log collection.
2
+
3
+ Two capture engines feed one normalized log bus:
4
+
5
+ * ``engine_device`` — real system logs / crash reports / sysdiagnose via the
6
+ ``pymobiledevice3`` CLI over Wi-Fi (requires a one-time USB pairing + Trust and,
7
+ on iOS 16+, Developer Mode).
8
+ * ``engine_agent`` — app-level logs streamed by the bundled Swift agent app
9
+ (``IDeviceTailKit``) over a framed TCP protocol. No pairing, no cable, no
10
+ Developer Mode; limited to the agent's own process by the iOS sandbox.
11
+
12
+ See ``docs/FEASIBILITY.md`` for exactly what iOS does and does not allow.
13
+ """
14
+
15
+ __version__ = "0.1.0"
@@ -0,0 +1,4 @@
1
+ from idevicetail.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())
@@ -0,0 +1,89 @@
1
+ """In-process log fan-out.
2
+
3
+ Every :class:`~idevicetail.models.LogRecord` from either engine is published here.
4
+ Consumers (the WebSocket server, the SQLite writer, exporters) each ``subscribe``
5
+ and get an independent asyncio queue.
6
+
7
+ Backpressure policy: each subscriber queue is bounded. If a consumer falls
8
+ behind, the *oldest* item in that consumer's queue is dropped to make room for
9
+ the newest — a slow browser tab can never stall the capture pipeline. Dropped
10
+ counts are tracked so the UI can show "N lines dropped".
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import asyncio
16
+ from collections import deque
17
+ from typing import Any
18
+
19
+ from .models import LogRecord
20
+
21
+
22
+ class Subscription:
23
+ __slots__ = ("queue", "dropped", "_bus")
24
+
25
+ def __init__(self, bus: "LogBus", maxsize: int) -> None:
26
+ self.queue: asyncio.Queue[dict[str, Any]] = asyncio.Queue(maxsize=maxsize)
27
+ self.dropped = 0
28
+ self._bus = bus
29
+
30
+ async def get(self) -> dict[str, Any]:
31
+ return await self.queue.get()
32
+
33
+ def close(self) -> None:
34
+ self._bus._subs.discard(self)
35
+
36
+
37
+ class LogBus:
38
+ def __init__(self, ring_size: int = 200_000) -> None:
39
+ self._subs: set[Subscription] = set()
40
+ self._ring: deque[dict[str, Any]] = deque(maxlen=ring_size)
41
+ self._seq = 0
42
+ self.total_published = 0
43
+
44
+ # -- producers ---------------------------------------------------------
45
+ def publish(self, rec: LogRecord) -> None:
46
+ self._seq += 1
47
+ rec.seq = self._seq
48
+ wire = rec.to_wire()
49
+ self._ring.append(wire)
50
+ self.total_published += 1
51
+ for sub in list(self._subs):
52
+ _offer(sub, wire)
53
+
54
+ def publish_many(self, recs: list[LogRecord]) -> None:
55
+ for r in recs:
56
+ self.publish(r)
57
+
58
+ # -- consumers -------------------------------------------------------
59
+ def subscribe(self, maxsize: int = 20_000) -> Subscription:
60
+ sub = Subscription(self, maxsize)
61
+ self._subs.add(sub)
62
+ return sub
63
+
64
+ def snapshot(self, limit: int | None = None) -> list[dict[str, Any]]:
65
+ if limit is None or limit >= len(self._ring):
66
+ return list(self._ring)
67
+ return list(self._ring)[-limit:]
68
+
69
+ @property
70
+ def seq(self) -> int:
71
+ return self._seq
72
+
73
+
74
+ def _offer(sub: Subscription, wire: dict[str, Any]) -> None:
75
+ try:
76
+ sub.queue.put_nowait(wire)
77
+ return
78
+ except asyncio.QueueFull:
79
+ pass
80
+ # Drop oldest, retry once.
81
+ try:
82
+ sub.queue.get_nowait()
83
+ sub.dropped += 1
84
+ except asyncio.QueueEmpty: # pragma: no cover - race
85
+ pass
86
+ try:
87
+ sub.queue.put_nowait(wire)
88
+ except asyncio.QueueFull: # pragma: no cover - consumer is fully wedged
89
+ sub.dropped += 1