machineconfig 5.15__py3-none-any.whl → 7.98__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 (472) hide show
  1. machineconfig/__init__.py +0 -28
  2. machineconfig/cluster/remote/cloud_manager.py +1 -1
  3. machineconfig/cluster/remote/distribute.py +0 -1
  4. machineconfig/cluster/remote/file_manager.py +0 -2
  5. machineconfig/cluster/remote/script_execution.py +0 -1
  6. machineconfig/cluster/sessions_managers/{utils → helpers}/enhanced_command_runner.py +4 -6
  7. machineconfig/cluster/sessions_managers/utils/load_balancer.py +1 -1
  8. machineconfig/cluster/sessions_managers/utils/maker.py +69 -0
  9. machineconfig/cluster/sessions_managers/wt_local.py +114 -289
  10. machineconfig/cluster/sessions_managers/wt_local_manager.py +70 -210
  11. machineconfig/cluster/sessions_managers/wt_remote.py +51 -43
  12. machineconfig/cluster/sessions_managers/wt_remote_manager.py +52 -198
  13. machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +6 -19
  14. machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
  15. machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
  16. machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +4 -2
  17. machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
  18. machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
  19. machineconfig/cluster/sessions_managers/zellij_local.py +81 -375
  20. machineconfig/cluster/sessions_managers/zellij_local_manager.py +25 -170
  21. machineconfig/cluster/sessions_managers/zellij_remote.py +40 -41
  22. machineconfig/cluster/sessions_managers/zellij_remote_manager.py +16 -12
  23. machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +4 -8
  24. machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +5 -20
  25. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +3 -9
  26. machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +3 -1
  27. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper.py +298 -0
  28. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_restart.py +77 -0
  29. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_helper_with_panes.py +228 -0
  30. machineconfig/cluster/sessions_managers/zellij_utils/zellij_local_manager_helper.py +165 -0
  31. machineconfig/jobs/{python → installer}/check_installations.py +2 -3
  32. machineconfig/jobs/installer/custom/boxes.py +61 -0
  33. machineconfig/jobs/installer/custom/hx.py +76 -19
  34. machineconfig/jobs/installer/custom/yazi.py +119 -0
  35. machineconfig/jobs/installer/custom_dev/alacritty.py +4 -4
  36. machineconfig/jobs/installer/custom_dev/brave.py +5 -9
  37. machineconfig/jobs/installer/custom_dev/cloudflare_warp_cli.py +23 -0
  38. machineconfig/jobs/installer/custom_dev/code.py +4 -1
  39. machineconfig/jobs/installer/custom_dev/dubdb_adbc.py +30 -0
  40. machineconfig/jobs/installer/custom_dev/nerdfont.py +1 -1
  41. machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +33 -28
  42. machineconfig/jobs/installer/custom_dev/sysabc.py +139 -0
  43. machineconfig/jobs/installer/custom_dev/wezterm.py +2 -19
  44. machineconfig/jobs/installer/custom_dev/winget.py +10 -14
  45. machineconfig/jobs/installer/installer_data.json +1487 -229
  46. machineconfig/jobs/installer/linux_scripts/brave.sh +4 -14
  47. machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +5 -17
  48. machineconfig/jobs/installer/linux_scripts/docker.sh +5 -17
  49. machineconfig/jobs/installer/linux_scripts/docker_start.sh +6 -14
  50. machineconfig/jobs/installer/linux_scripts/edge.sh +3 -11
  51. machineconfig/jobs/{linux/msc → installer/linux_scripts}/lid.sh +2 -8
  52. machineconfig/jobs/installer/linux_scripts/nerdfont.sh +5 -17
  53. machineconfig/jobs/{linux/msc → installer/linux_scripts}/network.sh +2 -8
  54. machineconfig/jobs/installer/linux_scripts/q.sh +10 -6
  55. machineconfig/jobs/installer/linux_scripts/redis.sh +6 -17
  56. machineconfig/jobs/installer/linux_scripts/vscode.sh +5 -17
  57. machineconfig/jobs/installer/linux_scripts/wezterm.sh +4 -12
  58. machineconfig/jobs/installer/package_groups.py +106 -177
  59. machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
  60. machineconfig/logger.py +0 -1
  61. machineconfig/profile/backup.toml +49 -0
  62. machineconfig/profile/bash_shell_profiles.md +11 -0
  63. machineconfig/profile/create_helper.py +62 -0
  64. machineconfig/profile/create_links.py +288 -0
  65. machineconfig/profile/create_links_export.py +100 -0
  66. machineconfig/profile/create_shell_profile.py +147 -0
  67. machineconfig/profile/mapper.toml +263 -0
  68. machineconfig/scripts/__init__.py +0 -4
  69. machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +14 -25
  70. machineconfig/scripts/linux/wrap_mcfg +46 -0
  71. machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
  72. machineconfig/scripts/python/agents.py +123 -117
  73. machineconfig/scripts/python/ai/initai.py +3 -28
  74. machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
  75. machineconfig/scripts/python/ai/scripts/command_runner.sh +9 -0
  76. machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +17 -18
  77. machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +17 -18
  78. machineconfig/scripts/python/ai/solutions/_shared.py +9 -1
  79. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
  80. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
  81. machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
  82. machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +5 -5
  83. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +5 -1
  84. machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
  85. machineconfig/scripts/python/ai/solutions/copilot/prompts/pyright_fix.md +16 -0
  86. machineconfig/scripts/python/ai/solutions/generic.py +28 -5
  87. machineconfig/scripts/python/ai/utils/generate_files.py +348 -0
  88. machineconfig/scripts/python/ai/utils/vscode_tasks.py +37 -0
  89. machineconfig/scripts/python/cloud.py +29 -0
  90. machineconfig/scripts/python/croshell.py +137 -113
  91. machineconfig/scripts/python/devops.py +61 -101
  92. machineconfig/scripts/python/devops_navigator.py +6 -0
  93. machineconfig/scripts/python/env_manager/__init__.py +1 -0
  94. machineconfig/scripts/python/env_manager/env_manager_tui.py +204 -0
  95. machineconfig/scripts/python/env_manager/path_manager_backend.py +47 -0
  96. machineconfig/scripts/python/env_manager/path_manager_tui.py +228 -0
  97. machineconfig/scripts/python/fire_jobs.py +110 -150
  98. machineconfig/scripts/python/ftpx.py +51 -24
  99. machineconfig/scripts/python/helpers/ast_search.py +74 -0
  100. machineconfig/scripts/python/helpers/qr_code.py +166 -0
  101. machineconfig/scripts/python/helpers/repo_rag.py +325 -0
  102. machineconfig/scripts/python/helpers/run_py_script.py +79 -0
  103. machineconfig/scripts/python/helpers/symantic_search.py +25 -0
  104. machineconfig/scripts/python/helpers/tmp_py_scripts/a.py +26 -0
  105. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.json +14 -0
  106. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
  107. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_cursor_agents.py +22 -0
  108. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
  109. machineconfig/scripts/python/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
  110. machineconfig/scripts/python/helpers_agents/fire_agents_help_launch.py +126 -0
  111. machineconfig/scripts/python/helpers_agents/fire_agents_helper_types.py +41 -0
  112. machineconfig/scripts/python/helpers_agents/templates/prompt.txt +10 -0
  113. machineconfig/scripts/python/helpers_agents/templates/template.ps1 +14 -0
  114. machineconfig/scripts/python/helpers_agents/templates/template.sh +32 -0
  115. machineconfig/scripts/python/{cloud_copy.py → helpers_cloud/cloud_copy.py} +30 -23
  116. machineconfig/scripts/python/{cloud_mount.py → helpers_cloud/cloud_mount.py} +29 -35
  117. machineconfig/scripts/python/{cloud_sync.py → helpers_cloud/cloud_sync.py} +12 -18
  118. machineconfig/scripts/python/{helpers → helpers_cloud}/helpers2.py +1 -1
  119. machineconfig/scripts/python/helpers_croshell/crosh.py +39 -0
  120. machineconfig/scripts/python/{start_slidev.py → helpers_croshell/start_slidev.py} +8 -9
  121. machineconfig/scripts/python/helpers_devops/cli_config.py +105 -0
  122. machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +89 -0
  123. machineconfig/scripts/python/helpers_devops/cli_data.py +25 -0
  124. machineconfig/scripts/python/helpers_devops/cli_nw.py +214 -0
  125. machineconfig/scripts/python/helpers_devops/cli_repos.py +215 -0
  126. machineconfig/scripts/python/helpers_devops/cli_self.py +172 -0
  127. machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
  128. machineconfig/scripts/python/helpers_devops/cli_share_server.py +142 -0
  129. machineconfig/scripts/python/{share_terminal.py → helpers_devops/cli_share_terminal.py} +45 -35
  130. machineconfig/scripts/python/helpers_devops/cli_utils.py +96 -0
  131. machineconfig/scripts/python/{devops_backup_retrieve.py → helpers_devops/devops_backup_retrieve.py} +7 -10
  132. machineconfig/scripts/python/helpers_devops/devops_status.py +499 -0
  133. machineconfig/scripts/python/{devops_update_repos.py → helpers_devops/devops_update_repos.py} +68 -49
  134. machineconfig/scripts/python/helpers_devops/themes/choose_pwsh_theme.ps1 +81 -0
  135. machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +3 -0
  136. machineconfig/scripts/python/{choose_wezterm_theme.py → helpers_devops/themes/choose_wezterm_theme.py} +3 -3
  137. machineconfig/scripts/python/helpers_fire_command/__init__.py +0 -0
  138. machineconfig/scripts/python/helpers_fire_command/f.py +0 -0
  139. machineconfig/scripts/python/{helpers/helpers4.py → helpers_fire_command/file_wrangler.py} +56 -20
  140. machineconfig/scripts/python/{fire_jobs_args_helper.py → helpers_fire_command/fire_jobs_args_helper.py} +5 -1
  141. machineconfig/scripts/python/helpers_fire_command/fire_jobs_route_helper.py +121 -0
  142. machineconfig/scripts/python/helpers_fire_command/fire_jobs_streamlit_helper.py +0 -0
  143. machineconfig/scripts/python/helpers_msearch/__init__.py +5 -0
  144. machineconfig/scripts/{linux → python/helpers_msearch/scripts_linux}/fzfg +3 -3
  145. machineconfig/scripts/python/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
  146. machineconfig/scripts/python/helpers_navigator/__init__.py +20 -0
  147. machineconfig/scripts/python/helpers_navigator/command_builder.py +111 -0
  148. machineconfig/scripts/python/helpers_navigator/command_detail.py +44 -0
  149. machineconfig/scripts/python/helpers_navigator/command_tree.py +620 -0
  150. machineconfig/scripts/python/helpers_navigator/data_models.py +28 -0
  151. machineconfig/scripts/python/helpers_navigator/main_app.py +272 -0
  152. machineconfig/scripts/python/helpers_navigator/search_bar.py +15 -0
  153. machineconfig/scripts/python/helpers_network/__init__.py +0 -0
  154. machineconfig/scripts/python/helpers_network/address.py +132 -0
  155. machineconfig/scripts/python/{devops_add_identity.py → helpers_network/devops_add_identity.py} +0 -2
  156. machineconfig/scripts/python/helpers_network/devops_add_ssh_key.py +153 -0
  157. machineconfig/scripts/{linux → python/helpers_network}/mount_nfs +0 -1
  158. machineconfig/scripts/python/{mount_nfs.py → helpers_network/mount_nfs.py} +3 -3
  159. machineconfig/scripts/{linux → python/helpers_network}/mount_nw_drive +1 -2
  160. machineconfig/scripts/python/{mount_ssh.py → helpers_network/mount_ssh.py} +3 -3
  161. machineconfig/scripts/python/{onetimeshare.py → helpers_network/onetimeshare.py} +0 -1
  162. machineconfig/scripts/python/helpers_network/ssh_debug_linux.py +391 -0
  163. machineconfig/scripts/python/helpers_network/ssh_debug_windows.py +338 -0
  164. machineconfig/scripts/python/{wifi_conn.py → helpers_network/wifi_conn.py} +1 -53
  165. machineconfig/scripts/python/{wsl_windows_transfer.py → helpers_network/wsl_windows_transfer.py} +5 -4
  166. machineconfig/scripts/python/helpers_repos/action.py +209 -0
  167. machineconfig/scripts/python/helpers_repos/action_helper.py +150 -0
  168. machineconfig/scripts/python/{repos_helper_clone.py → helpers_repos/clone.py} +2 -3
  169. machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +218 -0
  170. machineconfig/scripts/python/{repos_helper.py → helpers_repos/entrypoint.py} +9 -17
  171. machineconfig/scripts/python/helpers_repos/grource.py +340 -0
  172. machineconfig/scripts/python/{repos_helper_record.py → helpers_repos/record.py} +4 -3
  173. machineconfig/scripts/python/helpers_repos/repo_analyzer_1.py +160 -0
  174. machineconfig/scripts/python/{count_lines.py → helpers_repos/repo_analyzer_2.py} +113 -192
  175. machineconfig/scripts/python/helpers_repos/sync.py +66 -0
  176. machineconfig/scripts/python/{repos_helper_update.py → helpers_repos/update.py} +3 -3
  177. machineconfig/scripts/python/helpers_sessions/__init__.py +0 -0
  178. machineconfig/scripts/python/helpers_sessions/sessions_multiprocess.py +65 -0
  179. machineconfig/scripts/python/helpers_utils/download.py +150 -0
  180. machineconfig/scripts/python/helpers_utils/path.py +185 -0
  181. machineconfig/scripts/python/interactive.py +64 -84
  182. machineconfig/scripts/python/mcfg_entry.py +58 -0
  183. machineconfig/scripts/python/msearch.py +71 -0
  184. machineconfig/scripts/python/sessions.py +119 -45
  185. machineconfig/scripts/python/terminal.py +133 -0
  186. machineconfig/scripts/python/utils.py +64 -0
  187. machineconfig/scripts/windows/mounts/Restore-ThunderbirdProfile.ps1 +92 -0
  188. machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +1 -3
  189. machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +1 -1
  190. machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -6
  191. machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
  192. machineconfig/settings/broot/br.sh +0 -4
  193. machineconfig/settings/broot/conf.toml +1 -1
  194. machineconfig/settings/helix/config.toml +16 -0
  195. machineconfig/settings/helix/languages.toml +13 -4
  196. machineconfig/settings/helix/yazi-picker.sh +12 -0
  197. machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
  198. machineconfig/settings/lf/linux/exe/previewer.sh +9 -3
  199. machineconfig/settings/lf/linux/lfrc +10 -12
  200. machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
  201. machineconfig/settings/lf/windows/lfrc +18 -38
  202. machineconfig/settings/lf/windows/mkfile.ps1 +1 -1
  203. machineconfig/settings/linters/.ruff.toml +1 -1
  204. machineconfig/settings/lvim/windows/archive/config_additional.lua +0 -6
  205. machineconfig/settings/marimo/marimo.toml +80 -0
  206. machineconfig/settings/marimo/snippets/globalize.py +34 -0
  207. machineconfig/settings/pistol/pistol.conf +1 -1
  208. machineconfig/settings/shells/bash/init.sh +82 -31
  209. machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
  210. machineconfig/settings/shells/nushell/config.nu +2 -35
  211. machineconfig/settings/shells/nushell/env.nu +45 -6
  212. machineconfig/settings/shells/nushell/init.nu +314 -0
  213. machineconfig/settings/shells/pwsh/init.ps1 +61 -43
  214. machineconfig/settings/shells/starship/starship.toml +16 -0
  215. machineconfig/settings/shells/wezterm/wezterm.lua +2 -0
  216. machineconfig/settings/shells/wt/settings.json +32 -17
  217. machineconfig/settings/shells/zsh/init.sh +89 -0
  218. machineconfig/settings/svim/linux/init.toml +0 -4
  219. machineconfig/settings/svim/windows/init.toml +0 -3
  220. machineconfig/settings/television/cable_unix/alias.toml +8 -0
  221. machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
  222. machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
  223. machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
  224. machineconfig/settings/television/cable_unix/channels.toml +19 -0
  225. machineconfig/settings/television/cable_unix/dirs.toml +13 -0
  226. machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
  227. machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
  228. machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
  229. machineconfig/settings/television/cable_unix/env.toml +17 -0
  230. machineconfig/settings/television/cable_unix/files.toml +11 -0
  231. machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
  232. machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
  233. machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
  234. machineconfig/settings/television/cable_unix/git-log.toml +12 -0
  235. machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
  236. machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
  237. machineconfig/settings/television/cable_unix/guix.toml +20 -0
  238. machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
  239. machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
  240. machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
  241. machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
  242. machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
  243. machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
  244. machineconfig/settings/television/cable_unix/procs.toml +20 -0
  245. machineconfig/settings/television/cable_unix/text.toml +17 -0
  246. machineconfig/settings/television/cable_unix/tldr.toml +18 -0
  247. machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
  248. machineconfig/settings/television/cable_windows/alias.toml +7 -0
  249. machineconfig/settings/television/cable_windows/dirs.toml +13 -0
  250. machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
  251. machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
  252. machineconfig/settings/television/cable_windows/env.toml +17 -0
  253. machineconfig/settings/television/cable_windows/files.toml +14 -0
  254. machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
  255. machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
  256. machineconfig/settings/television/cable_windows/git-log.toml +11 -0
  257. machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
  258. machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
  259. machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
  260. machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
  261. machineconfig/settings/television/cable_windows/text.toml +17 -0
  262. machineconfig/settings/yazi/init.lua +61 -0
  263. machineconfig/settings/yazi/keymap_linux.toml +94 -0
  264. machineconfig/settings/yazi/keymap_windows.toml +78 -0
  265. machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
  266. machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
  267. machineconfig/settings/yazi/theme.toml +4 -0
  268. machineconfig/settings/yazi/yazi_linux.toml +84 -0
  269. machineconfig/settings/yazi/yazi_windows.toml +58 -0
  270. machineconfig/setup_linux/__init__.py +11 -0
  271. machineconfig/setup_linux/apps_desktop.sh +89 -0
  272. machineconfig/setup_linux/apps_gui.sh +64 -0
  273. machineconfig/setup_linux/ssh/openssh_all.sh +25 -0
  274. machineconfig/setup_linux/ssh/openssh_wsl.sh +38 -0
  275. machineconfig/setup_linux/uv.sh +15 -0
  276. machineconfig/setup_linux/web_shortcuts/interactive.sh +26 -6
  277. machineconfig/setup_linux/web_shortcuts/live_from_github.sh +31 -0
  278. machineconfig/setup_mac/__init__.py +16 -0
  279. machineconfig/setup_mac/apps_gui.sh +248 -0
  280. machineconfig/setup_mac/ssh/openssh_setup.sh +114 -0
  281. machineconfig/setup_mac/uv.sh +36 -0
  282. machineconfig/setup_windows/__init__.py +11 -0
  283. machineconfig/setup_windows/others/power_options.ps1 +7 -0
  284. machineconfig/setup_windows/ssh/add-sshkey.ps1 +29 -0
  285. machineconfig/setup_windows/ssh/add_identity.ps1 +11 -0
  286. machineconfig/setup_windows/ssh/openssh-server.ps1 +37 -0
  287. machineconfig/setup_windows/uv.ps1 +17 -0
  288. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +27 -10
  289. machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +30 -0
  290. machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
  291. machineconfig/utils/accessories.py +7 -5
  292. machineconfig/utils/cloud/onedrive/README.md +139 -0
  293. machineconfig/utils/code.py +155 -105
  294. machineconfig/utils/files/art/fat_croco.txt +10 -0
  295. machineconfig/utils/files/art/halfwit_croco.txt +9 -0
  296. machineconfig/utils/files/art/happy_croco.txt +22 -0
  297. machineconfig/utils/files/art/water_croco.txt +11 -0
  298. machineconfig/utils/files/ascii_art.py +1 -1
  299. machineconfig/utils/files/dbms.py +257 -0
  300. machineconfig/utils/files/headers.py +11 -14
  301. machineconfig/utils/files/ouch/__init__.py +0 -0
  302. machineconfig/utils/files/ouch/decompress.py +45 -0
  303. machineconfig/utils/files/read.py +10 -18
  304. machineconfig/utils/installer_utils/github_release_bulk.py +156 -119
  305. machineconfig/utils/installer_utils/install_from_url.py +183 -0
  306. machineconfig/utils/installer_utils/installer_class.py +64 -181
  307. machineconfig/utils/installer_utils/installer_cli.py +175 -0
  308. machineconfig/utils/installer_utils/installer_helper.py +129 -0
  309. machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +66 -97
  310. machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +49 -82
  311. machineconfig/utils/io.py +77 -23
  312. machineconfig/utils/links.py +254 -162
  313. machineconfig/utils/meta.py +256 -0
  314. machineconfig/utils/notifications.py +1 -1
  315. machineconfig/utils/options.py +46 -18
  316. machineconfig/utils/options_tv.py +119 -0
  317. machineconfig/utils/path_extended.py +48 -101
  318. machineconfig/utils/path_helper.py +76 -23
  319. machineconfig/utils/procs.py +50 -70
  320. machineconfig/utils/scheduler.py +88 -124
  321. machineconfig/utils/scheduling.py +0 -3
  322. machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
  323. machineconfig/utils/schemas/layouts/layout_types.py +1 -1
  324. machineconfig/utils/source_of_truth.py +3 -6
  325. machineconfig/utils/ssh.py +263 -274
  326. machineconfig/utils/ssh_utils/abc.py +5 -0
  327. machineconfig/utils/ssh_utils/copy_from_here.py +111 -0
  328. machineconfig/utils/ssh_utils/copy_to_here.py +302 -0
  329. machineconfig/utils/ssh_utils/utils.py +142 -0
  330. machineconfig/utils/ssh_utils/wsl.py +210 -0
  331. machineconfig/utils/terminal.py +3 -113
  332. machineconfig/utils/tst.py +20 -0
  333. machineconfig/utils/upgrade_packages.py +114 -28
  334. machineconfig/utils/ve.py +12 -4
  335. machineconfig-7.98.dist-info/METADATA +132 -0
  336. machineconfig-7.98.dist-info/RECORD +504 -0
  337. machineconfig-7.98.dist-info/entry_points.txt +13 -0
  338. machineconfig/cluster/sessions_managers/ffile.py +0 -4
  339. machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -49
  340. machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -85
  341. machineconfig/jobs/linux/msc/cli_agents.sh +0 -16
  342. machineconfig/jobs/python/python_ve_symlink.py +0 -37
  343. machineconfig/jobs/python/vscode/api.py +0 -57
  344. machineconfig/jobs/python/vscode/sync_code.py +0 -73
  345. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +0 -14
  346. machineconfig/jobs/windows/start_terminal.ps1 +0 -6
  347. machineconfig/jobs/windows/startup_file.cmd +0 -2
  348. machineconfig/profile/create.py +0 -303
  349. machineconfig/profile/shell.py +0 -176
  350. machineconfig/scripts/cloud/init.sh +0 -119
  351. machineconfig/scripts/linux/agents +0 -2
  352. machineconfig/scripts/linux/choose_wezterm_theme +0 -3
  353. machineconfig/scripts/linux/cloud_copy +0 -2
  354. machineconfig/scripts/linux/cloud_mount +0 -2
  355. machineconfig/scripts/linux/cloud_repo_sync +0 -2
  356. machineconfig/scripts/linux/cloud_sync +0 -2
  357. machineconfig/scripts/linux/croshell +0 -3
  358. machineconfig/scripts/linux/devops +0 -2
  359. machineconfig/scripts/linux/fire +0 -2
  360. machineconfig/scripts/linux/ftpx +0 -2
  361. machineconfig/scripts/linux/fzf2g +0 -21
  362. machineconfig/scripts/linux/fzfag +0 -17
  363. machineconfig/scripts/linux/fzffg +0 -25
  364. machineconfig/scripts/linux/fzfrga +0 -21
  365. machineconfig/scripts/linux/gh_models +0 -2
  366. machineconfig/scripts/linux/initai +0 -2
  367. machineconfig/scripts/linux/kill_process +0 -2
  368. machineconfig/scripts/linux/scheduler +0 -2
  369. machineconfig/scripts/linux/sessions +0 -2
  370. machineconfig/scripts/linux/share_smb +0 -1
  371. machineconfig/scripts/linux/skrg +0 -4
  372. machineconfig/scripts/linux/start_slidev +0 -2
  373. machineconfig/scripts/linux/start_terminals +0 -3
  374. machineconfig/scripts/linux/warp-cli.sh +0 -122
  375. machineconfig/scripts/linux/wifi_conn +0 -2
  376. machineconfig/scripts/linux/z_ls +0 -104
  377. machineconfig/scripts/python/ai/generate_files.py +0 -83
  378. machineconfig/scripts/python/ai/solutions/copilot/prompts/allLintersAndTypeCheckers.prompt.md +0 -5
  379. machineconfig/scripts/python/cloud_repo_sync.py +0 -190
  380. machineconfig/scripts/python/count_lines_frontend.py +0 -16
  381. machineconfig/scripts/python/devops_add_ssh_key.py +0 -120
  382. machineconfig/scripts/python/dotfile.py +0 -78
  383. machineconfig/scripts/python/fire_agents_help_launch.py +0 -120
  384. machineconfig/scripts/python/fire_agents_helper_types.py +0 -12
  385. machineconfig/scripts/python/fire_jobs_route_helper.py +0 -65
  386. machineconfig/scripts/python/get_zellij_cmd.py +0 -15
  387. machineconfig/scripts/python/gh_models.py +0 -104
  388. machineconfig/scripts/python/helpers/repo_sync_helpers.py +0 -116
  389. machineconfig/scripts/python/repos.py +0 -132
  390. machineconfig/scripts/python/repos_helper_action.py +0 -378
  391. machineconfig/scripts/python/snapshot.py +0 -25
  392. machineconfig/scripts/python/start_terminals.py +0 -121
  393. machineconfig/scripts/python/t4.py +0 -17
  394. machineconfig/scripts/windows/agents.ps1 +0 -1
  395. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
  396. machineconfig/scripts/windows/cloud_copy.ps1 +0 -1
  397. machineconfig/scripts/windows/cloud_mount.ps1 +0 -1
  398. machineconfig/scripts/windows/cloud_repo_sync.ps1 +0 -1
  399. machineconfig/scripts/windows/cloud_sync.ps1 +0 -1
  400. machineconfig/scripts/windows/croshell.ps1 +0 -1
  401. machineconfig/scripts/windows/devops.ps1 +0 -1
  402. machineconfig/scripts/windows/dotfile.ps1 +0 -1
  403. machineconfig/scripts/windows/fire.ps1 +0 -1
  404. machineconfig/scripts/windows/ftpx.ps1 +0 -1
  405. machineconfig/scripts/windows/fzfb.ps1 +0 -3
  406. machineconfig/scripts/windows/fzfg.ps1 +0 -2
  407. machineconfig/scripts/windows/fzfrga.bat +0 -20
  408. machineconfig/scripts/windows/gpt.ps1 +0 -1
  409. machineconfig/scripts/windows/grep.ps1 +0 -2
  410. machineconfig/scripts/windows/initai.ps1 +0 -1
  411. machineconfig/scripts/windows/kill_process.ps1 +0 -1
  412. machineconfig/scripts/windows/nano.ps1 +0 -3
  413. machineconfig/scripts/windows/pomodoro.ps1 +0 -1
  414. machineconfig/scripts/windows/reload_path.ps1 +0 -3
  415. machineconfig/scripts/windows/scheduler.ps1 +0 -1
  416. machineconfig/scripts/windows/sessions.ps1 +0 -1
  417. machineconfig/scripts/windows/snapshot.ps1 +0 -1
  418. machineconfig/scripts/windows/start_slidev.ps1 +0 -1
  419. machineconfig/scripts/windows/start_terminals.ps1 +0 -1
  420. machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
  421. machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
  422. machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
  423. machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
  424. machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
  425. machineconfig/settings/lf/windows/tst.ps1 +0 -1
  426. machineconfig/settings/yazi/yazi.toml +0 -4
  427. machineconfig/setup_linux/nix/cli_installation.sh +0 -157
  428. machineconfig/setup_linux/others/openssh-server_add_pub_key.sh +0 -57
  429. machineconfig/setup_linux/web_shortcuts/croshell.sh +0 -11
  430. machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -52
  431. machineconfig/setup_windows/web_shortcuts/all.ps1 +0 -18
  432. machineconfig/setup_windows/web_shortcuts/ascii_art.ps1 +0 -36
  433. machineconfig/setup_windows/web_shortcuts/croshell.ps1 +0 -16
  434. machineconfig/setup_windows/web_shortcuts/ssh.ps1 +0 -11
  435. machineconfig/utils/ai/generate_file_checklist.py +0 -68
  436. machineconfig/utils/installer_utils/installer.py +0 -189
  437. machineconfig-5.15.dist-info/METADATA +0 -188
  438. machineconfig-5.15.dist-info/RECORD +0 -415
  439. machineconfig-5.15.dist-info/entry_points.txt +0 -18
  440. machineconfig/cluster/sessions_managers/{utils → helpers}/load_balancer_helper.py +0 -0
  441. machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
  442. machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
  443. machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
  444. machineconfig/{jobs/python → scripts/python/ai/utils}/__init__.py +0 -0
  445. machineconfig/scripts/python/{helpers → helpers_agents}/__init__.py +0 -0
  446. machineconfig/{jobs/windows/msc/cli_agents.bat → scripts/python/helpers_agents/agentic_frameworks/__init__.py} +0 -0
  447. machineconfig/scripts/python/{fire_agents_help_search.py → helpers_agents/fire_agents_help_search.py} +0 -0
  448. machineconfig/scripts/python/{fire_agents_load_balancer.py → helpers_agents/fire_agents_load_balancer.py} +0 -0
  449. machineconfig/{jobs/windows/msc/cli_agents.ps1 → scripts/python/helpers_cloud/__init__.py} +0 -0
  450. machineconfig/scripts/python/{helpers → helpers_cloud}/cloud_helpers.py +1 -1
  451. /machineconfig/scripts/python/{helpers → helpers_cloud}/helpers5.py +0 -0
  452. /machineconfig/scripts/python/{fire_jobs_streamlit_helper.py → helpers_croshell/__init__.py} +0 -0
  453. /machineconfig/scripts/python/{pomodoro.py → helpers_croshell/pomodoro.py} +0 -0
  454. /machineconfig/scripts/python/{scheduler.py → helpers_croshell/scheduler.py} +0 -0
  455. /machineconfig/scripts/python/{viewer.py → helpers_croshell/viewer.py} +0 -0
  456. /machineconfig/scripts/python/{viewer_template.py → helpers_croshell/viewer_template.py} +0 -0
  457. /machineconfig/scripts/{windows/share_nfs.ps1 → python/helpers_devops/__init__.py} +0 -0
  458. /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers_devops/themes/__init__.py} +0 -0
  459. /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers_devops/themes/choose_starship_theme.ps1} +0 -0
  460. /machineconfig/scripts/python/{cloud_manager.py → helpers_fire_command/cloud_manager.py} +0 -0
  461. /machineconfig/scripts/{linux → python/helpers_network}/mount_drive +0 -0
  462. /machineconfig/scripts/python/{mount_nw_drive.py → helpers_network/mount_nw_drive.py} +0 -0
  463. /machineconfig/scripts/{linux → python/helpers_network}/mount_smb +0 -0
  464. /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
  465. /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
  466. /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
  467. /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
  468. /machineconfig/setup_linux/{web_shortcuts → others}/android.sh +0 -0
  469. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_add_key.ps1 +0 -0
  470. /machineconfig/{jobs/windows/archive → setup_windows/ssh}/openssh-server_copy-ssh-id.ps1 +0 -0
  471. {machineconfig-5.15.dist-info → machineconfig-7.98.dist-info}/WHEEL +0 -0
  472. {machineconfig-5.15.dist-info → machineconfig-7.98.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,62 @@
1
+
2
+ from typing import Literal
3
+ from pathlib import Path
4
+ import shutil
5
+ from machineconfig.utils.source_of_truth import LIBRARY_ROOT, CONFIG_ROOT
6
+
7
+
8
+ def _copy_path(source: Path, target: Path, overwrite: bool = False) -> None:
9
+ source = source.expanduser().resolve()
10
+ target = target.expanduser().resolve()
11
+ if not source.exists():
12
+ raise FileNotFoundError(f"Source path does not exist: {source}")
13
+ target.parent.mkdir(parents=True, exist_ok=True)
14
+ if target.exists() and not overwrite:
15
+ raise FileExistsError(f"Target already exists and overwrite=False: {target}")
16
+ if target.exists() and overwrite:
17
+ if target.is_dir():
18
+ shutil.rmtree(target)
19
+ else:
20
+ target.unlink()
21
+ if source.is_file():
22
+ shutil.copy2(source, target)
23
+ elif source.is_dir():
24
+ shutil.copytree(source, target, dirs_exist_ok=overwrite)
25
+ else:
26
+ raise ValueError(f"Source is neither file nor directory: {source}")
27
+
28
+
29
+ def copy_assets_to_machine(which: Literal["scripts", "settings"]) -> None:
30
+ import platform
31
+ import subprocess
32
+
33
+ system_name = platform.system().lower()
34
+ if system_name == "windows":
35
+ system = "windows"
36
+ elif system_name in {"linux", "darwin"}:
37
+ system = "linux"
38
+ else:
39
+ raise NotImplementedError(f"System {system_name} not supported")
40
+
41
+ match which:
42
+ case "scripts":
43
+ source = LIBRARY_ROOT.joinpath("scripts", system)
44
+ target = CONFIG_ROOT.joinpath("scripts")
45
+
46
+ wrap_mcfg_source = LIBRARY_ROOT.joinpath("scripts", "nu", "wrap_mcfg.nu")
47
+ wrap_mcfg_target = CONFIG_ROOT.joinpath("scripts", "wrap_mcfg.nu")
48
+ wrap_mcfg_target.parent.mkdir(parents=True, exist_ok=True)
49
+ _copy_path(source=wrap_mcfg_source, target=wrap_mcfg_target, overwrite=True)
50
+ case "settings":
51
+ source = LIBRARY_ROOT.joinpath("settings")
52
+ target = CONFIG_ROOT.joinpath("settings")
53
+
54
+ _copy_path(source=source, target=target, overwrite=True)
55
+
56
+ if system_name == "linux" and which == "scripts":
57
+ from rich.console import Console
58
+ console = Console()
59
+ console.print("\n[bold]📜 Setting executable permissions for scripts...[/bold]")
60
+ scripts_path = CONFIG_ROOT.joinpath("scripts")
61
+ subprocess.run(f"chmod +x {scripts_path} -R", shell=True, capture_output=True, text=True, check=False)
62
+ console.print("[green]✅ Script permissions updated[/green]")
@@ -0,0 +1,288 @@
1
+ """
2
+ This script Takes away all config files from the computer, place them in one directory
3
+ `dotfiles`, and create symlinks to those files from thier original locations.
4
+
5
+ """
6
+
7
+ from machineconfig.utils.links import OperationRecord
8
+ from rich.console import Console
9
+ from rich.panel import Panel
10
+ from rich.pretty import Pretty
11
+ from rich.text import Text
12
+ from rich.table import Table
13
+
14
+ from machineconfig.utils.path_extended import PathExtended
15
+ from machineconfig.utils.links import symlink_map, copy_map
16
+ from machineconfig.profile.create_links_export import ON_CONFLICT_STRICT
17
+ from machineconfig.utils.source_of_truth import LIBRARY_ROOT, CONFIG_ROOT
18
+
19
+ import platform
20
+ import subprocess
21
+ import tomllib
22
+ from typing import Optional, Any, TypedDict, Literal
23
+
24
+
25
+ system = platform.system() # Linux or Windows
26
+ ERROR_LIST: list[Any] = [] # append to this after every exception captured.
27
+ SYSTEM = system.lower()
28
+
29
+ console = Console()
30
+
31
+
32
+ class Base(TypedDict):
33
+ this: str
34
+ to_this: str
35
+ contents: Optional[bool]
36
+ copy: Optional[bool]
37
+ class ConfigMapper(TypedDict):
38
+ file_name: str
39
+ config_file_default_path: str
40
+ self_managed_config_file_path: str
41
+ contents: Optional[bool]
42
+ copy: Optional[bool]
43
+ class MapperFileData(TypedDict):
44
+ public: dict[str, list[ConfigMapper]]
45
+ private: dict[str, list[ConfigMapper]]
46
+ def read_mapper() -> MapperFileData:
47
+ mapper_data: dict[str, dict[str, Base]] = tomllib.loads(LIBRARY_ROOT.joinpath("profile/mapper.toml").read_text(encoding="utf-8"))
48
+ public: dict[str, list[ConfigMapper]] = {}
49
+ private: dict[str, list[ConfigMapper]] = {}
50
+ # def get_other_systems(current_system: str) -> list[str]:
51
+ # all_systems = ["linux", "windows", "darwin"]
52
+ # return [s for s in all_systems if s != current_system.lower()]
53
+ # OTHER_SYSTEMS = get_other_systems(SYSTEM)
54
+ for program_key, program_map in mapper_data.items():
55
+ parts = program_key.split("_")
56
+ if len(parts) > 1:
57
+ if parts[-1].lower() == "windows" and SYSTEM != "windows":
58
+ # console.print(f"Skipping Windows-only program mapping: {program_key}")
59
+ continue
60
+ elif parts[-1].lower() == "linux" and SYSTEM == "windows":
61
+ # console.print(f"Skipping Linux-only program mapping: {program_key}")
62
+ continue
63
+ for file_name, file_base in program_map.items():
64
+ file_map: ConfigMapper = {
65
+ "file_name": file_name,
66
+ "config_file_default_path": file_base["this"],
67
+ "self_managed_config_file_path": file_base["to_this"],
68
+ "contents": file_base.get("contents"),
69
+ "copy": file_base.get("copy"),
70
+ }
71
+ if "CONFIG_ROOT" in file_map["self_managed_config_file_path"]:
72
+ if program_key not in public:
73
+ public[program_key] = []
74
+ public[program_key].append(file_map)
75
+ else:
76
+ if program_key not in private:
77
+ private[program_key] = []
78
+ private[program_key].append(file_map)
79
+ return {"public": public, "private": private}
80
+
81
+
82
+ def apply_mapper(mapper_data: dict[str, list[ConfigMapper]],
83
+ on_conflict: ON_CONFLICT_STRICT,
84
+ method: Literal["symlink", "copy"]
85
+ ):
86
+ operation_records: list[OperationRecord] = []
87
+ print(f"Working with {len(mapper_data)} programs from mapper data.")
88
+ if len(mapper_data) == 1:
89
+ print(mapper_data)
90
+ import os
91
+ if os.name == "nt":
92
+ import ctypes
93
+ try:
94
+ is_admin = ctypes.windll.shell32.IsUserAnAdmin()
95
+ except Exception:
96
+ is_admin = False
97
+ total_length = sum(len(item) for item in mapper_data.values())
98
+ if not is_admin and method == "symlink" and total_length > 5:
99
+ warning_body = "\n".join([
100
+ "[bold yellow]Administrator privileges required[/]",
101
+ "Run the terminal as admin and try again to avoid repeated elevation prompts.",
102
+ ])
103
+ console.print(
104
+ Panel.fit(
105
+ warning_body,
106
+ title="⚠️ Permission Needed",
107
+ border_style="yellow",
108
+ padding=(1, 2),
109
+ )
110
+ )
111
+ raise RuntimeError("Run terminal as admin and try again, otherwise, there will be too many popups for admin requests and no chance to terminate the program.")
112
+ for program_name, program_files in mapper_data.items():
113
+ console.rule(f"🔄 Processing [bold]{program_name}[/] symlinks", style="cyan")
114
+ for a_mapper in program_files:
115
+ config_file_default_path = PathExtended(a_mapper["config_file_default_path"])
116
+ self_managed_config_file_path = PathExtended(a_mapper["self_managed_config_file_path"].replace("CONFIG_ROOT", CONFIG_ROOT.as_posix()))
117
+ # Determine whether to use copy or symlink
118
+ use_copy = method == "copy" or a_mapper.get("copy", False)
119
+ if "contents" in a_mapper and a_mapper["contents"]:
120
+ targets = list(self_managed_config_file_path.expanduser().search("*"))
121
+ for a_target in targets:
122
+ operation_type = "contents_copy" if use_copy else "contents_symlink"
123
+ try:
124
+ if use_copy:
125
+ result = copy_map(config_file_default_path=config_file_default_path.joinpath(a_target.name), self_managed_config_file_path=a_target, on_conflict=on_conflict)
126
+ else:
127
+ result = symlink_map(config_file_default_path=config_file_default_path.joinpath(a_target.name), self_managed_config_file_path=a_target, on_conflict=on_conflict)
128
+ operation_records.append({
129
+ "program": program_name,
130
+ "file_key": a_mapper["file_name"],
131
+ "defaultPath": str(config_file_default_path.joinpath(a_target.name)),
132
+ "selfManaged": str(a_target),
133
+ "operation": operation_type,
134
+ "action": result["action"],
135
+ "details": result["details"],
136
+ "status": "success"
137
+ })
138
+ except ValueError as ex:
139
+ if "resolve to the same location" in str(ex):
140
+ operation_records.append({
141
+ "program": program_name,
142
+ "file_key": a_mapper["file_name"],
143
+ "defaultPath": str(config_file_default_path.joinpath(a_target.name)),
144
+ "selfManaged": str(a_target),
145
+ "operation": operation_type,
146
+ "action": "already_linked",
147
+ "details": "defaultPath and selfManaged resolve to same location - already correctly configured",
148
+ "status": "success"
149
+ })
150
+ else:
151
+ raise
152
+ except Exception as ex:
153
+ console.print(f"❌ [red]Config error[/red]: {program_name} | {a_mapper['file_name']} | {a_target.name}. {ex}")
154
+ operation_records.append({
155
+ "program": program_name,
156
+ "file_key": a_mapper["file_name"],
157
+ "defaultPath": str(config_file_default_path.joinpath(a_target.name)),
158
+ "selfManaged": str(a_target),
159
+ "operation": operation_type,
160
+ "action": "error",
161
+ "details": f"Failed to process contents: {str(ex)}",
162
+ "status": f"error: {str(ex)}"
163
+ })
164
+ else:
165
+ operation_type = "copy" if use_copy else "symlink"
166
+ try:
167
+ if use_copy:
168
+ result = copy_map(config_file_default_path=config_file_default_path, self_managed_config_file_path=self_managed_config_file_path, on_conflict=on_conflict)
169
+ else:
170
+ result = symlink_map(config_file_default_path=config_file_default_path, self_managed_config_file_path=self_managed_config_file_path, on_conflict=on_conflict)
171
+ operation_records.append({
172
+ "program": program_name,
173
+ "file_key": a_mapper["file_name"],
174
+ "defaultPath": str(config_file_default_path),
175
+ "selfManaged": str(self_managed_config_file_path),
176
+ "operation": operation_type,
177
+ "action": result["action"],
178
+ "details": result["details"],
179
+ "status": "success"
180
+ })
181
+ except ValueError as ex:
182
+ if "resolve to the same location" in str(ex):
183
+ operation_records.append({
184
+ "program": program_name,
185
+ "file_key": a_mapper["file_name"],
186
+ "defaultPath": str(config_file_default_path),
187
+ "selfManaged": str(self_managed_config_file_path),
188
+ "operation": operation_type,
189
+ "action": "already_linked",
190
+ "details": "defaultPath and selfManaged resolve to same location - already correctly configured",
191
+ "status": "success"
192
+ })
193
+ else:
194
+ raise
195
+ except Exception as ex:
196
+ console.print(f"❌ [red]Config error[/red]: {program_name} | {a_mapper['file_name']} | {ex}")
197
+ operation_records.append({
198
+ "program": program_name,
199
+ "file_key": a_mapper["file_name"],
200
+ "defaultPath": str(config_file_default_path),
201
+ "selfManaged": str(self_managed_config_file_path),
202
+ "operation": operation_type,
203
+ "action": "error",
204
+ "details": f"Failed to create {operation_type}: {str(ex)}",
205
+ "status": f"error: {str(ex)}"
206
+ })
207
+
208
+ if program_name == "ssh" and system == "Linux": # permissions of ~/dotfiles/.ssh should be adjusted
209
+ try:
210
+ console.print("\n[bold]🔒 Setting secure permissions for SSH files...[/bold]")
211
+ subprocess.run("chmod 700 $HOME/.ssh/", shell=True, check=True)
212
+ subprocess.run("chmod 700 $HOME/dotfiles/creds/.ssh/", shell=True, check=True)
213
+ subprocess.run("chmod 600 $HOME/dotfiles/creds/.ssh/*", shell=True, check=True)
214
+ subprocess.run("chmod 600 $HOME/.ssh/*", shell=True, check=True)
215
+ console.print("[green]✅ SSH permissions set successfully[/green]")
216
+ except Exception as e:
217
+ ERROR_LIST.append(e)
218
+ console.print(f"❌ [red]Error setting SSH permissions[/red]: {e}")
219
+
220
+ # Display operation summary table
221
+ if operation_records:
222
+ table = Table(title="🔗 Symlink Operations Summary", show_header=True, header_style="bold magenta")
223
+ table.add_column("Program", style="cyan", no_wrap=True)
224
+ table.add_column("File Key", style="blue", no_wrap=True)
225
+ table.add_column("Default Path", style="green")
226
+ table.add_column("Self Managed", style="yellow")
227
+ table.add_column("Operation", style="magenta", no_wrap=True)
228
+ table.add_column("Action", style="red", no_wrap=True)
229
+ table.add_column("Details", style="white")
230
+ table.add_column("Status", style="red", no_wrap=True)
231
+
232
+ for record in operation_records:
233
+ status_style = "green" if record["status"] == "success" else "red"
234
+ action_style = "green" if record["action"] != "error" else "red"
235
+ table.add_row(
236
+ record["program"],
237
+ record["file_key"],
238
+ record["defaultPath"],
239
+ record["selfManaged"],
240
+ record["operation"],
241
+ f"[{action_style}]{record['action']}[/{action_style}]",
242
+ record["details"],
243
+ f"[{status_style}]{record['status']}[/{status_style}]"
244
+ )
245
+
246
+ console.print("\n")
247
+ console.print(table)
248
+
249
+ # Export operation records to CSV
250
+ import csv
251
+ from datetime import datetime
252
+
253
+ csv_dir = PathExtended(CONFIG_ROOT).joinpath("symlink_operations")
254
+ csv_dir.mkdir(parents=True, exist_ok=True)
255
+
256
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
257
+ csv_filename = f"symlink_operations_{timestamp}.csv"
258
+ csv_path = csv_dir.joinpath(csv_filename)
259
+
260
+ with open(csv_path, "w", newline="", encoding="utf-8") as csvfile:
261
+ fieldnames = ["program", "file_key", "defaultPath", "selfManaged", "operation", "action", "details", "status"]
262
+ writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
263
+ writer.writeheader()
264
+ writer.writerows(operation_records)
265
+
266
+ console.print(f"\n[bold green]📊 Operations exported to CSV:[/bold green] [cyan]{csv_path}[/cyan]")
267
+
268
+ if len(ERROR_LIST) > 0:
269
+ console.print(
270
+ Panel(
271
+ Pretty(ERROR_LIST),
272
+ title="❗ Errors Encountered During Processing",
273
+ border_style="red",
274
+ padding=(1, 2),
275
+ )
276
+ )
277
+ else:
278
+ console.print(
279
+ Panel.fit(
280
+ Text("✅ All symlinks created successfully!", justify="center"),
281
+ title="Symlink Creation Complete",
282
+ border_style="green",
283
+ )
284
+ )
285
+
286
+
287
+ if __name__ == "__main__":
288
+ pass
@@ -0,0 +1,100 @@
1
+
2
+ import typer
3
+ from typing import Optional, Literal, Annotated, TypeAlias
4
+
5
+ ON_CONFLICT_LOOSE: TypeAlias = Literal[
6
+ "throw-error", "t",
7
+ "overwrite-self-managed", "os",
8
+ "backup-self-managed", "bs",
9
+ "overwrite-default-path", "od",
10
+ "backup-default-path", "bd"
11
+ ]
12
+ ON_CONFLICT_STRICT: TypeAlias = Literal["throw-error", "overwrite-self-managed", "backup-self-managed", "overwrite-default-path", "backup-default-path"]
13
+ ON_CONFLICT_MAPPER: dict[str, ON_CONFLICT_STRICT] = {
14
+ "t": "throw-error",
15
+ "os": "overwrite-self-managed",
16
+ "bs": "backup-self-managed",
17
+ "od": "overwrite-default-path",
18
+ "bd": "backup-default-path",
19
+ "throw-error": "throw-error",
20
+ "overwrite-self-managed": "overwrite-self-managed",
21
+ "backup-self-managed": "backup-self-managed",
22
+ "overwrite-default-path": "overwrite-default-path",
23
+ "backup-default-path": "backup-default-path",
24
+ }
25
+
26
+
27
+ def main_public_from_parser(method: Annotated[Literal["symlink", "s", "copy", "c"], typer.Option(..., "--method", "-m", help="Method to use for setting up the config file.")],
28
+ on_conflict: Annotated[ON_CONFLICT_LOOSE, typer.Option(..., "--on-conflict", "-o", help="Action to take on conflict")] = "throw-error",
29
+ which: Annotated[Optional[str], typer.Option(..., "--which", "-w", help="Specific items to process")] = "all",
30
+ interactive: Annotated[bool, typer.Option(..., "--interactive", "-i", help="Run in interactive mode")] = False):
31
+ """Terminology:
32
+ SOURCE = Self-Managed-Config-File-Path
33
+ TARGET = Config-File-Default-Path
34
+ For public config files, the source always exists, because we know it comes from machineconfig repo."""
35
+ from machineconfig.profile.create_links import ConfigMapper, read_mapper
36
+ mapper_full = read_mapper()["public"]
37
+ if which is None:
38
+ assert interactive is True
39
+ from machineconfig.utils.options import choose_from_options
40
+ items_chosen = choose_from_options(msg="Which symlink to create?", options=list(mapper_full.keys()), tv=True, multi=True)
41
+ else:
42
+ assert interactive is False
43
+ if which == "all":
44
+ items_chosen = list(mapper_full.keys())
45
+ else:
46
+ items_chosen = which.split(",")
47
+ items_objections: dict[str, list[ConfigMapper]] = {item: mapper_full[item] for item in items_chosen if item in mapper_full}
48
+ if len(items_objections) == 0:
49
+ typer.echo("[red]Error:[/] No valid items selected.")
50
+ typer.Exit(code=1)
51
+ return
52
+ from machineconfig.profile.create_links import apply_mapper
53
+ from machineconfig.profile.create_helper import copy_assets_to_machine
54
+ copy_assets_to_machine(which="settings") # config files live here and will be linked to.
55
+ method_map: dict[str, Literal["symlink", "copy"]] = {
56
+ "s": "symlink",
57
+ "symlink": "symlink",
58
+ "c": "copy",
59
+ "copy": "copy",
60
+ }
61
+ method = method_map[method]
62
+ apply_mapper(mapper_data=items_objections, on_conflict=ON_CONFLICT_MAPPER[on_conflict], method=method)
63
+
64
+
65
+ def main_private_from_parser(method: Annotated[Literal["symlink", "s", "copy", "c"], typer.Option(..., "--method", "-m", help="Method to use for linking files")],
66
+ on_conflict: Annotated[ON_CONFLICT_LOOSE, typer.Option(..., "--on-conflict", "-o", help="Action to take on conflict")] = "throw-error",
67
+ which: Annotated[Optional[str], typer.Option(..., "--which", "-w", help="Specific items to process")] = "all",
68
+ interactive: Annotated[bool, typer.Option(..., "--interactive", "-i", help="Run in interactive mode")] = False):
69
+ from machineconfig.profile.create_links import ConfigMapper, read_mapper
70
+ mapper_full = read_mapper()["private"]
71
+ if which is None:
72
+ if interactive is False:
73
+ typer.echo("[red]Error:[/] --which must be provided when not running in interactive mode.")
74
+ typer.Exit(code=1)
75
+ return
76
+ from machineconfig.utils.options import choose_from_options
77
+ items_chosen = choose_from_options(msg="Which symlink to create?", options=list(mapper_full.keys()), tv=True, multi=True)
78
+ else:
79
+ if interactive is True:
80
+ typer.echo("[yellow]Warning:[/] --which is provided, but its not allowed to be used together with --interactive. Ignoring --interactive flag.")
81
+ typer.Exit(code=0)
82
+ return
83
+ if which == "all":
84
+ items_chosen = list(mapper_full.keys())
85
+ else:
86
+ items_chosen = which.split(",")
87
+ items_objections: dict[str, list[ConfigMapper]] = {item: mapper_full[item] for item in items_chosen if item in mapper_full}
88
+ if len(items_objections) == 0:
89
+ typer.echo("[red]Error:[/] No valid items selected.")
90
+ typer.Exit(code=1)
91
+ return
92
+ from machineconfig.profile.create_links import apply_mapper
93
+ method_map: dict[str, Literal["symlink", "copy"]] = {
94
+ "s": "symlink",
95
+ "symlink": "symlink",
96
+ "c": "copy",
97
+ "copy": "copy",
98
+ }
99
+ method = method_map[method]
100
+ apply_mapper(mapper_data=items_objections, on_conflict=ON_CONFLICT_MAPPER[on_conflict], method=method)
@@ -0,0 +1,147 @@
1
+ """shell"""
2
+
3
+ from pathlib import Path
4
+
5
+
6
+
7
+ def get_shell_profile_path() -> Path:
8
+ import platform
9
+ import subprocess
10
+ from rich.console import Console
11
+ from rich.panel import Panel
12
+ system = platform.system()
13
+ console = Console()
14
+ if system == "Windows":
15
+ result = subprocess.run(["pwsh", "-Command", "$PROFILE"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False)
16
+ if result.returncode == 0 and result.stdout.strip():
17
+ profile_path = Path(result.stdout.strip())
18
+ else:
19
+ print(f"Command failed with return code {result.returncode}")
20
+ print(f"stdout: {result.stdout}")
21
+ print(f"stderr: {result.stderr}")
22
+ raise ValueError(f"""Could not get profile path for Windows. Got stdout: {result.stdout}, stderr: {result.stderr}""")
23
+ elif system == "Linux":
24
+ profile_path = Path.home().joinpath(".bashrc")
25
+ elif system == "Darwin":
26
+ profile_path = Path.home().joinpath(".zshrc")
27
+ else:
28
+ raise ValueError(f"""Not implemented for this system {system}""")
29
+ console.print(Panel(f"""🐚 SHELL PROFILE | Working with path: `{profile_path}`""", title="[bold blue]Shell Profile[/bold blue]", border_style="blue"))
30
+ return profile_path
31
+
32
+
33
+ def get_nu_shell_profile_path() -> Path:
34
+ import platform
35
+ from rich.console import Console
36
+ from rich.panel import Panel
37
+ system = platform.system()
38
+ console = Console()
39
+ if system == "Windows":
40
+ profile_path = Path.home().joinpath(r"AppData\Roaming\nushell")
41
+ elif system == "Linux":
42
+ profile_path = Path.home().joinpath(".config/nushell")
43
+ elif system == "Darwin":
44
+ profile_path = Path.home().joinpath("Library/Application Support/nushell")
45
+ else:
46
+ raise ValueError(f"""Not implemented for this system {system}""")
47
+ console.print(Panel(f"""🐚 NU SHELL PROFILE | Working with path: `{profile_path}`""", title="[bold cyan]Nu Shell Profile[/bold cyan]", border_style="cyan"))
48
+ return profile_path
49
+
50
+
51
+ def create_default_shell_profile() -> None:
52
+ shell_profile_path = get_shell_profile_path()
53
+ import platform
54
+ import subprocess
55
+ from rich.console import Console
56
+ from rich.panel import Panel
57
+ from machineconfig.utils.source_of_truth import CONFIG_ROOT
58
+ from machineconfig.utils.path_extended import PathExtended
59
+ system = platform.system()
60
+ console = Console()
61
+ if not shell_profile_path.exists():
62
+ console.print(Panel(f"""🆕 PROFILE | Profile does not exist at `{shell_profile_path}`. Creating a new one.""", title="[bold blue]Profile[/bold blue]", border_style="blue"))
63
+ shell_profile_path.parent.mkdir(parents=True, exist_ok=True)
64
+ shell_profile_path.write_text("", encoding="utf-8")
65
+ shell_profile = shell_profile_path.read_text(encoding="utf-8")
66
+ from machineconfig.profile.create_helper import copy_assets_to_machine
67
+ copy_assets_to_machine("settings") # init.ps1 or init.sh live here
68
+ copy_assets_to_machine("scripts") # init scripts are going to reference those scripts.
69
+ shell_name = ""
70
+ if system == "Windows":
71
+ shell_name = "pwsh"
72
+ init_script = PathExtended(CONFIG_ROOT).joinpath("settings/shells/pwsh/init.ps1")
73
+ source_line = f""". {str(init_script.collapseuser(placeholder="$HOME"))}"""
74
+ elif system == "Linux":
75
+ shell_name = "bash"
76
+ init_script = PathExtended(CONFIG_ROOT).joinpath("settings/shells/bash/init.sh")
77
+ source_line = f"""source {str(init_script.collapseuser(placeholder="$HOME"))}"""
78
+ elif system == "Darwin":
79
+ shell_name = "zsh"
80
+ init_script = PathExtended(CONFIG_ROOT).joinpath("settings/shells/zsh/init.sh")
81
+ source_line = f"""source {str(init_script.collapseuser(placeholder="$HOME"))}"""
82
+ else:
83
+ raise ValueError(f"""Not implemented for this system {system}""")
84
+
85
+ was_shell_updated = False
86
+ if source_line in shell_profile:
87
+ console.print(Panel("🔄 PROFILE | Skipping init script sourcing - already present in profile", title="[bold blue]Profile[/bold blue]", border_style="blue"))
88
+ else:
89
+ console.print(Panel("📝 PROFILE | Adding init script sourcing to profile", title="[bold blue]Profile[/bold blue]", border_style="blue"))
90
+ shell_profile += "\n" + source_line + "\n"
91
+ if shell_name == "bash":
92
+ result = subprocess.run(["cat", "/proc/version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False)
93
+ if result.returncode == 0 and result.stdout:
94
+ version_info = result.stdout.lower()
95
+ is_wsl = "microsoft" in version_info or "wsl" in version_info
96
+ if is_wsl:
97
+ shell_profile += "\ncd $HOME"
98
+ console.print("📌 WSL detected - adding 'cd $HOME' to profile to avoid Windows filesystem")
99
+ # Sync shell history between Windows and WSL
100
+ # https://www.hanselman.com/blog/sharing-powershell-history-between-windows-and-wsl
101
+ shell_profile += """
102
+ # Sync shell history between Windows and WSL
103
+ export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\\n'}history -a; history -c; history -r"
104
+ """
105
+ was_shell_updated = True
106
+ if was_shell_updated:
107
+ shell_profile_path.parent.mkdir(parents=True, exist_ok=True)
108
+ shell_profile_path.write_text(shell_profile, encoding="utf-8")
109
+ console.print(Panel("✅ Profile updated successfully", title="[bold blue]Profile[/bold blue]", border_style="blue"))
110
+
111
+
112
+ def create_nu_shell_profile() -> None:
113
+ from rich.console import Console
114
+ from rich.panel import Panel
115
+ from machineconfig.utils.source_of_truth import CONFIG_ROOT
116
+ from machineconfig.utils.path_extended import PathExtended
117
+ console = Console()
118
+ nu_profile_path = get_nu_shell_profile_path()
119
+ config_dir = nu_profile_path
120
+ config_file = config_dir.joinpath("config.nu")
121
+ if not config_dir.exists():
122
+ console.print(Panel(f"""🆕 NU SHELL CONFIG | Config directory does not exist at `{config_dir}`. Creating a new one.""", title="[bold cyan]Nu Shell Config[/bold cyan]", border_style="cyan"))
123
+ config_dir.mkdir(parents=True, exist_ok=True)
124
+ if not config_file.exists():
125
+ console.print(Panel(f"""🆕 NU SHELL CONFIG | config.nu file does not exist at `{config_file}`. Creating a new one.""", title="[bold cyan]Nu Shell Config[/bold cyan]", border_style="cyan"))
126
+ config_file.write_text("", encoding="utf-8")
127
+ config_content = config_file.read_text(encoding="utf-8")
128
+ from machineconfig.profile.create_helper import copy_assets_to_machine
129
+ copy_assets_to_machine("settings")
130
+ copy_assets_to_machine("scripts")
131
+ init_script = PathExtended(CONFIG_ROOT).joinpath("settings/shells/nushell/init.nu")
132
+ source_line = f"""use {str(init_script)}"""
133
+ was_config_updated = False
134
+ if source_line in config_content:
135
+ console.print(Panel("🔄 NU SHELL CONFIG | Skipping init script sourcing - already present in config.nu", title="[bold cyan]Nu Shell Config[/bold cyan]", border_style="cyan"))
136
+ else:
137
+ console.print(Panel("📝 NU SHELL CONFIG | Adding init script sourcing to config.nu", title="[bold cyan]Nu Shell Config[/bold cyan]", border_style="cyan"))
138
+ config_content += "\n" + source_line + "\n"
139
+ was_config_updated = True
140
+ if was_config_updated:
141
+ config_dir.mkdir(parents=True, exist_ok=True)
142
+ config_file.write_text(config_content, encoding="utf-8")
143
+ console.print(Panel("✅ Nu shell config updated successfully", title="[bold cyan]Nu Shell Config[/bold cyan]", border_style="cyan"))
144
+
145
+
146
+ if __name__ == "__main__":
147
+ pass