ptn 0.1.4__py3-none-any.whl

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 (73) hide show
  1. porterminal/__init__.py +288 -0
  2. porterminal/__main__.py +8 -0
  3. porterminal/app.py +381 -0
  4. porterminal/application/__init__.py +1 -0
  5. porterminal/application/ports/__init__.py +7 -0
  6. porterminal/application/ports/connection_port.py +34 -0
  7. porterminal/application/services/__init__.py +13 -0
  8. porterminal/application/services/management_service.py +279 -0
  9. porterminal/application/services/session_service.py +249 -0
  10. porterminal/application/services/tab_service.py +286 -0
  11. porterminal/application/services/terminal_service.py +426 -0
  12. porterminal/asgi.py +38 -0
  13. porterminal/cli/__init__.py +19 -0
  14. porterminal/cli/args.py +91 -0
  15. porterminal/cli/display.py +157 -0
  16. porterminal/composition.py +208 -0
  17. porterminal/config.py +195 -0
  18. porterminal/container.py +65 -0
  19. porterminal/domain/__init__.py +91 -0
  20. porterminal/domain/entities/__init__.py +16 -0
  21. porterminal/domain/entities/output_buffer.py +73 -0
  22. porterminal/domain/entities/session.py +86 -0
  23. porterminal/domain/entities/tab.py +71 -0
  24. porterminal/domain/ports/__init__.py +12 -0
  25. porterminal/domain/ports/pty_port.py +80 -0
  26. porterminal/domain/ports/session_repository.py +58 -0
  27. porterminal/domain/ports/tab_repository.py +75 -0
  28. porterminal/domain/services/__init__.py +18 -0
  29. porterminal/domain/services/environment_sanitizer.py +61 -0
  30. porterminal/domain/services/rate_limiter.py +63 -0
  31. porterminal/domain/services/session_limits.py +104 -0
  32. porterminal/domain/services/tab_limits.py +54 -0
  33. porterminal/domain/values/__init__.py +25 -0
  34. porterminal/domain/values/environment_rules.py +156 -0
  35. porterminal/domain/values/rate_limit_config.py +21 -0
  36. porterminal/domain/values/session_id.py +20 -0
  37. porterminal/domain/values/shell_command.py +37 -0
  38. porterminal/domain/values/tab_id.py +24 -0
  39. porterminal/domain/values/terminal_dimensions.py +45 -0
  40. porterminal/domain/values/user_id.py +25 -0
  41. porterminal/infrastructure/__init__.py +20 -0
  42. porterminal/infrastructure/cloudflared.py +295 -0
  43. porterminal/infrastructure/config/__init__.py +9 -0
  44. porterminal/infrastructure/config/shell_detector.py +84 -0
  45. porterminal/infrastructure/config/yaml_loader.py +34 -0
  46. porterminal/infrastructure/network.py +43 -0
  47. porterminal/infrastructure/registry/__init__.py +5 -0
  48. porterminal/infrastructure/registry/user_connection_registry.py +104 -0
  49. porterminal/infrastructure/repositories/__init__.py +9 -0
  50. porterminal/infrastructure/repositories/in_memory_session.py +70 -0
  51. porterminal/infrastructure/repositories/in_memory_tab.py +124 -0
  52. porterminal/infrastructure/server.py +161 -0
  53. porterminal/infrastructure/web/__init__.py +7 -0
  54. porterminal/infrastructure/web/websocket_adapter.py +78 -0
  55. porterminal/logging_setup.py +48 -0
  56. porterminal/pty/__init__.py +46 -0
  57. porterminal/pty/env.py +97 -0
  58. porterminal/pty/manager.py +163 -0
  59. porterminal/pty/protocol.py +84 -0
  60. porterminal/pty/unix.py +162 -0
  61. porterminal/pty/windows.py +131 -0
  62. porterminal/static/assets/app-BQiuUo6Q.css +32 -0
  63. porterminal/static/assets/app-YNN_jEhv.js +71 -0
  64. porterminal/static/icon.svg +34 -0
  65. porterminal/static/index.html +139 -0
  66. porterminal/static/manifest.json +31 -0
  67. porterminal/static/sw.js +66 -0
  68. porterminal/updater.py +257 -0
  69. ptn-0.1.4.dist-info/METADATA +191 -0
  70. ptn-0.1.4.dist-info/RECORD +73 -0
  71. ptn-0.1.4.dist-info/WHEEL +4 -0
  72. ptn-0.1.4.dist-info/entry_points.txt +2 -0
  73. ptn-0.1.4.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.4
