machineconfig 6.82__py3-none-any.whl → 8.51__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 (461) hide show
  1. machineconfig/cluster/remote/cloud_manager.py +1 -1
  2. machineconfig/cluster/remote/run_cluster.py +1 -1
  3. machineconfig/cluster/remote/run_remote.py +1 -1
  4. machineconfig/cluster/sessions_managers/utils/maker.py +29 -15
  5. machineconfig/cluster/sessions_managers/wt_local.py +17 -222
  6. machineconfig/cluster/sessions_managers/wt_local_manager.py +56 -194
  7. machineconfig/cluster/sessions_managers/wt_remote_manager.py +42 -198
  8. machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
  9. machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
  10. machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
  11. machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
  12. machineconfig/cluster/sessions_managers/zellij_local.py +1 -1
  13. machineconfig/cluster/sessions_managers/zellij_local_manager.py +4 -2
  14. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +3 -2
  15. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +2 -2
  16. machineconfig/jobs/installer/checks/check_installations.py +133 -0
  17. machineconfig/jobs/installer/checks/install_utils.py +132 -0
  18. machineconfig/jobs/installer/checks/report_utils.py +39 -0
  19. machineconfig/jobs/installer/checks/vt_utils.py +89 -0
  20. machineconfig/jobs/installer/installer_data.json +1500 -310
  21. machineconfig/jobs/installer/linux_scripts/docker.sh +6 -9
  22. machineconfig/jobs/installer/linux_scripts/q.sh +10 -7
  23. machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
  24. machineconfig/jobs/installer/package_groups.py +62 -91
  25. machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
  26. machineconfig/jobs/installer/{custom → python_scripts}/boxes.py +2 -3
  27. machineconfig/jobs/installer/{custom_dev → python_scripts}/brave.py +5 -3
  28. machineconfig/jobs/installer/python_scripts/cloudflare_warp_cli.py +23 -0
  29. machineconfig/jobs/installer/{custom_dev → python_scripts}/code.py +14 -9
  30. machineconfig/jobs/installer/{custom_dev → python_scripts}/dubdb_adbc.py +1 -1
  31. machineconfig/jobs/installer/python_scripts/hx.py +214 -0
  32. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerdfont.py +2 -2
  33. machineconfig/jobs/installer/{custom_dev → python_scripts}/nerfont_windows_helper.py +32 -26
  34. machineconfig/jobs/installer/python_scripts/sysabc.py +145 -0
  35. machineconfig/jobs/installer/{custom_dev → python_scripts}/wezterm.py +2 -19
  36. machineconfig/jobs/installer/{custom_dev → python_scripts}/winget.py +10 -14
  37. machineconfig/jobs/installer/python_scripts/yazi.py +139 -0
  38. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nfs +0 -1
  39. machineconfig/jobs/scripts/powershell_scripts/cmatrix.ps1 +52 -0
  40. machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +13 -0
  41. machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +4 -0
  42. machineconfig/jobs/scripts_dynamic/a.py +428 -0
  43. machineconfig/logger.py +1 -2
  44. machineconfig/profile/create_helper.py +56 -18
  45. machineconfig/profile/create_links.py +79 -21
  46. machineconfig/profile/create_links_export.py +87 -36
  47. machineconfig/profile/create_shell_profile.py +92 -127
  48. machineconfig/profile/mapper_data.toml +45 -0
  49. machineconfig/profile/mapper_dotfiles.toml +249 -0
  50. machineconfig/scripts/__init__.py +0 -4
  51. machineconfig/scripts/linux/wrap_mcfg +46 -0
  52. machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
  53. machineconfig/scripts/python/agents.py +85 -165
  54. machineconfig/scripts/python/ai/initai.py +4 -2
  55. machineconfig/scripts/python/ai/scripts/__init__.py +1 -0
  56. machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
  57. machineconfig/scripts/python/ai/{command_runner → scripts}/command_runner.sh +1 -1
  58. machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +2 -0
  59. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +8 -6
  60. machineconfig/scripts/python/ai/solutions/claude/claude.py +1 -1
  61. machineconfig/scripts/python/ai/solutions/cline/cline.py +1 -1
  62. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
  63. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
  64. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
  65. machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +6 -6
  66. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +33 -0
  67. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
  68. machineconfig/scripts/python/ai/solutions/crush/crush.py +1 -1
  69. machineconfig/scripts/python/ai/solutions/cursor/cursors.py +1 -1
  70. machineconfig/scripts/python/ai/solutions/gemini/gemini.py +1 -1
  71. machineconfig/scripts/python/ai/solutions/gemini/settings.json +3 -0
  72. machineconfig/scripts/python/ai/{generate_files.py → utils/generate_files.py} +2 -2
  73. machineconfig/scripts/python/ai/{solutions → utils}/generic.py +2 -15
  74. machineconfig/scripts/python/ai/{vscode_tasks.py → utils/vscode_tasks.py} +13 -5
  75. machineconfig/scripts/python/cloud.py +58 -11
  76. machineconfig/scripts/python/croshell.py +10 -162
  77. machineconfig/scripts/python/devops.py +73 -36
  78. machineconfig/scripts/python/devops_navigator.py +16 -6
  79. machineconfig/scripts/python/fire_jobs.py +8 -222
  80. machineconfig/scripts/python/ftpx.py +7 -200
  81. machineconfig/scripts/python/graph/cli_graph.json +8743 -0
  82. machineconfig/scripts/python/{env_manager → helper_env}/path_manager_tui.py +2 -2
  83. machineconfig/scripts/python/helpers/helper_env/env_manager_tui.py +204 -0
  84. machineconfig/scripts/python/helpers/helper_env/path_manager_tui.py +228 -0
  85. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_crush.json +1 -1
  86. machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
  87. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_cursor_agents.py +3 -4
  88. machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
  89. machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
  90. machineconfig/scripts/python/helpers/helpers_agents/agents_impl.py +168 -0
  91. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_launch.py +38 -16
  92. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_helper_types.py +11 -14
  93. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aichat/config.yaml +5 -0
  94. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aider/.aider.conf.yml +2 -0
  95. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/copilot/config.yml +1 -0
  96. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/crush/crush.json +10 -0
  97. machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/gemini/settings.json +12 -0
  98. machineconfig/scripts/python/helpers/helpers_agents/privacy/privacy.py +109 -0
  99. machineconfig/scripts/python/helpers/helpers_agents/templates/prompt.txt +10 -0
  100. machineconfig/scripts/python/helpers/helpers_agents/templates/template.sh +34 -0
  101. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_copy.py +32 -25
  102. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_mount.py +29 -22
  103. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_sync.py +9 -8
  104. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers2.py +1 -1
  105. machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/crosh.py +3 -3
  106. machineconfig/scripts/python/helpers/helpers_croshell/croshell_impl.py +225 -0
  107. machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/scheduler.py +4 -4
  108. machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/start_slidev.py +12 -12
  109. machineconfig/scripts/python/helpers/helpers_devops/backup_config.py +149 -0
  110. machineconfig/scripts/python/helpers/helpers_devops/cli_backup_retrieve.py +262 -0
  111. machineconfig/scripts/python/helpers/helpers_devops/cli_config.py +98 -0
  112. machineconfig/scripts/python/helpers/helpers_devops/cli_config_dotfile.py +274 -0
  113. machineconfig/scripts/python/helpers/helpers_devops/cli_data.py +67 -0
  114. machineconfig/scripts/python/helpers/helpers_devops/cli_nw.py +201 -0
  115. machineconfig/scripts/python/helpers/helpers_devops/cli_repos.py +274 -0
  116. machineconfig/scripts/python/helpers/helpers_devops/cli_self.py +197 -0
  117. machineconfig/scripts/python/helpers/helpers_devops/cli_share_file.py +151 -0
  118. machineconfig/scripts/python/helpers/helpers_devops/cli_share_server.py +125 -0
  119. machineconfig/scripts/python/{helpers_devops/cli_terminal.py → helpers/helpers_devops/cli_share_terminal.py} +26 -22
  120. machineconfig/scripts/python/helpers/helpers_devops/cli_ssh.py +167 -0
  121. machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_status.py +17 -23
  122. machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_update_repos.py +1 -1
  123. machineconfig/scripts/python/{interactive.py → helpers/helpers_devops/interactive.py} +78 -71
  124. machineconfig/scripts/python/helpers/helpers_devops/run_script.py +197 -0
  125. machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.ps1 +41 -0
  126. machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.sh +48 -0
  127. machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_wezterm_theme.py +4 -4
  128. machineconfig/scripts/python/{helpers_fire/helpers4.py → helpers/helpers_fire_command/file_wrangler.py} +57 -20
  129. machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_args_helper.py +1 -0
  130. machineconfig/scripts/python/helpers/helpers_fire_command/fire_jobs_impl.py +233 -0
  131. machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_route_helper.py +26 -16
  132. machineconfig/scripts/python/helpers/helpers_msearch/__init__.py +5 -0
  133. machineconfig/scripts/python/helpers/helpers_msearch/msearch_impl.py +248 -0
  134. machineconfig/scripts/{linux → python/helpers/helpers_msearch/scripts_linux}/fzfg +6 -5
  135. machineconfig/scripts/python/helpers/helpers_msearch/scripts_linux/search_with_context.sh +48 -0
  136. machineconfig/scripts/python/helpers/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
  137. machineconfig/scripts/python/helpers/helpers_navigator/__init__.py +20 -0
  138. machineconfig/scripts/python/helpers/helpers_navigator/cli_graph_loader.py +234 -0
  139. machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/command_builder.py +61 -13
  140. machineconfig/scripts/python/helpers/helpers_navigator/command_detail.py +153 -0
  141. machineconfig/scripts/python/helpers/helpers_navigator/command_tree.py +45 -0
  142. machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/data_models.py +18 -11
  143. machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/main_app.py +5 -5
  144. machineconfig/scripts/python/helpers/helpers_network/address.py +174 -0
  145. machineconfig/scripts/python/helpers/helpers_network/address_switch.py +78 -0
  146. machineconfig/scripts/python/helpers/helpers_network/ftpx_impl.py +276 -0
  147. machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nfs.py +2 -2
  148. machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_ssh.py +3 -3
  149. machineconfig/scripts/python/helpers/helpers_network/ssh_add_identity.py +73 -0
  150. machineconfig/scripts/python/helpers/helpers_network/ssh_add_ssh_key.py +175 -0
  151. machineconfig/scripts/python/helpers/helpers_network/ssh_debug_linux.py +319 -0
  152. machineconfig/scripts/python/helpers/helpers_network/ssh_debug_windows.py +275 -0
  153. machineconfig/scripts/python/{nw → helpers/helpers_network}/wifi_conn.py +1 -53
  154. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action.py +3 -3
  155. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action_helper.py +3 -3
  156. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/clone.py +0 -1
  157. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/cloud_repo_sync.py +159 -48
  158. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/grource.py +4 -3
  159. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/record.py +33 -12
  160. machineconfig/scripts/python/helpers/helpers_repos/repo_analyzer_1.py +160 -0
  161. machineconfig/scripts/python/{helpers_repos/count_lines.py → helpers/helpers_repos/repo_analyzer_2.py} +156 -191
  162. machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/update.py +0 -6
  163. machineconfig/scripts/python/helpers/helpers_search/ast_search.py +74 -0
  164. machineconfig/scripts/python/helpers/helpers_search/qr_code.py +166 -0
  165. machineconfig/scripts/python/helpers/helpers_search/repo_rag.py +325 -0
  166. machineconfig/scripts/python/helpers/helpers_search/script_help.py +81 -0
  167. machineconfig/scripts/python/helpers/helpers_search/symantic_search.py +25 -0
  168. machineconfig/scripts/python/helpers/helpers_sessions/__init__.py +0 -0
  169. machineconfig/scripts/python/helpers/helpers_sessions/sessions_impl.py +186 -0
  170. machineconfig/scripts/python/{helpers_sessions → helpers/helpers_sessions}/sessions_multiprocess.py +20 -14
  171. machineconfig/scripts/python/helpers/helpers_terminal/__init__.py +0 -0
  172. machineconfig/scripts/python/helpers/helpers_terminal/terminal_impl.py +96 -0
  173. machineconfig/scripts/python/helpers/helpers_utils/download.py +150 -0
  174. machineconfig/scripts/python/helpers/helpers_utils/pdf.py +96 -0
  175. machineconfig/scripts/python/helpers/helpers_utils/python.py +210 -0
  176. machineconfig/scripts/python/helpers/helpers_utils/specs.py +246 -0
  177. machineconfig/scripts/python/mcfg_entry.py +143 -0
  178. machineconfig/scripts/python/msearch.py +26 -0
  179. machineconfig/scripts/python/sessions.py +69 -135
  180. machineconfig/scripts/python/terminal.py +58 -0
  181. machineconfig/scripts/python/utils.py +115 -38
  182. machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
  183. machineconfig/settings/atuin/config.toml +294 -0
  184. machineconfig/settings/atuin/themes/catppuccin-mocha-mauve.toml +12 -0
  185. machineconfig/settings/broot/conf.toml +1 -1
  186. machineconfig/settings/helix/config.toml +16 -0
  187. machineconfig/settings/helix/languages.toml +13 -4
  188. machineconfig/settings/helix/yazi-picker.sh +12 -0
  189. machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
  190. machineconfig/settings/lf/linux/exe/previewer.sh +3 -2
  191. machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
  192. machineconfig/settings/lf/windows/lfrc +14 -16
  193. machineconfig/settings/linters/.ruff.toml +2 -1
  194. machineconfig/settings/marimo/marimo.toml +1 -1
  195. machineconfig/settings/marimo/snippets/globalize.py +34 -0
  196. machineconfig/settings/mprocs/windows/mprocs.yaml +2 -2
  197. machineconfig/settings/shells/bash/init.sh +47 -12
  198. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
  199. machineconfig/settings/shells/nushell/config.nu +25 -33
  200. machineconfig/settings/shells/nushell/env.nu +21 -8
  201. machineconfig/settings/shells/nushell/init.nu +138 -0
  202. machineconfig/settings/shells/pwsh/init.ps1 +111 -17
  203. machineconfig/settings/shells/pwsh/search_pwsh_history.ps1 +99 -0
  204. machineconfig/settings/shells/starship/starship.toml +16 -0
  205. machineconfig/settings/shells/wezterm/wezterm.lua +6 -1
  206. machineconfig/settings/shells/wt/settings.json +27 -18
  207. machineconfig/settings/shells/zsh/init.sh +42 -23
  208. machineconfig/settings/television/cable_unix/alias.toml +8 -0
  209. machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
  210. machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
  211. machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
  212. machineconfig/settings/television/cable_unix/channels.toml +19 -0
  213. machineconfig/settings/television/cable_unix/dirs.toml +13 -0
  214. machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
  215. machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
  216. machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
  217. machineconfig/settings/television/cable_unix/env.toml +17 -0
  218. machineconfig/settings/television/cable_unix/files.toml +11 -0
  219. machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
  220. machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
  221. machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
  222. machineconfig/settings/television/cable_unix/git-log.toml +12 -0
  223. machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
  224. machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
  225. machineconfig/settings/television/cable_unix/guix.toml +20 -0
  226. machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
  227. machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
  228. machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
  229. machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
  230. machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
  231. machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
  232. machineconfig/settings/television/cable_unix/procs.toml +20 -0
  233. machineconfig/settings/television/cable_unix/text.toml +17 -0
  234. machineconfig/settings/television/cable_unix/tldr.toml +18 -0
  235. machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
  236. machineconfig/settings/television/cable_windows/alias.toml +7 -0
  237. machineconfig/settings/television/cable_windows/dirs.toml +13 -0
  238. machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
  239. machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
  240. machineconfig/settings/television/cable_windows/env.toml +17 -0
  241. machineconfig/settings/television/cable_windows/files.toml +14 -0
  242. machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
  243. machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
  244. machineconfig/settings/television/cable_windows/git-log.toml +11 -0
  245. machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
  246. machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
  247. machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
  248. machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
  249. machineconfig/settings/television/cable_windows/text.toml +17 -0
  250. machineconfig/settings/tv/config.toml +234 -0
  251. machineconfig/settings/tv/themes/catppuccin-mocha-sky.toml +22 -0
  252. machineconfig/settings/wsl/.wslconfig +5 -30
  253. machineconfig/settings/wt/__init__.py +0 -0
  254. machineconfig/settings/yazi/init.lua +61 -0
  255. machineconfig/settings/yazi/keymap_linux.toml +94 -0
  256. machineconfig/settings/yazi/keymap_windows.toml +78 -0
  257. machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
  258. machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
  259. machineconfig/settings/yazi/theme.toml +4 -0
  260. machineconfig/settings/yazi/yazi_linux.toml +94 -0
  261. machineconfig/settings/yazi/yazi_windows.toml +58 -0
  262. machineconfig/settings/zellij/layouts/st.kdl +40 -9
  263. machineconfig/settings/zellij/layouts/st2.kdl +1 -1
  264. machineconfig/setup_linux/__init__.py +2 -2
  265. machineconfig/setup_linux/apps_desktop.sh +8 -27
  266. machineconfig/setup_linux/web_shortcuts/interactive.sh +27 -12
  267. machineconfig/setup_linux/web_shortcuts/live_from_github.sh +34 -0
  268. machineconfig/setup_mac/__init__.py +1 -4
  269. machineconfig/setup_mac/apps_gui.sh +248 -0
  270. machineconfig/setup_windows/__init__.py +2 -5
  271. machineconfig/setup_windows/uv.ps1 +8 -1
  272. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +28 -12
  273. machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +31 -0
  274. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
  275. machineconfig/type_hinting/sql/__init__.py +1 -0
  276. machineconfig/type_hinting/sql/base.py +216 -0
  277. machineconfig/type_hinting/sql/core_schema.py +64 -0
  278. machineconfig/type_hinting/sql/core_schema_typeddict.py +41 -0
  279. machineconfig/type_hinting/sql/typeddict_codegen.py +222 -0
  280. machineconfig/type_hinting/typedict/__init__.py +1 -0
  281. machineconfig/type_hinting/typedict/ast_utils.py +130 -0
  282. machineconfig/type_hinting/typedict/generator_helpers.py +319 -0
  283. machineconfig/type_hinting/typedict/generators.py +231 -0
  284. machineconfig/type_hinting/typedict/polars_schema.py +24 -0
  285. machineconfig/type_hinting/typedict/polars_schema_typeddict.py +63 -0
  286. machineconfig/utils/accessories.py +31 -4
  287. machineconfig/utils/code.py +163 -51
  288. machineconfig/utils/files/ascii_art.py +11 -15
  289. machineconfig/utils/files/headers.py +6 -7
  290. machineconfig/utils/files/read.py +8 -1
  291. machineconfig/utils/installer_utils/github_release_bulk.py +95 -138
  292. machineconfig/utils/installer_utils/github_release_scraper.py +99 -0
  293. machineconfig/utils/installer_utils/install_from_url.py +183 -0
  294. machineconfig/utils/installer_utils/installer_class.py +53 -102
  295. machineconfig/utils/installer_utils/installer_cli.py +161 -0
  296. machineconfig/utils/installer_utils/installer_helper.py +129 -0
  297. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +42 -91
  298. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +20 -65
  299. machineconfig/utils/io.py +94 -9
  300. machineconfig/utils/links.py +56 -38
  301. machineconfig/utils/meta.py +38 -21
  302. machineconfig/utils/options.py +81 -23
  303. machineconfig/utils/options_utils/__init__.py +0 -0
  304. machineconfig/utils/options_utils/options_tv_linux.py +211 -0
  305. machineconfig/utils/options_utils/options_tv_windows.py +88 -0
  306. machineconfig/utils/options_utils/tv_options.py +37 -0
  307. machineconfig/utils/path_extended.py +52 -102
  308. machineconfig/utils/path_helper.py +76 -23
  309. machineconfig/utils/procs.py +1 -1
  310. machineconfig/utils/scheduler.py +26 -53
  311. machineconfig/utils/scheduling.py +0 -2
  312. machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
  313. machineconfig/utils/schemas/layouts/layout_types.py +1 -1
  314. machineconfig/utils/source_of_truth.py +6 -1
  315. machineconfig/utils/ssh.py +216 -419
  316. machineconfig/utils/ssh_utils/abc.py +5 -0
  317. machineconfig/utils/ssh_utils/copy_from_here.py +116 -0
  318. machineconfig/utils/ssh_utils/copy_to_here.py +303 -0
  319. machineconfig/utils/ssh_utils/utils.py +158 -0
  320. machineconfig/utils/ssh_utils/wsl.py +147 -0
  321. machineconfig/utils/ssh_utils/wsl_helper.py +217 -0
  322. machineconfig/utils/terminal.py +1 -0
  323. machineconfig/utils/upgrade_packages.py +107 -35
  324. machineconfig/utils/ve.py +12 -4
  325. machineconfig-8.51.dist-info/METADATA +140 -0
  326. machineconfig-8.51.dist-info/RECORD +543 -0
  327. {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/entry_points.txt +4 -1
  328. machineconfig/jobs/installer/check_installations.py +0 -248
  329. machineconfig/jobs/installer/custom/hx.py +0 -140
  330. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
  331. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
  332. machineconfig/jobs/installer/powershell_scripts/archive_pygraphviz.ps1 +0 -12
  333. machineconfig/jobs/installer/powershell_scripts/openssh-server_add_key.ps1 +0 -7
  334. machineconfig/jobs/installer/powershell_scripts/openssh-server_copy-ssh-id.ps1 +0 -14
  335. machineconfig/profile/backup.toml +0 -49
  336. machineconfig/profile/mapper.toml +0 -256
  337. machineconfig/scripts/linux/fzf2g +0 -21
  338. machineconfig/scripts/linux/fzfag +0 -17
  339. machineconfig/scripts/linux/fzffg +0 -25
  340. machineconfig/scripts/linux/fzfrga +0 -21
  341. machineconfig/scripts/linux/mcfgs +0 -38
  342. machineconfig/scripts/linux/other/share_smb +0 -1
  343. machineconfig/scripts/linux/other/switch_ip +0 -20
  344. machineconfig/scripts/linux/skrg +0 -4
  345. machineconfig/scripts/linux/warp-cli.sh +0 -122
  346. machineconfig/scripts/linux/z_ls +0 -104
  347. machineconfig/scripts/python/ai/command_runner/prompt.txt +0 -9
  348. machineconfig/scripts/python/helpers_devops/cli_config.py +0 -120
  349. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +0 -77
  350. machineconfig/scripts/python/helpers_devops/cli_data.py +0 -25
  351. machineconfig/scripts/python/helpers_devops/cli_nw.py +0 -73
  352. machineconfig/scripts/python/helpers_devops/cli_repos.py +0 -181
  353. machineconfig/scripts/python/helpers_devops/cli_self.py +0 -122
  354. machineconfig/scripts/python/helpers_devops/cli_share_server.py +0 -104
  355. machineconfig/scripts/python/helpers_devops/cli_utils.py +0 -221
  356. machineconfig/scripts/python/helpers_devops/devops_backup_retrieve.py +0 -80
  357. machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +0 -3
  358. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_crush.py +0 -37
  359. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_gemini.py +0 -44
  360. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_qwen.py +0 -43
  361. machineconfig/scripts/python/helpers_fire/prompt.txt +0 -2
  362. machineconfig/scripts/python/helpers_fire/template.sh +0 -15
  363. machineconfig/scripts/python/helpers_navigator/__init__.py +0 -20
  364. machineconfig/scripts/python/helpers_navigator/command_detail.py +0 -44
  365. machineconfig/scripts/python/helpers_navigator/command_tree.py +0 -588
  366. machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +0 -17
  367. machineconfig/scripts/python/helpers_repos/entrypoint.py +0 -76
  368. machineconfig/scripts/python/helpers_repos/secure_repo.py +0 -15
  369. machineconfig/scripts/python/mcfg.py +0 -48
  370. machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
  371. machineconfig/scripts/python/nw/devops_add_identity.py +0 -82
  372. machineconfig/scripts/python/nw/devops_add_ssh_key.py +0 -134
  373. machineconfig/scripts/python/nw/ssh_debug_linux.py +0 -391
  374. machineconfig/scripts/python/nw/ssh_debug_windows.py +0 -338
  375. machineconfig/scripts/python/nw/wsl_windows_transfer.py +0 -66
  376. machineconfig/scripts/windows/fzfb.ps1 +0 -3
  377. machineconfig/scripts/windows/fzfg.ps1 +0 -2
  378. machineconfig/scripts/windows/fzfrga.bat +0 -20
  379. machineconfig/scripts/windows/mcfgs.ps1 +0 -17
  380. machineconfig/scripts/windows/mounts/mount_ssh.ps1 +0 -13
  381. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  382. machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
  383. machineconfig/settings/lf/windows/tst.ps1 +0 -1
  384. machineconfig/settings/yazi/yazi.toml +0 -4
  385. machineconfig/setup_linux/apps.sh +0 -66
  386. machineconfig/setup_linux/others/cli_installation.sh +0 -137
  387. machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh +0 -30
  388. machineconfig/setup_linux/ssh/openssh_all.sh +0 -25
  389. machineconfig/setup_linux/ssh/openssh_wsl.sh +0 -38
  390. machineconfig/setup_mac/apps.sh +0 -73
  391. machineconfig/setup_mac/ssh/openssh_setup.sh +0 -114
  392. machineconfig/setup_windows/apps.ps1 +0 -62
  393. machineconfig/setup_windows/others/obs.ps1 +0 -4
  394. machineconfig/setup_windows/ssh/add-sshkey.ps1 +0 -29
  395. machineconfig/setup_windows/ssh/add_identity.ps1 +0 -11
  396. machineconfig/setup_windows/ssh/openssh-server.ps1 +0 -37
  397. machineconfig/utils/installer_utils/installer.py +0 -225
  398. machineconfig/utils/tst.py +0 -20
  399. machineconfig-6.82.dist-info/METADATA +0 -82
  400. machineconfig-6.82.dist-info/RECORD +0 -441
  401. machineconfig/jobs/installer/{custom_dev → checks}/__init__.py +0 -0
  402. machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
  403. machineconfig/{scripts/python/helpers_cloud → jobs/installer/python_scripts}/__init__.py +0 -0
  404. machineconfig/jobs/installer/{custom_dev → python_scripts}/alacritty.py +0 -0
  405. machineconfig/jobs/installer/{custom_dev → python_scripts}/bypass_paywall.py +0 -0
  406. machineconfig/jobs/installer/{custom_dev → python_scripts}/cursor.py +0 -0
  407. machineconfig/jobs/installer/{custom_dev → python_scripts}/espanso.py +0 -0
  408. machineconfig/jobs/installer/{custom → python_scripts}/gh.py +0 -0
  409. machineconfig/jobs/installer/{custom_dev → python_scripts}/goes.py +0 -0
  410. machineconfig/jobs/installer/{custom_dev → python_scripts}/lvim.py +0 -0
  411. machineconfig/jobs/installer/{custom_dev → python_scripts}/redis.py +0 -0
  412. machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/android.sh +0 -0
  413. machineconfig/jobs/{installer/linux_scripts → scripts/bash_scripts}/lid.sh +0 -0
  414. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_drive +0 -0
  415. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nw_drive +0 -0
  416. machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_smb +0 -0
  417. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_cloud.sh +0 -0
  418. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_nfs +0 -0
  419. machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/start_docker +0 -0
  420. machineconfig/{scripts → jobs/scripts/powershell_scripts}/Restore-ThunderbirdProfile.ps1 +0 -0
  421. machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/docker.ps1 +0 -0
  422. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nfs.ps1 +0 -0
  423. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nw.ps1 +0 -0
  424. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_smb.ps1 +0 -0
  425. machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/power_options.ps1 +0 -0
  426. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_cloud.cmd +0 -0
  427. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_smb.ps1 +0 -0
  428. machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/unlock_bitlocker.ps1 +0 -0
  429. machineconfig/scripts/python/{helpers_croshell → ai/utils}/__init__.py +0 -0
  430. machineconfig/scripts/python/ai/{solutions/_shared.py → utils/shared.py} +0 -0
  431. machineconfig/scripts/python/{helpers_devops → graph}/__init__.py +0 -0
  432. machineconfig/scripts/python/{helpers_devops/themes → helpers}/__init__.py +0 -0
  433. machineconfig/scripts/python/{env_manager → helpers/helper_env}/__init__.py +0 -0
  434. machineconfig/scripts/python/{env_manager → helpers/helper_env}/path_manager_backend.py +0 -0
  435. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/__init__.py +0 -0
  436. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/__init__.py +0 -0
  437. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_search.py +0 -0
  438. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_load_balancer.py +0 -0
  439. machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents/templates}/template.ps1 +0 -0
  440. machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_cloud}/__init__.py +0 -0
  441. machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_helpers.py +1 -1
  442. /machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers5.py +0 -0
  443. /machineconfig/scripts/python/{helpers_sessions → helpers/helpers_croshell}/__init__.py +0 -0
  444. /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/pomodoro.py +0 -0
  445. /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer.py +0 -0
  446. /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer_template.py +0 -0
  447. /machineconfig/scripts/python/{nw → helpers/helpers_devops}/__init__.py +0 -0
  448. /machineconfig/{setup_windows/wt_and_pwsh → scripts/python/helpers/helpers_devops/themes}/__init__.py +0 -0
  449. /machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_pwsh_theme.ps1 +0 -0
  450. /machineconfig/scripts/python/{helpers_devops/themes/choose_starship_theme.ps1 → helpers/helpers_fire_command/__init__.py} +0 -0
  451. /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/cloud_manager.py +0 -0
  452. /machineconfig/scripts/python/{helpers_fire_command/fire_jobs_streamlit_helper.py → helpers/helpers_fire_command/f.py} +0 -0
  453. /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers/helpers_fire_command/fire_jobs_streamlit_helper.py} +0 -0
  454. /machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/search_bar.py +0 -0
  455. /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers/helpers_network/__init__.py} +0 -0
  456. /machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nw_drive.py +0 -0
  457. /machineconfig/scripts/python/{nw → helpers/helpers_network}/onetimeshare.py +0 -0
  458. /machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/sync.py +0 -0
  459. /machineconfig/{setup_windows/wt_and_pwsh → settings/wt}/set_wt_settings.py +0 -0
  460. {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/WHEEL +0 -0
  461. {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,175 @@
1
+ """SSH"""
2
+
3
+ from platform import system
4
+ from pathlib import Path
5
+ from rich.console import Console
6
+ from rich.panel import Panel
7
+ from rich import box
8
+ from typing import Optional, Annotated
9
+ import typer
10
+ import subprocess
11
+
12
+
13
+ console = Console()
14
+
15
+
16
+ def _add_ssh_key_windows(path_to_key: Path) -> None:
17
+ """Add SSH key on Windows using Python with proper UTF-8 encoding.
18
+ This replaces the PowerShell script that was writing UTF-16LE encoded files which openssh server cannot read.
19
+ """
20
+ sshd_dir = Path("C:/ProgramData/ssh")
21
+ admin_auth_keys = sshd_dir / "administrators_authorized_keys"
22
+ sshd_config = sshd_dir / "sshd_config"
23
+ key_content = path_to_key.read_text(encoding="utf-8").strip()
24
+ if admin_auth_keys.exists():
25
+ existing = admin_auth_keys.read_text(encoding="utf-8")
26
+ if not existing.endswith("\n"):
27
+ existing += "\n"
28
+ admin_auth_keys.write_text(existing + key_content + "\n", encoding="utf-8")
29
+ else:
30
+ admin_auth_keys.write_text(key_content + "\n", encoding="utf-8")
31
+ icacls_cmd = f'icacls "{admin_auth_keys}" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"'
32
+ subprocess.run(icacls_cmd, shell=True, check=True)
33
+ if sshd_config.exists():
34
+ config_text = sshd_config.read_text(encoding="utf-8")
35
+ config_text = config_text.replace("#PubkeyAuthentication", "PubkeyAuthentication")
36
+ sshd_config.write_text(config_text, encoding="utf-8")
37
+ subprocess.run("Restart-Service sshd -Force", shell=True, check=True)
38
+
39
+
40
+ def get_add_ssh_key_script(path_to_key: Path, verbose: bool = True) -> tuple[str, str]:
41
+ """Returns (program_script, status_message) tuple. For Windows, program_script is empty because we handle it in Python."""
42
+ os_name = system()
43
+ if os_name == "Linux" or os_name == "Darwin":
44
+ authorized_keys = Path.home().joinpath(".ssh/authorized_keys")
45
+ os_icon, os_label = "🐧", "Linux/macOS"
46
+ elif os_name == "Windows":
47
+ authorized_keys = Path("C:/ProgramData/ssh/administrators_authorized_keys")
48
+ os_icon, os_label = "🪟", "Windows"
49
+ else:
50
+ raise NotImplementedError("Only Linux, macOS and Windows are supported")
51
+
52
+ status_lines: list[str] = [f"{os_icon} {os_label} │ Auth file: {authorized_keys}"]
53
+ program = ""
54
+
55
+ if authorized_keys.exists():
56
+ keys_text = authorized_keys.read_text(encoding="utf-8").split("\n")
57
+ key_count = len([k for k in keys_text if k.strip()])
58
+ status_lines.append(f"🔑 Existing keys: {key_count}")
59
+ if path_to_key.read_text(encoding="utf-8") in authorized_keys.read_text(encoding="utf-8"):
60
+ status_lines.append(f"⚠️ Key [yellow]{path_to_key.name}[/yellow] already authorized, skipping")
61
+ else:
62
+ status_lines.append(f"➕ Adding: [green]{path_to_key.name}[/green]")
63
+ if os_name == "Linux" or os_name == "Darwin":
64
+ program = f"cat {path_to_key} >> ~/.ssh/authorized_keys"
65
+ elif os_name == "Windows":
66
+ _add_ssh_key_windows(path_to_key)
67
+ else:
68
+ raise NotImplementedError
69
+ else:
70
+ status_lines.append(f"📝 Creating auth file with: [green]{path_to_key.name}[/green]")
71
+ if os_name == "Linux" or os_name == "Darwin":
72
+ program = f"cat {path_to_key} > ~/.ssh/authorized_keys"
73
+ else:
74
+ _add_ssh_key_windows(path_to_key)
75
+
76
+ if os_name == "Linux" or os_name == "Darwin":
77
+ program += """
78
+ sudo chmod 700 ~/.ssh
79
+ sudo chmod 644 ~/.ssh/authorized_keys
80
+ sudo chmod 644 ~/.ssh/*.pub
81
+ sudo service ssh --full-restart
82
+ # from superuser.com/questions/215504/permissions-on-private-key-in-ssh-folder
83
+ """
84
+ return program, "\n".join(status_lines)
85
+
86
+
87
+ """
88
+ Common pitfalls:
89
+ 🚫 Wrong line endings (LF/CRLF) in config files
90
+ 🌐 Network port conflicts (try 2222 -> 2223) between WSL and Windows
91
+ sudo service ssh restart
92
+ sudo service ssh status
93
+ sudo nano /etc/ssh/sshd_config
94
+ """
95
+
96
+
97
+ def main(pub_path: Annotated[Optional[str], typer.Argument(help="Path to the public key file")] = None,
98
+ pub_choose: Annotated[bool, typer.Option("--choose", "-c", help="Choose from available public keys in ~/.ssh")] = False,
99
+ pub_val: Annotated[bool, typer.Option("--paste", "-p", help="Paste the public key content manually")] = False,
100
+ from_github: Annotated[Optional[str], typer.Option("--from-github", "-g", help="Fetch public keys from a GitHub username")] = None
101
+ ) -> None:
102
+ info_lines: list[str] = []
103
+ program = ""
104
+ status_msg = ""
105
+
106
+ if pub_path:
107
+ key_path = Path(pub_path).expanduser().absolute()
108
+ key_path.parent.mkdir(parents=True, exist_ok=True)
109
+ if not key_path.exists():
110
+ console.print(Panel(f"❌ Key path does not exist: {key_path}", title="[bold red]Error[/bold red]", border_style="red"))
111
+ raise typer.Exit(code=1)
112
+ info_lines.append(f"📄 Source: Local file │ {key_path}")
113
+ program, status_msg = get_add_ssh_key_script(key_path)
114
+
115
+ elif pub_choose:
116
+ pub_keys = list(Path.home().joinpath(".ssh").glob("*.pub"))
117
+ if not pub_keys:
118
+ console.print(Panel("⚠️ No public keys found in ~/.ssh", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
119
+ return
120
+ info_lines.append(f"📄 Source: Local ~/.ssh │ Found {len(pub_keys)} key(s)")
121
+ programs: list[str] = []
122
+ statuses: list[str] = []
123
+ for key in pub_keys:
124
+ p, s = get_add_ssh_key_script(key)
125
+ programs.append(p)
126
+ statuses.append(s)
127
+ program = "\n\n\n".join(programs)
128
+ status_msg = "\n".join(statuses)
129
+
130
+ elif pub_val:
131
+ key_filename = input("📝 File name (default: my_pasted_key.pub): ") or "my_pasted_key.pub"
132
+ key_path = Path.home().joinpath(f".ssh/{key_filename}")
133
+ key_path.parent.mkdir(parents=True, exist_ok=True)
134
+ key_path.write_text(input("🔑 Paste the public key here: "), encoding="utf-8")
135
+ info_lines.append(f"📄 Source: Pasted │ Saved to {key_path}")
136
+ program, status_msg = get_add_ssh_key_script(key_path)
137
+
138
+ elif from_github:
139
+ import requests
140
+ response = requests.get(f"https://api.github.com/users/{from_github}/keys")
141
+ if response.status_code != 200:
142
+ console.print(Panel(f"❌ GitHub API error for user '{from_github}' │ Status: {response.status_code}", title="[bold red]Error[/bold red]", border_style="red"))
143
+ raise typer.Exit(code=1)
144
+ keys = response.json()
145
+ if not keys:
146
+ console.print(Panel(f"⚠️ No public keys found for GitHub user: {from_github}", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
147
+ return
148
+ key_path = Path.home().joinpath(f".ssh/{from_github}_github_keys.pub")
149
+ key_path.parent.mkdir(parents=True, exist_ok=True)
150
+ key_path.write_text("\n".join([key["key"] for key in keys]), encoding="utf-8")
151
+ info_lines.append(f"📄 Source: GitHub @{from_github} │ {len(keys)} key(s) → {key_path}")
152
+ program, status_msg = get_add_ssh_key_script(key_path)
153
+
154
+ else:
155
+ console.print(Panel("❌ No key source specified. Use --help for options.", title="[bold red]Error[/bold red]", border_style="red"))
156
+ raise typer.Exit(code=1)
157
+
158
+ combined_info = "\n".join(info_lines + [""] + status_msg.split("\n"))
159
+ console.print(Panel(combined_info, title="[bold blue]🔑 SSH Key Authorization[/bold blue]", border_style="blue"))
160
+
161
+ if program.strip():
162
+ from machineconfig.utils.code import run_shell_script
163
+ run_shell_script(script=program, display_script=True, clean_env=False)
164
+
165
+ import machineconfig.scripts.python.helpers.helpers_network.address as helper
166
+ res = helper.select_lan_ipv4(prefer_vpn=False)
167
+ if res is None:
168
+ console.print(Panel("❌ Could not determine local LAN IPv4 address", title="[bold red]Error[/bold red]", border_style="red"))
169
+ raise typer.Exit(code=1)
170
+
171
+ console.print(Panel(f"✅ Complete │ This machine accessible at: [green]{res}[/green]", title="[bold green]SSH Key Authorization[/bold green]", border_style="green", box=box.DOUBLE_EDGE))
172
+
173
+
174
+ if __name__ == "__main__":
175
+ pass
@@ -0,0 +1,319 @@
1
+
2
+
3
+ from platform import system
4
+ from pathlib import Path
5
+ from rich.console import Console
6
+ from rich.panel import Panel
7
+ from rich.table import Table
8
+ from rich import box
9
+ import subprocess
10
+ import os
11
+ import re
12
+
13
+
14
+ console = Console()
15
+
16
+
17
+ def _run(cmd: list[str]) -> tuple[bool, str]:
18
+ try:
19
+ result = subprocess.run(cmd, capture_output=True, text=True, check=False)
20
+ return result.returncode == 0, result.stdout.strip()
21
+ except FileNotFoundError:
22
+ return False, ""
23
+
24
+
25
+ def _check_sshd_installed() -> tuple[bool, str]:
26
+ sshd_paths = ["/usr/sbin/sshd", "/usr/bin/sshd", "/sbin/sshd"]
27
+ for path in sshd_paths:
28
+ if Path(path).exists():
29
+ return True, path
30
+ ok, which_out = _run(["which", "sshd"])
31
+ if ok and which_out:
32
+ return True, which_out
33
+ return False, ""
34
+
35
+
36
+ def _detect_package_manager() -> tuple[str, str]:
37
+ if Path("/usr/bin/apt").exists() or Path("/usr/bin/apt-get").exists():
38
+ return "apt", "sudo apt update && sudo apt install -y openssh-server"
39
+ if Path("/usr/bin/dnf").exists():
40
+ return "dnf", "sudo dnf install -y openssh-server"
41
+ if Path("/usr/bin/yum").exists():
42
+ return "yum", "sudo yum install -y openssh-server"
43
+ if Path("/usr/bin/pacman").exists():
44
+ return "pacman", "sudo pacman -S --noconfirm openssh"
45
+ if Path("/usr/bin/zypper").exists():
46
+ return "zypper", "sudo zypper install -y openssh"
47
+ return "unknown", "# Install openssh-server using your package manager"
48
+
49
+
50
+ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
51
+ if system() != "Linux":
52
+ raise NotImplementedError("ssh_debug_linux is only supported on Linux")
53
+
54
+ results: dict[str, dict[str, str | bool]] = {}
55
+ issues: list[tuple[str, str, str]] = []
56
+ current_user = os.environ.get("USER", os.environ.get("USERNAME", "unknown"))
57
+ ssh_port = "22"
58
+ ip_addresses: list[str] = []
59
+
60
+ ok, hostname = _run(["hostname"])
61
+ hostname = hostname if ok else "unknown"
62
+
63
+ install_info: list[str] = []
64
+ sshd_installed, sshd_path = _check_sshd_installed()
65
+ _pkg_manager, install_cmd = _detect_package_manager()
66
+ if not sshd_installed:
67
+ results["installation"] = {"status": "error", "message": "OpenSSH Server not installed"}
68
+ issues.append(("sshd not installed", "Cannot accept incoming SSH connections", install_cmd))
69
+ install_info.append("❌ OpenSSH Server: [red]NOT INSTALLED[/red]")
70
+ install_info.append(f" [dim]Install with: {install_cmd}[/dim]")
71
+ else:
72
+ results["installation"] = {"status": "ok", "message": f"sshd found at {sshd_path}"}
73
+ install_info.append(f"✅ OpenSSH Server: installed at [cyan]{sshd_path}[/cyan]")
74
+ console.print(Panel("\n".join(install_info), title="[bold]Installation[/bold]", border_style="blue"))
75
+
76
+ ssh_dir = Path.home().joinpath(".ssh")
77
+ authorized_keys = ssh_dir.joinpath("authorized_keys")
78
+ home_dir = Path.home()
79
+
80
+ perm_info: list[str] = []
81
+ home_stat = os.stat(home_dir)
82
+ home_perms = oct(home_stat.st_mode)[-3:]
83
+ if home_perms[2] in ["7", "6", "3", "2"]:
84
+ results["home_directory"] = {"status": "error", "message": f"Home world-writable: {home_perms}"}
85
+ issues.append((f"Home dir perms {home_perms}", "sshd refuses login if home is world-writable", f"chmod 755 {home_dir}"))
86
+ perm_info.append(f"❌ Home directory: [red]{home_perms}[/red] (world-writable)")
87
+ perm_info.append(" [dim]sshd will refuse key auth if home is writable by others[/dim]")
88
+ else:
89
+ perm_info.append(f"✅ Home directory: {home_perms}")
90
+
91
+ if not ssh_dir.exists():
92
+ results["ssh_directory"] = {"status": "error", "message": "~/.ssh missing"}
93
+ issues.append(("~/.ssh missing", "No place for authorized_keys", "mkdir -p ~/.ssh && chmod 700 ~/.ssh"))
94
+ perm_info.append("❌ ~/.ssh: [red]does not exist[/red]")
95
+ else:
96
+ ssh_perms = oct(os.stat(ssh_dir).st_mode)[-3:]
97
+ if ssh_perms != "700":
98
+ results["ssh_directory"] = {"status": "error", "message": f"~/.ssh perms {ssh_perms}"}
99
+ issues.append((f"~/.ssh perms {ssh_perms}", "sshd requires 700 on ~/.ssh", "chmod 700 ~/.ssh"))
100
+ perm_info.append(f"❌ ~/.ssh: [red]{ssh_perms}[/red] (must be 700)")
101
+ else:
102
+ perm_info.append(f"✅ ~/.ssh: {ssh_perms}")
103
+
104
+ if not authorized_keys.exists():
105
+ results["authorized_keys"] = {"status": "error", "message": "authorized_keys missing"}
106
+ issues.append(("authorized_keys missing", "No keys = no login", "Add public key: cat id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"))
107
+ perm_info.append("❌ authorized_keys: [red]does not exist[/red]")
108
+ perm_info.append(" [dim]No authorized keys = cannot login with SSH key[/dim]")
109
+ else:
110
+ ak_perms = oct(os.stat(authorized_keys).st_mode)[-3:]
111
+ try:
112
+ keys = [line for line in authorized_keys.read_text(encoding="utf-8").split("\n") if line.strip()]
113
+ key_count = len(keys)
114
+ except Exception:
115
+ key_count = 0
116
+ if ak_perms not in ["600", "644"]:
117
+ results["authorized_keys"] = {"status": "error", "message": f"authorized_keys perms {ak_perms}"}
118
+ issues.append((f"authorized_keys perms {ak_perms}", "sshd requires 600 or 644", "chmod 600 ~/.ssh/authorized_keys"))
119
+ perm_info.append(f"❌ authorized_keys: [red]{ak_perms}[/red] ({key_count} key(s)) - must be 600/644")
120
+ else:
121
+ results["authorized_keys"] = {"status": "ok", "message": f"{key_count} key(s)"}
122
+ perm_info.append(f"✅ authorized_keys: {ak_perms} ([green]{key_count} key(s)[/green])")
123
+
124
+ console.print(Panel("\n".join(perm_info), title="[bold]Permissions[/bold]", border_style="blue"))
125
+
126
+ svc_info: list[str] = []
127
+ ssh_ok, _ = _run(["systemctl", "is-active", "ssh"])
128
+ sshd_ok, _ = _run(["systemctl", "is-active", "sshd"])
129
+ if ssh_ok or sshd_ok:
130
+ svc_name = "ssh" if ssh_ok else "sshd"
131
+ results["ssh_service"] = {"status": "ok", "message": f"{svc_name} running"}
132
+ svc_info.append(f"✅ Service: [green]{svc_name} running[/green]")
133
+ else:
134
+ results["ssh_service"] = {"status": "error", "message": "sshd not running"}
135
+ issues.append(("sshd not running", "No SSH daemon = no connections", "sudo systemctl start ssh && sudo systemctl enable ssh"))
136
+ svc_info.append("❌ Service: [red]not running[/red]")
137
+
138
+ console.print(Panel("\n".join(svc_info), title="[bold]Service[/bold]", border_style="blue"))
139
+
140
+ net_info: list[str] = []
141
+ ok, ip_out = _run(["ip", "addr", "show"])
142
+ if ok:
143
+ ip_addresses = re.findall(r'inet\s+(\d+\.\d+\.\d+\.\d+)/\d+.*scope\s+global', ip_out)
144
+ if ip_addresses:
145
+ net_info.append(f"🌐 IP: [cyan]{', '.join(ip_addresses)}[/cyan]")
146
+
147
+ sshd_config_paths = [Path("/etc/ssh/sshd_config"), Path("/etc/sshd_config")]
148
+ sshd_config: Path | None = None
149
+ for p in sshd_config_paths:
150
+ if p.exists():
151
+ sshd_config = p
152
+ break
153
+
154
+ if sshd_config:
155
+ try:
156
+ config_text = sshd_config.read_text(encoding="utf-8")
157
+ port_lines = [line for line in config_text.split("\n") if line.strip().startswith("Port") and not line.strip().startswith("#")]
158
+ if port_lines:
159
+ ssh_port = port_lines[0].split()[1]
160
+ net_info.append(f"🔌 Port: [cyan]{ssh_port}[/cyan]")
161
+
162
+ pubkey_lines = [line for line in config_text.split("\n") if "PubkeyAuthentication" in line and not line.strip().startswith("#")]
163
+ if pubkey_lines and "no" in pubkey_lines[-1].lower():
164
+ results["pubkey_auth"] = {"status": "error", "message": "PubkeyAuthentication disabled"}
165
+ issues.append(("PubkeyAuthentication disabled", "Key-based login won't work", f"Edit {sshd_config}: set PubkeyAuthentication yes, then sudo systemctl restart ssh"))
166
+ net_info.append("❌ PubkeyAuthentication: [red]disabled[/red]")
167
+ else:
168
+ net_info.append("✅ PubkeyAuthentication: enabled")
169
+
170
+ password_lines = [line for line in config_text.split("\n") if "PasswordAuthentication" in line and not line.strip().startswith("#")]
171
+ if password_lines:
172
+ password_enabled = "yes" in password_lines[-1].lower()
173
+ if password_enabled:
174
+ results["password_auth"] = {"status": "ok", "message": "PasswordAuthentication enabled"}
175
+ net_info.append("✅ PasswordAuthentication: [green]enabled[/green]")
176
+ else:
177
+ results["password_auth"] = {"status": "info", "message": "PasswordAuthentication disabled"}
178
+ net_info.append("ℹ️ PasswordAuthentication: [yellow]disabled[/yellow] (key-only)")
179
+ else:
180
+ results["password_auth"] = {"status": "ok", "message": "PasswordAuthentication enabled (default)"}
181
+ net_info.append("✅ PasswordAuthentication: [green]enabled[/green] (default)")
182
+
183
+ permit_root = [line for line in config_text.split("\n") if "PermitRootLogin" in line and not line.strip().startswith("#")]
184
+ if permit_root:
185
+ val = permit_root[-1].split()[-1].lower()
186
+ net_info.append(f"ℹ️ PermitRootLogin: {val}")
187
+ except Exception:
188
+ pass
189
+
190
+ ok, ss_out = _run(["ss", "-tlnp"])
191
+ if ok:
192
+ listening = [line for line in ss_out.split("\n") if f":{ssh_port}" in line]
193
+ if not listening:
194
+ results["ssh_listening"] = {"status": "error", "message": f"Not listening on {ssh_port}"}
195
+ issues.append((f"Not listening on port {ssh_port}", "No connections possible", "sudo systemctl restart ssh"))
196
+ net_info.append(f"❌ Listening: [red]NOT on port {ssh_port}[/red]")
197
+ elif all("127.0.0.1" in line or "[::1]" in line for line in listening):
198
+ results["ssh_listening"] = {"status": "error", "message": "Localhost only"}
199
+ issues.append(("SSH bound to localhost", "Only local connections", f"Edit {sshd_config}: remove/comment ListenAddress 127.0.0.1"))
200
+ net_info.append("❌ Listening: [red]localhost only[/red]")
201
+ else:
202
+ results["ssh_listening"] = {"status": "ok", "message": f"Listening on {ssh_port}"}
203
+ net_info.append(f"✅ Listening: 0.0.0.0:{ssh_port}")
204
+
205
+ fw_checked = False
206
+ ok, ufw_out = _run(["ufw", "status"])
207
+ if ok and "Status: active" in ufw_out:
208
+ fw_checked = True
209
+ if f"{ssh_port}/tcp" in ufw_out.lower() or "ssh" in ufw_out.lower() or f" {ssh_port} " in ufw_out:
210
+ results["firewall"] = {"status": "ok", "message": "UFW allows SSH"}
211
+ net_info.append("✅ Firewall (UFW): allows SSH")
212
+ else:
213
+ results["firewall"] = {"status": "error", "message": "UFW blocking SSH"}
214
+ issues.append(("UFW blocking SSH", "Incoming connections dropped", f"sudo ufw allow {ssh_port}/tcp"))
215
+ net_info.append("❌ Firewall (UFW): [red]blocking SSH[/red]")
216
+ net_info.append(" [dim]Active firewall without SSH rule = blocked[/dim]")
217
+
218
+ if not fw_checked:
219
+ ok, fwd_out = _run(["firewall-cmd", "--state"])
220
+ if ok and "running" in fwd_out.lower():
221
+ fw_checked = True
222
+ ok2, svc_out = _run(["firewall-cmd", "--list-services"])
223
+ if ok2 and "ssh" in svc_out.lower():
224
+ results["firewall"] = {"status": "ok", "message": "firewalld allows SSH"}
225
+ net_info.append("✅ Firewall (firewalld): allows SSH")
226
+ else:
227
+ results["firewall"] = {"status": "error", "message": "firewalld blocking SSH"}
228
+ issues.append(("firewalld blocking SSH", "Incoming connections dropped", "sudo firewall-cmd --permanent --add-service=ssh && sudo firewall-cmd --reload"))
229
+ net_info.append("❌ Firewall (firewalld): [red]blocking SSH[/red]")
230
+
231
+ if not fw_checked:
232
+ ok, ipt_out = _run(["iptables", "-L", "INPUT", "-n"])
233
+ if ok and ipt_out:
234
+ has_drop_policy = "policy DROP" in ipt_out or "policy REJECT" in ipt_out
235
+ has_ssh_allow = f"dpt:{ssh_port}" in ipt_out or "dpt:ssh" in ipt_out
236
+ if has_drop_policy and not has_ssh_allow:
237
+ results["firewall"] = {"status": "error", "message": "iptables blocking SSH"}
238
+ issues.append(("iptables blocking SSH", "DROP/REJECT policy without SSH allow", f"sudo iptables -I INPUT -p tcp --dport {ssh_port} -j ACCEPT"))
239
+ net_info.append("❌ Firewall (iptables): [red]DROP policy, no SSH rule[/red]")
240
+ fw_checked = True
241
+ elif has_drop_policy and has_ssh_allow:
242
+ results["firewall"] = {"status": "ok", "message": "iptables allows SSH"}
243
+ net_info.append("✅ Firewall (iptables): allows SSH")
244
+ fw_checked = True
245
+
246
+ if not fw_checked:
247
+ net_info.append("ℹ️ Firewall: none detected / not active")
248
+
249
+ console.print(Panel("\n".join(net_info), title="[bold]Network & Firewall[/bold]", border_style="blue"))
250
+
251
+ other_info: list[str] = []
252
+ hosts_deny = Path("/etc/hosts.deny")
253
+ if hosts_deny.exists():
254
+ try:
255
+ content = hosts_deny.read_text(encoding="utf-8")
256
+ active = [line for line in content.splitlines() if line.strip() and not line.strip().startswith("#")]
257
+ joined = " ".join(active).lower()
258
+ if "sshd" in joined or "all" in joined:
259
+ results["hosts_deny"] = {"status": "error", "message": "hosts.deny blocking"}
260
+ issues.append(("hosts.deny blocking SSH", "TCP wrappers deny before firewall", "Edit /etc/hosts.deny to remove sshd/ALL entries"))
261
+ other_info.append("❌ /etc/hosts.deny: [red]may block SSH[/red]")
262
+ else:
263
+ other_info.append("✅ /etc/hosts.deny: OK")
264
+ except Exception:
265
+ pass
266
+
267
+ ok, se_out = _run(["getenforce"])
268
+ if ok and se_out:
269
+ if se_out == "Enforcing":
270
+ other_info.append("ℹ️ SELinux: Enforcing (run [cyan]restorecon -Rv ~/.ssh[/cyan] if issues)")
271
+ else:
272
+ other_info.append(f"ℹ️ SELinux: {se_out}")
273
+
274
+ log_files = [Path("/var/log/auth.log"), Path("/var/log/secure")]
275
+ for lf in log_files:
276
+ if lf.exists():
277
+ ok, tail = _run(["tail", "-n", "20", str(lf)])
278
+ if ok:
279
+ errors = [line for line in tail.split("\n") if any(k in line.lower() for k in ["error", "failed", "refused", "denied"]) and "ssh" in line.lower()]
280
+ if errors:
281
+ other_info.append(f"⚠️ Recent SSH errors in {lf.name}: {len(errors)}")
282
+ else:
283
+ other_info.append(f"✅ {lf.name}: no recent SSH errors")
284
+ break
285
+
286
+ if other_info:
287
+ console.print(Panel("\n".join(other_info), title="[bold]Additional[/bold]", border_style="blue"))
288
+
289
+ if issues:
290
+ fix_table = Table(title="Issues & Fixes", box=box.ROUNDED, show_lines=True, title_style="bold red")
291
+ fix_table.add_column("Issue", style="yellow", width=25)
292
+ fix_table.add_column("Impact", style="white", width=35)
293
+ fix_table.add_column("Fix Command", style="green", width=55)
294
+ for issue, impact, fix in issues:
295
+ fix_table.add_row(issue, impact, fix)
296
+ console.print(fix_table)
297
+
298
+ fix_script_path = Path("/tmp/ssh_fix.sh")
299
+ script_lines = ["#!/bin/bash", "set -e", "", "# SSH Fix Script - Generated by ssh_debug_linux", f"# {len(issues)} issue(s) to fix", ""]
300
+ for issue, _impact, fix in issues:
301
+ script_lines.append(f"# Fix: {issue}")
302
+ script_lines.append(fix)
303
+ script_lines.append("")
304
+ script_lines.append("echo 'All fixes applied. Re-run ssh_debug_linux to verify.'")
305
+ fix_script_path.write_text("\n".join(script_lines), encoding="utf-8")
306
+ fix_script_path.chmod(0o755)
307
+
308
+ console.print(Panel(f"[bold yellow]⚠️ {len(issues)} issue(s) found[/bold yellow]\n\nFix script generated: [cyan]{fix_script_path}[/cyan]\nRun: [green]sudo bash {fix_script_path}[/green]", title="[bold]Summary[/bold]", border_style="yellow"))
309
+ else:
310
+ conn_info = f"👤 {current_user} 🖥️ {hostname} 🔌 :{ssh_port}"
311
+ if ip_addresses:
312
+ conn_info += f"\n\n[bold]Connect:[/bold] ssh {current_user}@{ip_addresses[0]}"
313
+ console.print(Panel(f"[bold green]✅ All checks passed[/bold green]\n\n{conn_info}", title="[bold]Ready[/bold]", border_style="green"))
314
+
315
+ return results
316
+
317
+
318
+ if __name__ == "__main__":
319
+ ssh_debug_linux()