portacode 0.3.20.dev10__tar.gz → 1.4.3__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.

Potentially problematic release.


This version of portacode might be problematic. Click here for more details.

Files changed (378) hide show
  1. {portacode-0.3.20.dev10 → portacode-1.4.3}/.claude/settings.local.json +6 -2
  2. portacode-1.4.3/.gitignore +16 -0
  3. portacode-1.4.3/.gitmodules +6 -0
  4. portacode-1.4.3/MANIFEST.in +4 -0
  5. portacode-1.4.3/PKG-INFO +293 -0
  6. portacode-1.4.3/README.md +251 -0
  7. portacode-1.4.3/connect.py +11 -0
  8. portacode-1.4.3/connect.sh +15 -0
  9. portacode-1.4.3/docker-compose.yaml +98 -0
  10. portacode-1.4.3/docs/images/device-transfer-button.png +0 -0
  11. portacode-1.4.3/docs/images/device-transfer-modal.png +0 -0
  12. portacode-1.4.3/docs/images/pair-device-button.png +0 -0
  13. portacode-1.4.3/docs/images/pairing-request.png +0 -0
  14. portacode-1.4.3/docs/images/student-workspace.png +0 -0
  15. portacode-1.4.3/examples/README.md +9 -0
  16. portacode-1.4.3/examples/simple_device/Dockerfile +8 -0
  17. portacode-1.4.3/examples/simple_device/README.md +35 -0
  18. portacode-1.4.3/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode +15 -0
  19. portacode-1.4.3/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode.pub +6 -0
  20. portacode-1.4.3/examples/simple_device/docker-compose.yaml +14 -0
  21. portacode-1.4.3/examples/workshop_fleet/Dockerfile +16 -0
  22. portacode-1.4.3/examples/workshop_fleet/README.md +152 -0
  23. portacode-1.4.3/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode +15 -0
  24. portacode-1.4.3/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode.pub +6 -0
  25. portacode-1.4.3/examples/workshop_fleet/data/student-01/.local/share/portacode/run/gateway.pid +1 -0
  26. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/.gitignore +2 -0
  27. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/README.md +38 -0
  28. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/db.sqlite3 +0 -0
  29. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__init__.py +1 -0
  30. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/__init__.cpython-311.pyc +0 -0
  31. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/settings.cpython-311.pyc +0 -0
  32. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/urls.cpython-311.pyc +0 -0
  33. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/wsgi.cpython-311.pyc +0 -0
  34. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/asgi.py +13 -0
  35. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/settings.py +87 -0
  36. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/urls.py +13 -0
  37. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/wsgi.py +13 -0
  38. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/manage.py +22 -0
  39. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/requirements.txt +1 -0
  40. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/templates/treats/home.html +137 -0
  41. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/__init__.py +1 -0
  42. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/__init__.cpython-311.pyc +0 -0
  43. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/admin.cpython-311.pyc +0 -0
  44. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/apps.cpython-311.pyc +0 -0
  45. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/menu.cpython-311.pyc +0 -0
  46. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/models.cpython-311.pyc +0 -0
  47. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/urls.cpython-311.pyc +0 -0
  48. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/views.cpython-311.pyc +0 -0
  49. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/admin.py +3 -0
  50. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/apps.py +6 -0
  51. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/menu.py +69 -0
  52. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__init__.py +1 -0
  53. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
  54. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/models.py +11 -0
  55. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/tests.py +15 -0
  56. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/urls.py +9 -0
  57. portacode-1.4.3/examples/workshop_fleet/data/student-01/workspace/treats/views.py +28 -0
  58. portacode-1.4.3/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode +15 -0
  59. portacode-1.4.3/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode.pub +6 -0
  60. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/README.md +38 -0
  61. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/__init__.py +1 -0
  62. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/asgi.py +13 -0
  63. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/settings.py +87 -0
  64. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/urls.py +13 -0
  65. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/wsgi.py +13 -0
  66. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/manage.py +22 -0
  67. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/requirements.txt +1 -0
  68. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/templates/treats/home.html +85 -0
  69. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/treats/__init__.py +1 -0
  70. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/treats/admin.py +3 -0
  71. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/treats/apps.py +6 -0
  72. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/treats/menu.py +43 -0
  73. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/treats/migrations/__init__.py +1 -0
  74. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/treats/models.py +11 -0
  75. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/treats/tests.py +15 -0
  76. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/treats/urls.py +9 -0
  77. portacode-1.4.3/examples/workshop_fleet/data/student-02/workspace/treats/views.py +22 -0
  78. portacode-1.4.3/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode +15 -0
  79. portacode-1.4.3/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode.pub +6 -0
  80. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/README.md +38 -0
  81. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/__init__.py +1 -0
  82. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/asgi.py +13 -0
  83. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/settings.py +87 -0
  84. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/urls.py +13 -0
  85. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/wsgi.py +13 -0
  86. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/manage.py +22 -0
  87. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/requirements.txt +1 -0
  88. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/templates/treats/home.html +85 -0
  89. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/treats/__init__.py +1 -0
  90. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/treats/admin.py +3 -0
  91. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/treats/apps.py +6 -0
  92. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/treats/menu.py +43 -0
  93. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/treats/migrations/__init__.py +1 -0
  94. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/treats/models.py +11 -0
  95. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/treats/tests.py +15 -0
  96. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/treats/urls.py +9 -0
  97. portacode-1.4.3/examples/workshop_fleet/data/student-03/workspace/treats/views.py +22 -0
  98. portacode-1.4.3/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode +15 -0
  99. portacode-1.4.3/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode.pub +6 -0
  100. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/README.md +38 -0
  101. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/__init__.py +1 -0
  102. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/asgi.py +13 -0
  103. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/settings.py +87 -0
  104. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/urls.py +13 -0
  105. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/wsgi.py +13 -0
  106. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/manage.py +22 -0
  107. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/requirements.txt +1 -0
  108. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/templates/treats/home.html +85 -0
  109. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/treats/__init__.py +1 -0
  110. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/treats/admin.py +3 -0
  111. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/treats/apps.py +6 -0
  112. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/treats/menu.py +43 -0
  113. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/treats/migrations/__init__.py +1 -0
  114. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/treats/models.py +11 -0
  115. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/treats/tests.py +15 -0
  116. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/treats/urls.py +9 -0
  117. portacode-1.4.3/examples/workshop_fleet/data/student-04/workspace/treats/views.py +22 -0
  118. portacode-1.4.3/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode +15 -0
  119. portacode-1.4.3/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode.pub +6 -0
  120. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/README.md +38 -0
  121. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/__init__.py +1 -0
  122. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/asgi.py +13 -0
  123. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/settings.py +87 -0
  124. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/urls.py +13 -0
  125. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/wsgi.py +13 -0
  126. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/manage.py +22 -0
  127. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/requirements.txt +1 -0
  128. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/templates/treats/home.html +85 -0
  129. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/treats/__init__.py +1 -0
  130. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/treats/admin.py +3 -0
  131. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/treats/apps.py +6 -0
  132. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/treats/menu.py +43 -0
  133. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/treats/migrations/__init__.py +1 -0
  134. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/treats/models.py +11 -0
  135. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/treats/tests.py +15 -0
  136. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/treats/urls.py +9 -0
  137. portacode-1.4.3/examples/workshop_fleet/data/student-05/workspace/treats/views.py +22 -0
  138. portacode-1.4.3/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode +15 -0
  139. portacode-1.4.3/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode.pub +6 -0
  140. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/README.md +38 -0
  141. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/__init__.py +1 -0
  142. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/asgi.py +13 -0
  143. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/settings.py +87 -0
  144. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/urls.py +13 -0
  145. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/wsgi.py +13 -0
  146. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/manage.py +22 -0
  147. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/requirements.txt +1 -0
  148. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/templates/treats/home.html +85 -0
  149. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/treats/__init__.py +1 -0
  150. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/treats/admin.py +3 -0
  151. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/treats/apps.py +6 -0
  152. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/treats/menu.py +43 -0
  153. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/treats/migrations/__init__.py +1 -0
  154. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/treats/models.py +11 -0
  155. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/treats/tests.py +15 -0
  156. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/treats/urls.py +9 -0
  157. portacode-1.4.3/examples/workshop_fleet/data/student-06/workspace/treats/views.py +22 -0
  158. portacode-1.4.3/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode +15 -0
  159. portacode-1.4.3/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode.pub +6 -0
  160. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/README.md +38 -0
  161. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/__init__.py +1 -0
  162. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/asgi.py +13 -0
  163. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/settings.py +87 -0
  164. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/urls.py +13 -0
  165. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/wsgi.py +13 -0
  166. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/manage.py +22 -0
  167. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/requirements.txt +1 -0
  168. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/templates/treats/home.html +85 -0
  169. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/treats/__init__.py +1 -0
  170. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/treats/admin.py +3 -0
  171. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/treats/apps.py +6 -0
  172. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/treats/menu.py +43 -0
  173. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/treats/migrations/__init__.py +1 -0
  174. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/treats/models.py +11 -0
  175. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/treats/tests.py +15 -0
  176. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/treats/urls.py +9 -0
  177. portacode-1.4.3/examples/workshop_fleet/data/student-07/workspace/treats/views.py +22 -0
  178. portacode-1.4.3/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode +15 -0
  179. portacode-1.4.3/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode.pub +6 -0
  180. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/README.md +38 -0
  181. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/__init__.py +1 -0
  182. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/asgi.py +13 -0
  183. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/settings.py +87 -0
  184. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/urls.py +13 -0
  185. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/wsgi.py +13 -0
  186. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/manage.py +22 -0
  187. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/requirements.txt +1 -0
  188. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/templates/treats/home.html +85 -0
  189. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/treats/__init__.py +1 -0
  190. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/treats/admin.py +3 -0
  191. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/treats/apps.py +6 -0
  192. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/treats/menu.py +43 -0
  193. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/treats/migrations/__init__.py +1 -0
  194. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/treats/models.py +11 -0
  195. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/treats/tests.py +15 -0
  196. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/treats/urls.py +9 -0
  197. portacode-1.4.3/examples/workshop_fleet/data/student-08/workspace/treats/views.py +22 -0
  198. portacode-1.4.3/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode +15 -0
  199. portacode-1.4.3/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode.pub +6 -0
  200. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/README.md +38 -0
  201. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/__init__.py +1 -0
  202. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/asgi.py +13 -0
  203. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/settings.py +87 -0
  204. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/urls.py +13 -0
  205. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/wsgi.py +13 -0
  206. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/manage.py +22 -0
  207. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/requirements.txt +1 -0
  208. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/templates/treats/home.html +85 -0
  209. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/treats/__init__.py +1 -0
  210. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/treats/admin.py +3 -0
  211. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/treats/apps.py +6 -0
  212. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/treats/menu.py +43 -0
  213. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/treats/migrations/__init__.py +1 -0
  214. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/treats/models.py +11 -0
  215. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/treats/tests.py +15 -0
  216. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/treats/urls.py +9 -0
  217. portacode-1.4.3/examples/workshop_fleet/data/student-09/workspace/treats/views.py +22 -0
  218. portacode-1.4.3/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode +15 -0
  219. portacode-1.4.3/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode.pub +6 -0
  220. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/README.md +38 -0
  221. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/__init__.py +1 -0
  222. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/asgi.py +13 -0
  223. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/settings.py +87 -0
  224. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/urls.py +13 -0
  225. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/wsgi.py +13 -0
  226. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/manage.py +22 -0
  227. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/requirements.txt +1 -0
  228. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/templates/treats/home.html +85 -0
  229. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/treats/__init__.py +1 -0
  230. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/treats/admin.py +3 -0
  231. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/treats/apps.py +6 -0
  232. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/treats/menu.py +43 -0
  233. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/treats/migrations/__init__.py +1 -0
  234. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/treats/models.py +11 -0
  235. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/treats/tests.py +15 -0
  236. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/treats/urls.py +9 -0
  237. portacode-1.4.3/examples/workshop_fleet/data/student-10/workspace/treats/views.py +22 -0
  238. portacode-1.4.3/examples/workshop_fleet/docker-compose.yaml +121 -0
  239. portacode-1.4.3/examples/workshop_fleet/initial_content/README.md +38 -0
  240. portacode-1.4.3/examples/workshop_fleet/initial_content/galactic_bakeshop/__init__.py +1 -0
  241. portacode-1.4.3/examples/workshop_fleet/initial_content/galactic_bakeshop/asgi.py +13 -0
  242. portacode-1.4.3/examples/workshop_fleet/initial_content/galactic_bakeshop/settings.py +87 -0
  243. portacode-1.4.3/examples/workshop_fleet/initial_content/galactic_bakeshop/urls.py +13 -0
  244. portacode-1.4.3/examples/workshop_fleet/initial_content/galactic_bakeshop/wsgi.py +13 -0
  245. portacode-1.4.3/examples/workshop_fleet/initial_content/manage.py +22 -0
  246. portacode-1.4.3/examples/workshop_fleet/initial_content/requirements.txt +1 -0
  247. portacode-1.4.3/examples/workshop_fleet/initial_content/templates/treats/home.html +85 -0
  248. portacode-1.4.3/examples/workshop_fleet/initial_content/treats/__init__.py +1 -0
  249. portacode-1.4.3/examples/workshop_fleet/initial_content/treats/admin.py +3 -0
  250. portacode-1.4.3/examples/workshop_fleet/initial_content/treats/apps.py +6 -0
  251. portacode-1.4.3/examples/workshop_fleet/initial_content/treats/menu.py +43 -0
  252. portacode-1.4.3/examples/workshop_fleet/initial_content/treats/migrations/__init__.py +1 -0
  253. portacode-1.4.3/examples/workshop_fleet/initial_content/treats/models.py +11 -0
  254. portacode-1.4.3/examples/workshop_fleet/initial_content/treats/tests.py +15 -0
  255. portacode-1.4.3/examples/workshop_fleet/initial_content/treats/urls.py +9 -0
  256. portacode-1.4.3/examples/workshop_fleet/initial_content/treats/views.py +22 -0
  257. portacode-1.4.3/examples/workshop_fleet/instructions/WELCOME.md +25 -0
  258. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/_version.py +16 -3
  259. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/cli.py +143 -17
  260. portacode-1.4.3/portacode/connection/client.py +383 -0
  261. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +573 -34
  262. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/__init__.py +14 -1
  263. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/base.py +78 -16
  264. portacode-1.4.3/portacode/connection/handlers/chunked_content.py +244 -0
  265. portacode-1.4.3/portacode/connection/handlers/diff_handlers.py +603 -0
  266. portacode-1.4.3/portacode/connection/handlers/file_handlers.py +1094 -0
  267. portacode-1.4.3/portacode/connection/handlers/project_aware_file_handlers.py +226 -0
  268. portacode-1.4.3/portacode/connection/handlers/project_state/__init__.py +92 -0
  269. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/project_state/file_system_watcher.py +61 -35
  270. portacode-1.4.3/portacode/connection/handlers/project_state/git_manager.py +1502 -0
  271. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/project_state/handlers.py +393 -72
  272. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/project_state/manager.py +458 -234
  273. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/project_state/models.py +7 -0
  274. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/project_state/utils.py +17 -28
  275. portacode-1.4.3/portacode/connection/handlers/project_state_handlers.py +45 -0
  276. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/registry.py +15 -4
  277. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/session.py +316 -26
  278. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/system_handlers.py +26 -7
  279. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/tab_factory.py +53 -46
  280. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/terminal_handlers.py +21 -8
  281. portacode-1.4.3/portacode/connection/handlers/update_handler.py +61 -0
  282. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/terminal.py +79 -20
  283. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/keypair.py +63 -1
  284. portacode-1.4.3/portacode/logging_categories.py +140 -0
  285. portacode-1.4.3/portacode/pairing.py +103 -0
  286. portacode-1.4.3/portacode/static/js/test-ntp-clock.html +63 -0
  287. portacode-1.4.3/portacode/static/js/utils/ntp-clock.js +232 -0
  288. portacode-1.4.3/portacode/utils/NTP_ARCHITECTURE.md +136 -0
  289. portacode-1.4.3/portacode/utils/__init__.py +1 -0
  290. portacode-1.4.3/portacode/utils/diff_apply.py +456 -0
  291. portacode-1.4.3/portacode/utils/diff_renderer.py +371 -0
  292. portacode-1.4.3/portacode/utils/ntp_clock.py +65 -0
  293. portacode-1.4.3/portacode.egg-info/PKG-INFO +293 -0
  294. portacode-1.4.3/portacode.egg-info/SOURCES.txt +359 -0
  295. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode.egg-info/requires.txt +1 -0
  296. {portacode-0.3.20.dev10 → portacode-1.4.3}/setup.py +7 -0
  297. {portacode-0.3.20.dev10 → portacode-1.4.3}/test_modules/test_device_online.py +1 -1
  298. {portacode-0.3.20.dev10 → portacode-1.4.3}/test_modules/test_file_operations.py +93 -3
  299. portacode-1.4.3/test_modules/test_git_status_ui.py +370 -0
  300. {portacode-0.3.20.dev10 → portacode-1.4.3}/test_modules/test_login_flow.py +8 -4
  301. {portacode-0.3.20.dev10 → portacode-1.4.3}/test_modules/test_navigate_testing_folder.py +156 -72
  302. portacode-1.4.3/test_modules/test_play_store_screenshots.py +294 -0
  303. portacode-1.4.3/test_modules/test_terminal_buffer_performance.py +261 -0
  304. portacode-1.4.3/test_modules/test_terminal_loading_race_condition.py +95 -0
  305. portacode-1.4.3/test_request_id.py +146 -0
  306. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/.env.example +4 -1
  307. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/core/hierarchical_runner.py +77 -5
  308. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/core/playwright_manager.py +92 -9
  309. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/core/runner.py +10 -2
  310. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/core/test_discovery.py +7 -3
  311. portacode-1.4.3/todo/UI_UX/opening_a_file_on_desktop_results_in_nothing.md +1 -0
  312. portacode-1.4.3/todo/agent_context_management.md +12 -0
  313. portacode-1.4.3/todo/django_server_time_sync.md +54 -0
  314. portacode-1.4.3/todo/issues/device_performance_degradation.md +129 -0
  315. portacode-1.4.3/todo/issues/git_data_not_captured_in_proxmox.md +2004 -0
  316. portacode-1.4.3/todo/issues/indefinite_resource_loading.md +5 -0
  317. portacode-1.4.3/todo/issues/portacode_service_silently_down.md +74 -0
  318. portacode-1.4.3/todo/issues/premature_terminal_exit.md +66 -0
  319. portacode-1.4.3/todo/issues/project_cpu_hotspots.md +33 -0
  320. portacode-1.4.3/todo/issues/terminals_exit_upon_starting.md +3 -0
  321. portacode-1.4.3/todo/issues/wrong_item_classification_on_client_side.md +15 -0
  322. portacode-1.4.3/todo/smartphone_terminal_input_frustrations.md +11 -0
  323. portacode-1.4.3/tools/generate_play_store_assets.py +1033 -0
  324. portacode-1.4.3/tools/pairing_tester.py +97 -0
  325. portacode-1.4.3/tools/run_screenshot_suite.sh +92 -0
  326. portacode-1.4.3/tools/test_python_ntp_clock.py +39 -0
  327. portacode-1.4.3/validate.sh +146 -0
  328. portacode-0.3.20.dev10/.gitignore +0 -10
  329. portacode-0.3.20.dev10/.gitmodules +0 -3
  330. portacode-0.3.20.dev10/MANIFEST.in +0 -2
  331. portacode-0.3.20.dev10/PKG-INFO +0 -241
  332. portacode-0.3.20.dev10/README.md +0 -211
  333. portacode-0.3.20.dev10/docker-compose.yaml +0 -37
  334. portacode-0.3.20.dev10/portacode/connection/client.py +0 -189
  335. portacode-0.3.20.dev10/portacode/connection/handlers/file_handlers.py +0 -368
  336. portacode-0.3.20.dev10/portacode/connection/handlers/project_state/__init__.py +0 -145
  337. portacode-0.3.20.dev10/portacode/connection/handlers/project_state/centralized_handlers.py +0 -395
  338. portacode-0.3.20.dev10/portacode/connection/handlers/project_state/centralized_manager.py +0 -586
  339. portacode-0.3.20.dev10/portacode/connection/handlers/project_state/centralized_state.py +0 -468
  340. portacode-0.3.20.dev10/portacode/connection/handlers/project_state/git_manager.py +0 -1177
  341. portacode-0.3.20.dev10/portacode/connection/handlers/project_state/simplified_file_watcher.py +0 -162
  342. portacode-0.3.20.dev10/portacode/connection/handlers/project_state_handlers.py +0 -43
  343. portacode-0.3.20.dev10/portacode.egg-info/PKG-INFO +0 -241
  344. portacode-0.3.20.dev10/portacode.egg-info/SOURCES.txt +0 -78
  345. {portacode-0.3.20.dev10 → portacode-1.4.3}/.claude/agents/communication-manager.md +0 -0
  346. {portacode-0.3.20.dev10 → portacode-1.4.3}/LICENSE +0 -0
  347. {portacode-0.3.20.dev10 → portacode-1.4.3}/Makefile +0 -0
  348. {portacode-0.3.20.dev10 → portacode-1.4.3}/backup.sh +0 -0
  349. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/README.md +0 -0
  350. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/__init__.py +0 -0
  351. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/__main__.py +0 -0
  352. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/README.md +0 -0
  353. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/__init__.py +0 -0
  354. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/README.md +0 -0
  355. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/handlers/project_state/README.md +0 -0
  356. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/connection/multiplex.py +0 -0
  357. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/data.py +0 -0
  358. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode/service.py +0 -0
  359. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode.egg-info/dependency_links.txt +0 -0
  360. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode.egg-info/entry_points.txt +0 -0
  361. {portacode-0.3.20.dev10 → portacode-1.4.3}/portacode.egg-info/top_level.txt +0 -0
  362. {portacode-0.3.20.dev10 → portacode-1.4.3}/pyproject.toml +0 -0
  363. {portacode-0.3.20.dev10 → portacode-1.4.3}/restore.sh +0 -0
  364. {portacode-0.3.20.dev10 → portacode-1.4.3}/run_tests.py +0 -0
  365. {portacode-0.3.20.dev10 → portacode-1.4.3}/setup.cfg +0 -0
  366. {portacode-0.3.20.dev10 → portacode-1.4.3}/test.sh +0 -0
  367. {portacode-0.3.20.dev10 → portacode-1.4.3}/test_modules/README.md +0 -0
  368. {portacode-0.3.20.dev10 → portacode-1.4.3}/test_modules/__init__.py +0 -0
  369. {portacode-0.3.20.dev10 → portacode-1.4.3}/test_modules/test_terminal_interaction.py +0 -0
  370. {portacode-0.3.20.dev10 → portacode-1.4.3}/test_modules/test_terminal_start.py +0 -0
  371. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/README.md +0 -0
  372. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/__init__.py +0 -0
  373. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/cli.py +0 -0
  374. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/core/__init__.py +0 -0
  375. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/core/base_test.py +0 -0
  376. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/core/cli_manager.py +0 -0
  377. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/core/shared_cli_manager.py +0 -0
  378. {portacode-0.3.20.dev10 → portacode-1.4.3}/testing_framework/requirements.txt +0 -0