2
+ Name: ptn
3
+ Version: 0.1.4
4
+ Summary: Web-based terminal accessible from phone via Cloudflare Tunnel
5
+ Project-URL: Homepage, https://github.com/lyehe/porterminal
6
+ Project-URL: Repository, https://github.com/lyehe/porterminal
7
+ Project-URL: Documentation, https://github.com/lyehe/porterminal/tree/main/docs
8
+ Project-URL: Issues, https://github.com/lyehe/porterminal/issues
9
+ Author: Porterminal Contributors
10
+ Maintainer: Porterminal Contributors
11
+ License: AGPL-3.0-or-later
12
+ License-File: LICENSE
13
+ Keywords: cloudflare,mobile,pty,terminal,tunnel,web,websocket,xterm
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Web Environment
16
+ Classifier: Framework :: FastAPI
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Intended Audience :: System Administrators
19
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
20
+ Classifier: Operating System :: MacOS
21
+ Classifier: Operating System :: Microsoft :: Windows
22
+ Classifier: Operating System :: POSIX :: Linux
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: Internet :: WWW/HTTP
26
+ Classifier: Topic :: System :: Shells
27
+ Classifier: Topic :: Terminals :: Terminal Emulators/X Terminals
28
+ Requires-Python: >=3.12
29
+ Requires-Dist: fastapi>=0.104.0
30
+ Requires-Dist: pydantic>=2.0
31
+ Requires-Dist: pywinpty>=2.0.0; sys_platform == 'win32'
32
+ Requires-Dist: pyyaml>=6.0
33
+ Requires-Dist: qrcode>=7.4
34
+ Requires-Dist: rich>=13.0
35
+ Requires-Dist: uvicorn[standard]>=0.24.0
36
+ Provides-Extra: dev
37
+ Requires-Dist: watchfiles>=0.21.0; extra == 'dev'
38
+ Description-Content-Type: text/markdown
39
+
40
+ <p align="center">
41
+ <a href="https://github.com/lyehe/porterminal">
42
+ <img src="assets/banner.jpg" alt="Porterminal - Vibe Code From Anywhere" width="600">
43
+ </a>
44
+ </p>
45
+
46
+ <p align="center">
47
+ <a href="https://pypi.org/project/ptn/">
48
+ <img src="https://img.shields.io/pypi/v/ptn?style=flat-square&logo=pypi&logoColor=white&label=PyPI" alt="PyPI">
49
+ </a>
50
+ <a href="https://pypi.org/project/ptn/">
51
+ <img src="https://img.shields.io/pypi/pyversions/ptn?style=flat-square&logo=python&logoColor=white" alt="Python">
52
+ </a>
53
+ <a href="https://pypi.org/project/ptn/">
54
+ <img src="https://img.shields.io/pypi/dm/ptn?style=flat-square&label=Downloads" alt="Downloads">
55
+ </a>
56
+ <a href="https://github.com/lyehe/porterminal/blob/main/LICENSE">
57
+ <img src="https://img.shields.io/github/license/lyehe/porterminal?style=flat-square" alt="License">
58
+ </a>
59
+ </p>
60
+
61
+ Simple, quick and dirty web terminal accessible from your phone via Cloudflare Quick Tunnel. Vibe-coding-friendly interface with virtual keys, multi-tab sessions, etc.
62
+
63
+ ## Features
64
+
65
+ - **Touch-optimized** - Virtual keyboard, touch gestures
66
+ - **Multi-tab sessions** - Run multiple terminals simultaneously with persistent sessions
67
+ - **Instant access** - Cloudflare Quick Tunnel with QR code, no port forwarding needed
68
+ - **Cross-platform** - Windows (PowerShell, CMD, WSL), Linux/macOS (Bash, Zsh, Fish)
69
+
70
+ ## Quick Start
71
+
72
+ ```bash
73
+ # Run without installing
74
+ uvx ptn
75
+
76
+
77
+ # Or install
78
+ uv tool install ptn
79
+ ptn
80
+ ```
81
+
82
+ Scan the QR code with your phone to connect.
83
+
84
+
85
+ ## Usage
86
+
87
+ ```
88
+ ptn [path] [options]
89
+ ```
90
+
91
+ **Examples:**
92
+
93
+ ```bash
94
+ # Start in current directory with tunnel
95
+ ptn
96
+
97
+ # Start in a specific project folder
98
+ ptn ~/projects/myapp
99
+
100
+ # Local network only (no Cloudflare tunnel)
101
+ ptn --no-tunnel
102
+
103
+ # Run in background (returns immediately)
104
+ ptn -b
105
+
106
+ # Show detailed startup logs
107
+ ptn -v
108
+
109
+ # Update to latest version
110
+ ptn -U
111
+
112
+ # Check for updates without installing
113
+ ptn --check-update
114
+ ```
115
+
116
+ **Options:**
117
+
118
+ | Option | Description |
119
+ |--------|-------------|
120
+ | `path` | Starting directory for the shell (default: current) |
121
+ | `--no-tunnel` | Local network only, no Cloudflare tunnel |
122
+ | `-b, --background` | Run in background and return immediately |
123
+ | `-v, --verbose` | Show detailed startup logs |
124
+ | `-U, --update` | Update to the latest version |
125
+ | `--check-update` | Check if a newer version is available |
126
+ | `-V, --version` | Show version |
127
+ | `-h, --help` | Show help message |
128
+
129
+ ## Configuration
130
+
131
+ Create `config.yaml` in your working directory to customize:
132
+
133
+ ```yaml
134
+ # Server settings
135
+ server:
136
+ host: "127.0.0.1"
137
+ port: 8000
138
+
139
+ # Terminal settings
140
+ terminal:
141
+ cols: 120 # Default columns (40-500)
142
+ rows: 30 # Default rows (10-200)
143
+ default_shell: powershell # Default shell ID
144
+
145
+ # Custom shells (optional - auto-detected if not specified)
146
+ shells:
147
+ - id: powershell
148
+ name: PowerShell
149
+ command: powershell.exe
150
+ args: ["-NoLogo"]
151
+ - id: wsl
152
+ name: WSL
153
+ command: wsl.exe
154
+ args: []
155
+
156
+ # Custom quick-action buttons
157
+ buttons:
158
+ - label: "git"
159
+ send: "git status\r"
160
+ - label: "ls"
161
+ send: "ls -la\r"
162
+ - label: "clear"
163
+ send: "clear\r"
164
+ - label: "exit"
165
+ send: "exit\r"
166
+ ```
167
+
168
+ **Minimal config example:**
169
+
170
+ ```yaml
171
+ terminal:
172
+ default_shell: bash
173
+ ```
174
+
175
+ ## Security
176
+
177
+ > **Warning:** The URL is the only authentication. Anyone with the link can access your terminal.
178
+
179
+ - Environment variables sanitized (API keys, tokens, secrets blocked)
180
+ - Rate limiting on input
181
+ - Sessions isolated per user via Cloudflare Access
182
+
183
+ ## Requirements
184
+
185
+ - Python 3.12+
186
+ - [uv](https://docs.astral.sh/uv/) is prefered
187
+ - [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) (auto-installed if missing)
188
+
189
+ ## License
190
+
191
+ [AGPL-3.0](LICENSE)
@@ -0,0 +1,73 @@
1
+ porterminal/__init__.py,sha256=V8uAGMquwSE-cDVDLRiwyQ1rp9VK8PFApDAUY8TWezg,10050
2
+ porterminal/__main__.py,sha256=XLo21rqmISrIZFiaHC58Trgq8E0gxH4Wb3driD4JA7c,137
3
+ porterminal/app.py,sha256=C6j2DG0ZrzqDu7DjfLmamjmMMHvhp2M7_28JyKDcc-Q,13852
4
+ porterminal/asgi.py,sha256=gXGCq2U4C5wJvjLa1sU946GIGfCsnex5mT3J_-u6YiY,1151
5
+ porterminal/composition.py,sha256=jHZQiL51rOXLptmP_luR2cYMirAZG3DQ1vF6thVDFLc,6429
6
+ porterminal/config.py,sha256=0kPTRjFrf_--w1riefJKPPuo1JcK83T-M1zcWS_8304,5759
7
+ porterminal/container.py,sha256=bZ4lR6hvERMoGZvQ2y5VEE4kIiVhhcfBHzzc-xZ_xeg,1865
8
+ porterminal/logging_setup.py,sha256=DhoN_FdJFbRawcsYy8mLRU32TCT1ZfZ2G4Q_AOKwZuA,1513
9
+ porterminal/updater.py,sha256=737adYtUZKyh1czjQn8VuOaa1DO--oH4uebt2shFfqs,7175
10
+ porterminal/application/__init__.py,sha256=Q5gQia_11ubfMcDbzjvI6RoUU2jFJkuQrsbSuIfQCRA,55
11
+ porterminal/application/ports/__init__.py,sha256=zKcSDFmPPOIP0Oxuf8O5AEMmURV7AaSVA2D8iahwU6c,149
12
+ porterminal/application/ports/connection_port.py,sha256=kXIl-fzx3SbpU8kV1rpmgNeI22XSJMbzXGt1YcwZO8Y,926
13
+ porterminal/application/services/__init__.py,sha256=YO-iPdE_-EEV9tVnu0NcB5bwSCCSVy9CWOGBFCJyoRc,335
14
+ porterminal/application/services/management_service.py,sha256=WllcHDCQuPzAKkEEyhV8afDWJ2aUw8rsBsFhbZ3DWPU,8661
15
+ porterminal/application/services/session_service.py,sha256=f1Mk-a9ug895jSsskOKY1uW3N5IcMTEutpM_d0RAmaM,8234
16
+ porterminal/application/services/tab_service.py,sha256=0_S978dYhBW2-eaZN2wOlcZOY4V4iPt2MMNOyoZQxPs,8307
17
+ porterminal/application/services/terminal_service.py,sha256=4UUlZKHGaCoI37759V0xs30ydZPemsFm9MIehiIkFX4,15670
18
+ porterminal/cli/__init__.py,sha256=A3y-QgKrT-vdAYV-xsZjeyMkiPymZaZzYUGQ-_3cXmQ,305
19
+ porterminal/cli/args.py,sha256=cWgs6GMmlNw9_vOpk1bIqt968sriXpgGvQM7s8Ti7ZA,2548
20
+ porterminal/cli/display.py,sha256=wErWVPz3PmCvX5vxxaCdPb4YSeByrEj1dj0BSSmrZE0,5530
21
+ porterminal/domain/__init__.py,sha256=A_EgLaAzPwETbnGx6ZeiyjVwP4EBWAweofo464PGhHI,1680
22
+ porterminal/domain/entities/__init__.py,sha256=dIQp6T0M-Bl_DJpSOGQGBD29Rl_FDR0XfVrDL08ck50,463
23
+ porterminal/domain/entities/output_buffer.py,sha256=3-tCGOUvU3U9QfOmPu9703VlyJu3bZKYbEzSPYTqwWE,2246
24
+ porterminal/domain/entities/session.py,sha256=SzAEqbqr49QhcSW_2BqYVJst1_6yo8qs21Efh_uBJDA,2680
25
+ porterminal/domain/entities/tab.py,sha256=OQPS_CtTx5MD8bjH23NQw0Z4RbXh8Mqew3P0_KYHYl4,2124
26
+ porterminal/domain/ports/__init__.py,sha256=YoiaopwjGvKqhekp19zwZ7960WNPZ-jQ9TNUw0wgMGw,294
27
+ porterminal/domain/ports/pty_port.py,sha256=mOlYB5bgMW1br6QcGJHkrmPSOCRds8o76x7bKaQrvto,1925
28
+ porterminal/domain/ports/session_repository.py,sha256=Gh5c2cneboXYEuNw8Gxw06IZwpMqhN0HA7KINFFi2LQ,1611
29
+ porterminal/domain/ports/tab_repository.py,sha256=OVLi4jhsBxWNiRKhX849bbv_OWhBGuBHK79Qk9bUlR8,1948
30
+ porterminal/domain/services/__init__.py,sha256=YiEokgIXvSbfieNlBfdWSPJlbBYDFrzIYc5aVpkjSeI,561
31
+ porterminal/domain/services/environment_sanitizer.py,sha256=RslZDn8jso8bX1hG9p9NQyv1ey19u1F5xATPlq6pKVw,2014
32
+ porterminal/domain/services/rate_limiter.py,sha256=I0cybe1PX7uYWlr7l92N3jM89yFQDRKqD5p9-lT8Mas,1724
33
+ porterminal/domain/services/session_limits.py,sha256=EqW_tqr0Br3a2gzgl5Dg80dx1umcU6VMr4-ELRtGx_w,3181
34
+ porterminal/domain/services/tab_limits.py,sha256=nokX8gP9_41MNIdQ7Fri2JLAs4_Ch-fy3CgpKHTZnT8,1434
35
+ porterminal/domain/values/__init__.py,sha256=_hVr6uiuKOMvlsE1j41b8NxSoOBuK9CkLK2d9mjsFzg,682
36
+ porterminal/domain/values/environment_rules.py,sha256=ewBv6Z_iXbWOFNcYmvczgKL6Kb_zzlGH1mh46n2_5jU,3888
37
+ porterminal/domain/values/rate_limit_config.py,sha256=BZb-Jbxav8kJ6ijADIrW_-JhDt8WuPIe8OIqLnQykXA,548
38
+ porterminal/domain/values/session_id.py,sha256=dYBSZdG6WWjp06mUbTZwjufb30A6lSuK-NKwqxAAavY,461
39
+ porterminal/domain/values/shell_command.py,sha256=9U723nsdDCsW_M17qBp__cu3r9uuBVuur0kifaoiEF0,1102
40
+ porterminal/domain/values/tab_id.py,sha256=zKZZ1lBQUmXZ3PQlH0jejUQ_AA_SVTW-Z7jCI7Tq37A,557
41
+ porterminal/domain/values/terminal_dimensions.py,sha256=mWtMQi40EDtwnKpQadTR5eD0VmInO-2kgbUUw2VVCZY,1334
42
+ porterminal/domain/values/user_id.py,sha256=eskGRVL-qj4czXljF0e5imDh19pAq16faXJY0lZ73kM,581
43
+ porterminal/infrastructure/__init__.py,sha256=rIaiEG4gyvfSixSEry0kA2uMhStQQIWv9PRlfs17qts,649
44
+ porterminal/infrastructure/cloudflared.py,sha256=6vGUdFmGrxLTbopGgEdYRKJ5n0M3Ov00cuM-hEYAjSk,11506
45
+ porterminal/infrastructure/network.py,sha256=XnYbEXKQA8BnrLFl9b4OTTixFG1pVFxfeVuhN-XPkfU,1275
46
+ porterminal/infrastructure/server.py,sha256=U_GwzUSyD96S3_M-jOj922lsgCWGvyDPev0vyd3nlGc,4463
47
+ porterminal/infrastructure/config/__init__.py,sha256=9KOQsmjYn6iPS5xnp2UZnmEUqm7ZUoxQcU48CF6xPR8,205
48
+ porterminal/infrastructure/config/shell_detector.py,sha256=03raUHVgKg0UG1KNrf_U3BOQ1Mbi3gGNxK_etLCIubQ,2610
49
+ porterminal/infrastructure/config/yaml_loader.py,sha256=7EQhJLQymHRGwHLIsEXvIDTnfcRmMgl-ASuQaOaycnY,877
50
+ porterminal/infrastructure/registry/__init__.py,sha256=reNbIYRr1alNps7zm_oENuS6QWNKiiO-WG09LT5MLmM,157
51
+ porterminal/infrastructure/registry/user_connection_registry.py,sha256=u9KOSijHiRITnwnOBKwXuYOKbFguh2NbxmNMxIoo8vc,3398
52
+ porterminal/infrastructure/repositories/__init__.py,sha256=UyF9lpobXgKb9Ti6ucC6fDcC9CkMAGDThggEG-Rf-Aw,250
53
+ porterminal/infrastructure/repositories/in_memory_session.py,sha256=yNkCuxrR8S5yTC_I_OFOYg1DlgEkxcI2DEW6aPq9ByQ,2490
54
+ porterminal/infrastructure/repositories/in_memory_tab.py,sha256=J0AC1jgv63YvnuZzQTkIT6aUUC6b7zqVrXFnPSZ_sVQ,4337
55
+ porterminal/infrastructure/web/__init__.py,sha256=QZqOtxOqhuxh4AD5xzPl9CBfOscdXOoGQv4zT4rpy7Q,147
56
+ porterminal/infrastructure/web/websocket_adapter.py,sha256=vVjIhcfWikPw-PKfSyqm3Y7PbTxNj1mstfrHIpcg6ng,2424
57
+ porterminal/pty/__init__.py,sha256=WNniN5uYKthLMOT7nzH63pkfFCJltToika50NZGR2cA,1054
58
+ porterminal/pty/env.py,sha256=-TmrdZfRzbVmyt8CJB7AoeZupbvkLBHumJOOtZLWgvI,2268
59
+ porterminal/pty/manager.py,sha256=Z7uvxauCC43b3z25VyJD0tI__08EpgcogT-Fe-VV17w,4483
60
+ porterminal/pty/protocol.py,sha256=-OPHIfLxL6R_JTrOQNB2t-sRH7LqtFgJE3QkBcHBqNA,1982
61
+ porterminal/pty/unix.py,sha256=hDwHuD2XD4RN6t_Hk_q-XvgQ4dNF9zUSwJhe0-Y9JBU,5094
62
+ porterminal/pty/windows.py,sha256=7WrtxgUbqDKSPMK9_pN9vNPzMalV1p-UyyZlBZJn8EY,3933
63
+ porterminal/static/icon.svg,sha256=y7-MIl7F_wVQMLHWmmC7MrZHZK5ikLg1BR_0jbqnTkc,1949
64
+ porterminal/static/index.html,sha256=UJbLVhG9EqGE-FYaF-D0vDw20Ux1dzZ3MtYKu2RDUYc,6627
65
+ porterminal/static/manifest.json,sha256=h81-UNLU_V2-BxsjIy8BqODzIN9Ppn-ej1cneZsdR38,688
66
+ porterminal/static/sw.js,sha256=1rE3N-4MMwl3kFAyrmsWQWiTbdjfpn33BD6DsVj0oA8,1892
67
+ porterminal/static/assets/app-BQiuUo6Q.css,sha256=6agNcSPu-05ATv9AiFxWPbnnn3QmdUa8igeGKAD_MZs,16310
68
+ porterminal/static/assets/app-YNN_jEhv.js,sha256=hTMVk2bZNGoS3udG8ukzo4t8afsuiylVvvpXE6gIi94,432496
69
+ ptn-0.1.4.dist-info/METADATA,sha256=yx2VYWHaA-3p8TuTZsIR0-tacKQIBvgQp2LrETSk9Xc,5391
70
+ ptn-0.1.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
71
+ ptn-0.1.4.dist-info/entry_points.txt,sha256=Ftj1zSu_7G0yD5mAtGN3RoewyIuoBOfP_noSISe73tU,41
72
+ ptn-0.1.4.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
73
+ ptn-0.1.4.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ptn = porterminal:main