@@ -12,8 +12,12 @@
12
12
  "Bash(grep:*)",
13
13
  "Bash(./test.sh)",
14
14
  "Bash(./test.sh:*)",
15
- "Bash(mkdir:*)"
15
+ "Bash(mkdir:*)",
16
+ "Bash(./connect.sh)",
17
+ "Bash(git -C /home/menas/testing_folder status --porcelain)",
18
+ "Bash(docker-compose restart:*)",
19
+ "Bash(./debug/list_user_devices_and_projects.sh:*)"
16
20
  ],
17
21
  "deny": []
18
22
  }
19
- }
23
+ }
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info
4
+ *.env
5
+ *.env.*
6
+ dist
7
+ .pypirc
8
+ _version.py
9
+ client_sessions.json
10
+ project_state_debug.json
11
+ test_results
12
+ logs
13
+
14
+ # Example-generated volumes
15
+ examples/simple_device/data/
16
+ examples/workshop_fleet/data/
@@ -0,0 +1,6 @@
1
+ [submodule "server"]
2
+ path = server
3
+ url = ./server
4
+ [submodule "portacode_for_school"]
5
+ path = portacode_for_school
6
+ url = git@github.com:meena-erian/portacode_for_school.git
@@ -0,0 +1,4 @@
1
+ prune server
2
+ exclude .pypirc
3
+ recursive-include portacode/static *.js *.html
4
+ recursive-include examples *
@@ -0,0 +1,293 @@
1
+ Metadata-Version: 2.4
2
+ Name: portacode
3
+ Version: 1.4.3
4
+ Summary: Portacode CLI client and SDK
5
+ Home-page: https://github.com/portacode/portacode
6
+ Author: Meena Erian
7
+ Author-email: hi@menas.pro
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: click>=8.0
15
+ Requires-Dist: platformdirs>=3.0
16
+ Requires-Dist: cryptography>=41.0
17
+ Requires-Dist: websockets>=12.0
18
+ Requires-Dist: pyperclip>=1.8
19
+ Requires-Dist: psutil>=5.9
20
+ Requires-Dist: pyte>=0.8
21
+ Requires-Dist: pywinpty>=2.0; platform_system == "Windows"
22
+ Requires-Dist: GitPython>=3.1.45
23
+ Requires-Dist: watchdog>=3.0
24
+ Requires-Dist: diff-match-patch>=20230430
25
+ Requires-Dist: Pygments>=2.14.0
26
+ Requires-Dist: ntplib>=0.4.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: black; extra == "dev"
29
+ Requires-Dist: flake8; extra == "dev"
30
+ Requires-Dist: pytest; extra == "dev"
31
+ Dynamic: author
32
+ Dynamic: author-email
33
+ Dynamic: classifier
34
+ Dynamic: description
35
+ Dynamic: description-content-type
36
+ Dynamic: home-page
37
+ Dynamic: license-file
38
+ Dynamic: provides-extra
39
+ Dynamic: requires-dist
40
+ Dynamic: requires-python
41
+ Dynamic: summary
42
+
43
+ # Portacode
44
+
45
+ **An AI-first, mobile-first IDE and admin tool, made with love and passion by software engineers, for software engineers.**
46
+
47
+ Portacode transforms any device with python into a remotely accessible development environment. Access your home lab, server or even embedded system chip from your phone, code on your desktop or your smartphone from anywhere, or help a colleague debug their server - all through a beautiful web interface designed for the modern developer.
48
+
49
+ ## ✨ Why Portacode?
50
+
51
+ - **🤖 AI-First**: Built from the ground up with AI integration in mind
52
+ - **📱 Mobile-First**: Code and administrate from your phone or tablet
53
+ - **🌍 Global Access**: Connect to your devices from anywhere with internet
54
+ - **🔐 Secure**: HTTPS encrypted with RSA key authentication
55
+ - **⚡ Fast Setup**: Get connected in under 60 seconds
56
+ - **🔄 Always Connected**: Automatic reconnection and persistent service options
57
+ - **🆓 Free Account**: Create your account and start connecting immediately
58
+ - **🖥️ Cross-Platform**: Works on Windows, macOS, and Linux
59
+
60
+ ## 🚀 Quick Start
61
+
62
+ ### 1. Install Portacode
63
+
64
+ ```bash
65
+ pip install portacode
66
+ ```
67
+
68
+ ### 2. Connect Your Device
69
+
70
+ ```bash
71
+ portacode connect
72
+ ```
73
+
74
+ Follow the on-screen instructions to:
75
+ - Visit [https://portacode.com](https://portacode.com)
76
+ - Create your free account
77
+ - Add your device using the generated key
78
+ - Start coding and administrating!
79
+
80
+ ### 3. Access Your Development Environment
81
+
82
+ Once connected, you can:
83
+ - Open terminal sessions from the web dashboard
84
+ - Execute commands remotely
85
+ - Monitor system status
86
+ - Access your development environment from any device
87
+
88
+ Want to see Portacode running inside containers or powering classrooms? Browse the [`examples/` directory](https://github.com/portacode/portacode/tree/master/examples) (also bundled in the PyPI source) for copy-paste Docker Compose setups ranging from a single-device sandbox to a ten-seat workshop fleet.
89
+
90
+ ## 🔑 Pair Devices with Zero-Touch Codes
91
+
92
+ The fastest way to bring a new machine online is with a short-lived pairing code:
93
+
94
+ 1. Log in to [https://portacode.com](https://portacode.com) and press **Pair Device** on the dashboard:
95
+ ![Pair Device button](https://raw.githubusercontent.com/portacode/portacode/master/docs/images/pair-device-button.png)
96
+ 2. A four-digit code appears (valid for 15 minutes). This code only authorizes a pairing **request**—no device can reach your account until you approve it.
97
+ 3. On the device, run Portacode with the code:
98
+ ```bash
99
+ PORTACODE_PAIRING_CODE=1234 portacode connect \
100
+ --device-name "My Laptop" \
101
+ --project-path /srv/project-one \
102
+ --project-path /srv/project-two
103
+ ```
104
+ - `--device-name` (or `PORTACODE_DEVICE_NAME`) pre-fills the friendly label shown in the dashboard.
105
+ - Repeat `--project-path /abs/path` to register up to ten Projects automatically once the request is approved.
106
+ - Automating inside Docker? Export your own `PORTACODE_PROJECT_PATHS=/srv/a:/srv/b` and convert it into repeated `--project-path` switches before invoking the CLI—see `portacode_for_school/persistent_workspace/entrypoint.sh` for a reference implementation.
107
+ 4. Because the device has no fingerprint yet, the CLI bootstraps an in-memory keypair and announces a pending request to the dashboard. You immediately see the card with the supplied metadata:
108
+ ![Pairing request card](https://raw.githubusercontent.com/portacode/portacode/master/docs/images/pairing-request.png)
109
+ 5. Click **Approve**. The CLI persists the keypair on disk and transitions into a normal authenticated connection. Future `portacode connect` runs reuse the stored RSA keys—no additional codes required unless you revoke the device.
110
+
111
+ Need to pair multiple machines at once? A single pairing code can be reused concurrently: every device that launches `portacode connect` with that code shows up as its own approval card until you accept or decline it.
112
+
113
+ This workflow works great for headless setups and containers: export the environment variables, run `portacode connect --non-interactive`, and finish the approval from the dashboard.
114
+
115
+ ## 💡 Use Cases
116
+
117
+ - **Remote Development**: Code, build, and debug from anywhere - even your phone
118
+ - **Server Administration**: 24/7 server access with persistent service installation
119
+ - **Mobile Development**: Full IDE experience on mobile devices
120
+
121
+ ## 🔧 Essential Commands
122
+
123
+ ### Basic Usage
124
+ ```bash
125
+ # Start a connection (runs until closed)
126
+ portacode connect
127
+
128
+ # Run connection in background
129
+ portacode connect --detach
130
+
131
+ # Check version
132
+ portacode --version
133
+
134
+ # Get help
135
+ portacode --help
136
+ ```
137
+
138
+ ### Service Management
139
+ ```bash
140
+ # First, authenticate your device
141
+ portacode connect
142
+
143
+ # For system services, install package system-wide
144
+ sudo pip install portacode --system
145
+
146
+ # Install persistent service (auto-start on boot)
147
+ sudo portacode service install
148
+
149
+ # Check service status (use -v for verbose debugging)
150
+ sudo portacode service status
151
+ sudo portacode service status -v
152
+
153
+ # Stop/remove the service
154
+ sudo portacode service stop
155
+ sudo portacode service uninstall
156
+ ```
157
+
158
+ ## 🌐 Web Dashboard
159
+
160
+ Access your connected devices at [https://portacode.com](https://portacode.com)
161
+
162
+ **Current Features:**
163
+ - Real-time terminal access
164
+ - System monitoring
165
+ - Device management
166
+ - Multi-device switching
167
+ - Secure authentication
168
+
169
+ **Coming Soon:**
170
+ - AI-powered code assistance
171
+ - Mobile-optimized IDE interface
172
+ - File management and editing
173
+ - Collaborative development tools
174
+
175
+ ## 🔐 Security
176
+
177
+ - **RSA Key Authentication**: Each device gets a unique RSA key pair
178
+ - **HTTPS Encrypted**: All communication is encrypted in transit
179
+ - **No Passwords**: Key-based authentication eliminates password risks
180
+ - **Revocable Access**: Remove devices instantly from the web dashboard
181
+ - **Local Key Storage**: Private keys never leave your device
182
+
183
+ ## 🆘 Troubleshooting
184
+
185
+ ### Connection Issues
186
+ ```bash
187
+ # Check if another connection is running
188
+ portacode connect
189
+
190
+ # View service logs
191
+ sudo portacode service status --verbose
192
+ ```
193
+
194
+ ### Service Installation Issues
195
+ ```bash
196
+ # First authenticate your device
197
+ portacode connect
198
+
199
+ # If service commands fail, ensure system-wide installation
200
+ sudo pip install portacode --system
201
+
202
+ # Then try service installation again
203
+ sudo portacode service install
204
+
205
+ # Use verbose status to debug connection issues
206
+ sudo portacode service status -v
207
+ ```
208
+
209
+ ### Clipboard Issues (Linux)
210
+ ```bash
211
+ # Install clipboard support
212
+ sudo apt-get install xclip
213
+ ```
214
+
215
+ ### Key Management
216
+ Portacode follows the OS-specific *user data* directory (via [`platformdirs`](https://pypi.org/project/platformdirs/)) and keeps its identity in `portacode/keys/`:
217
+ - **Linux**: `~/.local/share/portacode/keys/`
218
+ - **macOS**: `~/Library/Application Support/portacode/keys/`
219
+ - **Windows**: `%APPDATA%\portacode\keys\`
220
+
221
+ When `PORTACODE_PAIRING_CODE` is set, the CLI generates an in-memory keypair, waits for dashboard approval, and only then writes the files to this directory. If that folder disappears, the CLI will create a fresh identity next time it runs.
222
+
223
+ #### Persisting Keys in Containers
224
+ Docker images (including the simple `python:3.11-slim` example that runs Portacode as `root`) store the data inside `/root/.local/share/portacode`. Bind-mount that path or override `XDG_DATA_HOME` so the keys survive container restarts:
225
+
226
+ ```yaml
227
+ services:
228
+ device-01:
229
+ build: .
230
+ environment:
231
+ PORTACODE_PAIRING_CODE: "${PORTACODE_PAIRING_CODE:-}"
232
+ volumes:
233
+ - ./data/device-01/workspace:/root/workspace
234
+ - ./data/device-01/.local/share/portacode:/root/.local/share/portacode # persists device keys
235
+ ```
236
+
237
+ Alternatively, set `XDG_DATA_HOME=/root/.portacode` before running `portacode connect` and mount that directory from the host. The rule of thumb: **persist whichever folder contains `.local/share/portacode/keys/`** so your device fingerprint sticks around.
238
+
239
+ #### Minimal Docker Example
240
+ If you want a plug-and-play container, check the `examples/simple_device/` folder that ships with this repo and the PyPI source distribution. It contains a tiny `Dockerfile` and `docker-compose.yaml` you can copy as-is. The Dockerfile installs `git` before `pip install portacode` so GitPython can interact with repositories—remember to do the same in your own images if you expect to work inside version-controlled projects.
241
+
242
+ The accompanying Compose file demonstrates how to:
243
+ - run `portacode connect --non-interactive` with a predefined `--device-name` and `--project-path`
244
+ - pass `PORTACODE_PAIRING_CODE` via environment variables
245
+ - bind-mount your workspace plus `/root/.local/share/portacode` for key persistence
246
+
247
+ Together, those 10 lines illustrate the complete flow for remotely accessing a Docker-hosted machine with Portacode.
248
+
249
+ #### Workshop Fleet Example
250
+ Training a group? `examples/workshop_fleet/` spins up ten identical containers—one per student—with their own workspace bind mounts plus a shared read-only `instructions/` folder. The Dockerfile in that folder copies everything from `initial_content/` into the image (`COPY initial_content/ /opt/initial_content/`), and the compose command seeds each student workspace on boot via `cp -an /opt/initial_content/. /root/workspace/`. That means:
251
+ - Instructors drop starter code into `initial_content/` before `docker compose up` and every container gets the same seed files without overwriting student changes after the first sync.
252
+ - The host `instructions/` directory is mounted at `/root/workspace/instructions` in **read-only** mode, so you can update agendas or hints live while students can only view them.
253
+ - Each seat persists its Portacode identity in `data/student-XX/.local/share/portacode`, so reconnecting after a restart does not need new pairing codes.
254
+
255
+ See the full walkthrough and assets in [`examples/workshop_fleet/`](https://github.com/portacode/portacode/tree/master/examples/workshop_fleet), which is also shipped inside the PyPI source tarball for offline access.
256
+
257
+ ## 🌱 Early Stage Project
258
+
259
+ **Portacode is a young project with big dreams.** We're building the future of remote development and mobile-first coding experiences. As a new project, we're actively seeking:
260
+
261
+ - **👥 Community Feedback**: Does this solve a real problem for you?
262
+ - **🤝 Contributors**: Help us build the IDE of the future
263
+ - **📢 Early Adopters**: Try it out and let us know what you think
264
+ - **💡 Feature Ideas**: What would make your remote development workflow better?
265
+
266
+ **Your support matters!** Whether you contribute code, report bugs, share ideas, or simply let us know that you find value in what we're building - every bit of feedback helps us decide whether to continue investing in this vision or focus on other projects.
267
+
268
+ ## 📞 Get In Touch
269
+
270
+ - **Email**: hi@menas.pro
271
+ - **Support**: support@portacode.com
272
+ - **GitHub**: [https://github.com/portacode/portacode](https://github.com/portacode/portacode)
273
+
274
+ ## 🤝 Contributing
275
+
276
+ We welcome all forms of contribution:
277
+ - 🐛 **Bug Reports**: Found something broken? Let us know!
278
+ - ✨ **Feature Requests**: What would make Portacode better for you?
279
+ - 📖 **Documentation**: Help others get started
280
+ - 💻 **Code Contributions**: Help us build the future of remote development
281
+ - 💬 **Feedback**: Tell us if you find this useful!
282
+
283
+ Check out our [GitHub repository](https://github.com/portacode/portacode) to get started.
284
+
285
+ ## 📄 License
286
+
287
+ MIT License - see [LICENSE](https://github.com/portacode/portacode/blob/master/LICENSE) file for details.
288
+
289
+ ---
290
+
291
+ **Get started today**: `pip install portacode && portacode connect`
292
+
293
+ *Built with ❤️ and ☕ by passionate software engineers*
@@ -0,0 +1,251 @@
1
+ # Portacode
2
+
3
+ **An AI-first, mobile-first IDE and admin tool, made with love and passion by software engineers, for software engineers.**
4
+
5
+ Portacode transforms any device with python into a remotely accessible development environment. Access your home lab, server or even embedded system chip from your phone, code on your desktop or your smartphone from anywhere, or help a colleague debug their server - all through a beautiful web interface designed for the modern developer.
6
+
7
+ ## ✨ Why Portacode?
8
+
9
+ - **🤖 AI-First**: Built from the ground up with AI integration in mind
10
+ - **📱 Mobile-First**: Code and administrate from your phone or tablet
11
+ - **🌍 Global Access**: Connect to your devices from anywhere with internet
12
+ - **🔐 Secure**: HTTPS encrypted with RSA key authentication
13
+ - **⚡ Fast Setup**: Get connected in under 60 seconds
14
+ - **🔄 Always Connected**: Automatic reconnection and persistent service options
15
+ - **🆓 Free Account**: Create your account and start connecting immediately
16
+ - **🖥️ Cross-Platform**: Works on Windows, macOS, and Linux
17
+
18
+ ## 🚀 Quick Start
19
+
20
+ ### 1. Install Portacode
21
+
22
+ ```bash
23
+ pip install portacode
24
+ ```
25
+
26
+ ### 2. Connect Your Device
27
+
28
+ ```bash
29
+ portacode connect
30
+ ```
31
+
32
+ Follow the on-screen instructions to:
33
+ - Visit [https://portacode.com](https://portacode.com)
34
+ - Create your free account
35
+ - Add your device using the generated key
36
+ - Start coding and administrating!
37
+
38
+ ### 3. Access Your Development Environment
39
+
40
+ Once connected, you can:
41
+ - Open terminal sessions from the web dashboard
42
+ - Execute commands remotely
43
+ - Monitor system status
44
+ - Access your development environment from any device
45
+
46
+ Want to see Portacode running inside containers or powering classrooms? Browse the [`examples/` directory](https://github.com/portacode/portacode/tree/master/examples) (also bundled in the PyPI source) for copy-paste Docker Compose setups ranging from a single-device sandbox to a ten-seat workshop fleet.
47
+
48
+ ## 🔑 Pair Devices with Zero-Touch Codes
49
+
50
+ The fastest way to bring a new machine online is with a short-lived pairing code:
51
+
52
+ 1. Log in to [https://portacode.com](https://portacode.com) and press **Pair Device** on the dashboard:
53
+ ![Pair Device button](https://raw.githubusercontent.com/portacode/portacode/master/docs/images/pair-device-button.png)
54
+ 2. A four-digit code appears (valid for 15 minutes). This code only authorizes a pairing **request**—no device can reach your account until you approve it.
55
+ 3. On the device, run Portacode with the code:
56
+ ```bash
57
+ PORTACODE_PAIRING_CODE=1234 portacode connect \
58
+ --device-name "My Laptop" \
59
+ --project-path /srv/project-one \
60
+ --project-path /srv/project-two
61
+ ```
62
+ - `--device-name` (or `PORTACODE_DEVICE_NAME`) pre-fills the friendly label shown in the dashboard.
63
+ - Repeat `--project-path /abs/path` to register up to ten Projects automatically once the request is approved.
64
+ - Automating inside Docker? Export your own `PORTACODE_PROJECT_PATHS=/srv/a:/srv/b` and convert it into repeated `--project-path` switches before invoking the CLI—see `portacode_for_school/persistent_workspace/entrypoint.sh` for a reference implementation.
65
+ 4. Because the device has no fingerprint yet, the CLI bootstraps an in-memory keypair and announces a pending request to the dashboard. You immediately see the card with the supplied metadata:
66
+ ![Pairing request card](https://raw.githubusercontent.com/portacode/portacode/master/docs/images/pairing-request.png)
67
+ 5. Click **Approve**. The CLI persists the keypair on disk and transitions into a normal authenticated connection. Future `portacode connect` runs reuse the stored RSA keys—no additional codes required unless you revoke the device.
68
+
69
+ Need to pair multiple machines at once? A single pairing code can be reused concurrently: every device that launches `portacode connect` with that code shows up as its own approval card until you accept or decline it.
70
+
71
+ This workflow works great for headless setups and containers: export the environment variables, run `portacode connect --non-interactive`, and finish the approval from the dashboard.
72
+
73
+ ## 💡 Use Cases
74
+
75
+ - **Remote Development**: Code, build, and debug from anywhere - even your phone
76
+ - **Server Administration**: 24/7 server access with persistent service installation
77
+ - **Mobile Development**: Full IDE experience on mobile devices
78
+
79
+ ## 🔧 Essential Commands
80
+
81
+ ### Basic Usage
82
+ ```bash
83
+ # Start a connection (runs until closed)
84
+ portacode connect
85
+
86
+ # Run connection in background
87
+ portacode connect --detach
88
+
89
+ # Check version
90
+ portacode --version
91
+
92
+ # Get help
93
+ portacode --help
94
+ ```
95
+
96
+ ### Service Management
97
+ ```bash
98
+ # First, authenticate your device
99
+ portacode connect
100
+
101
+ # For system services, install package system-wide
102
+ sudo pip install portacode --system
103
+
104
+ # Install persistent service (auto-start on boot)
105
+ sudo portacode service install
106
+
107
+ # Check service status (use -v for verbose debugging)
108
+ sudo portacode service status
109
+ sudo portacode service status -v
110
+
111
+ # Stop/remove the service
112
+ sudo portacode service stop
113
+ sudo portacode service uninstall
114
+ ```
115
+
116
+ ## 🌐 Web Dashboard
117
+
118
+ Access your connected devices at [https://portacode.com](https://portacode.com)
119
+
120
+ **Current Features:**
121
+ - Real-time terminal access
122
+ - System monitoring
123
+ - Device management
124
+ - Multi-device switching
125
+ - Secure authentication
126
+
127
+ **Coming Soon:**
128
+ - AI-powered code assistance
129
+ - Mobile-optimized IDE interface
130
+ - File management and editing
131
+ - Collaborative development tools
132
+
133
+ ## 🔐 Security
134
+
135
+ - **RSA Key Authentication**: Each device gets a unique RSA key pair
136
+ - **HTTPS Encrypted**: All communication is encrypted in transit
137
+ - **No Passwords**: Key-based authentication eliminates password risks
138
+ - **Revocable Access**: Remove devices instantly from the web dashboard
139
+ - **Local Key Storage**: Private keys never leave your device
140
+
141
+ ## 🆘 Troubleshooting
142
+
143
+ ### Connection Issues
144
+ ```bash
145
+ # Check if another connection is running
146
+ portacode connect
147
+
148
+ # View service logs
149
+ sudo portacode service status --verbose
150
+ ```
151
+
152
+ ### Service Installation Issues
153
+ ```bash
154
+ # First authenticate your device
155
+ portacode connect
156
+
157
+ # If service commands fail, ensure system-wide installation
158
+ sudo pip install portacode --system
159
+
160
+ # Then try service installation again
161
+ sudo portacode service install
162
+
163
+ # Use verbose status to debug connection issues
164
+ sudo portacode service status -v
165
+ ```
166
+
167
+ ### Clipboard Issues (Linux)
168
+ ```bash
169
+ # Install clipboard support
170
+ sudo apt-get install xclip
171
+ ```
172
+
173
+ ### Key Management
174
+ Portacode follows the OS-specific *user data* directory (via [`platformdirs`](https://pypi.org/project/platformdirs/)) and keeps its identity in `portacode/keys/`:
175
+ - **Linux**: `~/.local/share/portacode/keys/`
176
+ - **macOS**: `~/Library/Application Support/portacode/keys/`
177
+ - **Windows**: `%APPDATA%\portacode\keys\`
178
+
179
+ When `PORTACODE_PAIRING_CODE` is set, the CLI generates an in-memory keypair, waits for dashboard approval, and only then writes the files to this directory. If that folder disappears, the CLI will create a fresh identity next time it runs.
180
+
181
+ #### Persisting Keys in Containers
182
+ Docker images (including the simple `python:3.11-slim` example that runs Portacode as `root`) store the data inside `/root/.local/share/portacode`. Bind-mount that path or override `XDG_DATA_HOME` so the keys survive container restarts:
183
+
184
+ ```yaml
185
+ services:
186
+ device-01:
187
+ build: .
188
+ environment:
189
+ PORTACODE_PAIRING_CODE: "${PORTACODE_PAIRING_CODE:-}"
190
+ volumes:
191
+ - ./data/device-01/workspace:/root/workspace
192
+ - ./data/device-01/.local/share/portacode:/root/.local/share/portacode # persists device keys
193
+ ```
194
+
195
+ Alternatively, set `XDG_DATA_HOME=/root/.portacode` before running `portacode connect` and mount that directory from the host. The rule of thumb: **persist whichever folder contains `.local/share/portacode/keys/`** so your device fingerprint sticks around.
196
+
197
+ #### Minimal Docker Example
198
+ If you want a plug-and-play container, check the `examples/simple_device/` folder that ships with this repo and the PyPI source distribution. It contains a tiny `Dockerfile` and `docker-compose.yaml` you can copy as-is. The Dockerfile installs `git` before `pip install portacode` so GitPython can interact with repositories—remember to do the same in your own images if you expect to work inside version-controlled projects.
199
+
200
+ The accompanying Compose file demonstrates how to:
201
+ - run `portacode connect --non-interactive` with a predefined `--device-name` and `--project-path`
202
+ - pass `PORTACODE_PAIRING_CODE` via environment variables
203
+ - bind-mount your workspace plus `/root/.local/share/portacode` for key persistence
204
+
205
+ Together, those 10 lines illustrate the complete flow for remotely accessing a Docker-hosted machine with Portacode.
206
+
207
+ #### Workshop Fleet Example
208
+ Training a group? `examples/workshop_fleet/` spins up ten identical containers—one per student—with their own workspace bind mounts plus a shared read-only `instructions/` folder. The Dockerfile in that folder copies everything from `initial_content/` into the image (`COPY initial_content/ /opt/initial_content/`), and the compose command seeds each student workspace on boot via `cp -an /opt/initial_content/. /root/workspace/`. That means:
209
+ - Instructors drop starter code into `initial_content/` before `docker compose up` and every container gets the same seed files without overwriting student changes after the first sync.
210
+ - The host `instructions/` directory is mounted at `/root/workspace/instructions` in **read-only** mode, so you can update agendas or hints live while students can only view them.
211
+ - Each seat persists its Portacode identity in `data/student-XX/.local/share/portacode`, so reconnecting after a restart does not need new pairing codes.
212
+
213
+ See the full walkthrough and assets in [`examples/workshop_fleet/`](https://github.com/portacode/portacode/tree/master/examples/workshop_fleet), which is also shipped inside the PyPI source tarball for offline access.
214
+
215
+ ## 🌱 Early Stage Project
216
+
217
+ **Portacode is a young project with big dreams.** We're building the future of remote development and mobile-first coding experiences. As a new project, we're actively seeking:
218
+
219
+ - **👥 Community Feedback**: Does this solve a real problem for you?
220
+ - **🤝 Contributors**: Help us build the IDE of the future
221
+ - **📢 Early Adopters**: Try it out and let us know what you think
222
+ - **💡 Feature Ideas**: What would make your remote development workflow better?
223
+
224
+ **Your support matters!** Whether you contribute code, report bugs, share ideas, or simply let us know that you find value in what we're building - every bit of feedback helps us decide whether to continue investing in this vision or focus on other projects.
225
+
226
+ ## 📞 Get In Touch
227
+
228
+ - **Email**: hi@menas.pro
229
+ - **Support**: support@portacode.com
230
+ - **GitHub**: [https://github.com/portacode/portacode](https://github.com/portacode/portacode)
231
+
232
+ ## 🤝 Contributing
233
+
234
+ We welcome all forms of contribution:
235
+ - 🐛 **Bug Reports**: Found something broken? Let us know!
236
+ - ✨ **Feature Requests**: What would make Portacode better for you?
237
+ - 📖 **Documentation**: Help others get started
238
+ - 💻 **Code Contributions**: Help us build the future of remote development
239
+ - 💬 **Feedback**: Tell us if you find this useful!
240
+
241
+ Check out our [GitHub repository](https://github.com/portacode/portacode) to get started.
242
+
243
+ ## 📄 License
244
+
245
+ MIT License - see [LICENSE](https://github.com/portacode/portacode/blob/master/LICENSE) file for details.
246
+
247
+ ---
248
+
249
+ **Get started today**: `pip install portacode && portacode connect`
250
+
251
+ *Built with ❤️ and ☕ by passionate software engineers*
@@ -0,0 +1,11 @@
1
+ import sys
2
+ from portacode.cli import cli
3
+
4
+ # Build command arguments
5
+ args = ['connect', '--non-interactive', '--debug']
6
+
7
+ # Add log categories if provided
8
+ if len(sys.argv) > 1 and sys.argv[1]:
9
+ args.extend(['--log-categories', sys.argv[1]])
10
+
11
+ cli(args)
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+
3
+ # Portacode connection script with optional log category filtering
4
+ #
5
+ # Usage examples:
6
+ # ./connect.sh # Normal debug mode (all logs)
7
+ # ./connect.sh connection,git # Only connection and git logs
8
+ # ./connect.sh project_state # Only project state logs (useful for debugging project sync issues)
9
+ # ./connect.sh filesystem,git # Only filesystem and git logs
10
+ # ./connect.sh list # Show available log categories
11
+ #
12
+ # Available categories: connection, auth, websocket, terminal, project_state, filesystem, git, handlers, mux, system, debug
13
+
14
+ # Pass log categories as first argument to connect.py
15
+ python connect.py "$1"