machineconfig 3.93__py3-none-any.whl → 3.95__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.

Potentially problematic release.


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

Files changed (79) hide show
  1. machineconfig/jobs/{python_custom_installers → installer/custom}/gh.py +22 -7
  2. machineconfig/jobs/{python_custom_installers → installer/custom}/hx.py +13 -4
  3. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/alacritty.py +11 -5
  4. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/brave.py +17 -14
  5. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/bypass_paywall.py +7 -9
  6. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/code.py +13 -13
  7. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/cursor.py +7 -7
  8. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/espanso.py +21 -17
  9. machineconfig/jobs/installer/custom_dev/goes.py +63 -0
  10. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/lvim.py +10 -14
  11. machineconfig/jobs/installer/custom_dev/nerdfont.py +87 -0
  12. machineconfig/{setup_windows/wt_and_pwsh/install_nerd_fonts.py → jobs/installer/custom_dev/nerfont_windows_helper.py} +68 -25
  13. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/redis.py +13 -8
  14. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/wezterm.py +13 -7
  15. machineconfig/jobs/{python_custom_installers/dev → installer/custom_dev}/winget.py +1 -3
  16. machineconfig/jobs/installer/packages_custom_dev.json +226 -0
  17. machineconfig/jobs/installer/packages_custom_essential.json +39 -0
  18. machineconfig/jobs/installer/packages_github_dev.json +1110 -0
  19. machineconfig/jobs/installer/packages_github_essential.json +804 -0
  20. machineconfig/jobs/linux/msc/cli_agents.sh +5 -0
  21. machineconfig/profile/create.py +5 -1
  22. machineconfig/scripts/linux/devops +1 -1
  23. machineconfig/scripts/python/ai/solutions/gemini/settings.json +1 -1
  24. machineconfig/scripts/python/devops.py +126 -65
  25. machineconfig/scripts/python/devops_devapps_install.py +30 -19
  26. machineconfig/setup_linux/web_shortcuts/interactive.py +267 -0
  27. machineconfig/setup_linux/web_shortcuts/interactive.sh +6 -152
  28. machineconfig/utils/installer.py +17 -80
  29. machineconfig/utils/installer_utils/github_release_bulk.py +198 -0
  30. machineconfig/utils/installer_utils/installer_class.py +223 -210
  31. machineconfig/utils/schemas/installer/installer_types.py +29 -6
  32. {machineconfig-3.93.dist-info → machineconfig-3.95.dist-info}/METADATA +2 -1
  33. {machineconfig-3.93.dist-info → machineconfig-3.95.dist-info}/RECORD +50 -71
  34. machineconfig/jobs/python_custom_installers/archive/ngrok.py +0 -63
  35. machineconfig/jobs/python_custom_installers/dev/aider.py +0 -37
  36. machineconfig/jobs/python_custom_installers/dev/docker_desktop.py +0 -78
  37. machineconfig/jobs/python_custom_installers/dev/goes.py +0 -55
  38. machineconfig/jobs/python_custom_installers/dev/nerdfont.py +0 -68
  39. machineconfig/jobs/python_custom_installers/dev/reverse_proxy.md +0 -31
  40. machineconfig/jobs/python_custom_installers/docker.py +0 -74
  41. machineconfig/jobs/python_custom_installers/warp-cli.py +0 -71
  42. machineconfig/jobs/python_generic_installers/config.json +0 -603
  43. machineconfig/jobs/python_generic_installers/config.json.bak +0 -414
  44. machineconfig/jobs/python_generic_installers/dev/config.archive.json +0 -18
  45. machineconfig/jobs/python_generic_installers/dev/config.json +0 -825
  46. machineconfig/jobs/python_generic_installers/dev/config.json.bak +0 -565
  47. machineconfig/jobs/python_linux_installers/__init__.py +0 -0
  48. machineconfig/jobs/python_linux_installers/archive/config.json +0 -18
  49. machineconfig/jobs/python_linux_installers/archive/config.json.bak +0 -10
  50. machineconfig/jobs/python_linux_installers/config.json +0 -145
  51. machineconfig/jobs/python_linux_installers/config.json.bak +0 -110
  52. machineconfig/jobs/python_linux_installers/dev/__init__.py +0 -0
  53. machineconfig/jobs/python_linux_installers/dev/config.json +0 -276
  54. machineconfig/jobs/python_linux_installers/dev/config.json.bak +0 -206
  55. machineconfig/jobs/python_windows_installers/__init__.py +0 -0
  56. machineconfig/jobs/python_windows_installers/archive/__init__.py +0 -0
  57. machineconfig/jobs/python_windows_installers/archive/file.json +0 -11
  58. machineconfig/jobs/python_windows_installers/config.json +0 -82
  59. machineconfig/jobs/python_windows_installers/config.json.bak +0 -56
  60. machineconfig/jobs/python_windows_installers/dev/__init__.py +0 -0
  61. machineconfig/jobs/python_windows_installers/dev/config.json +0 -4
  62. machineconfig/jobs/python_windows_installers/dev/config.json.bak +0 -3
  63. /machineconfig/jobs/{python_custom_installers → installer}/__init__.py +0 -0
  64. /machineconfig/jobs/{python_generic_installers → installer/custom_dev}/__init__.py +0 -0
  65. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/brave.sh +0 -0
  66. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/docker.sh +0 -0
  67. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/docker_start.sh +0 -0
  68. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/edge.sh +0 -0
  69. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/nerdfont.sh +0 -0
  70. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/pgsql.sh +0 -0
  71. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/redis.sh +0 -0
  72. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/timescaledb.sh +0 -0
  73. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/vscode.sh +0 -0
  74. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/warp-cli.sh +0 -0
  75. /machineconfig/jobs/{python_custom_installers/scripts/linux → installer/linux_scripts}/wezterm.sh +0 -0
  76. /machineconfig/{setup_windows/wt_and_pwsh → jobs/installer/powershell_scripts}/install_fonts.ps1 +0 -0
  77. {machineconfig-3.93.dist-info → machineconfig-3.95.dist-info}/WHEEL +0 -0
  78. {machineconfig-3.93.dist-info → machineconfig-3.95.dist-info}/entry_points.txt +0 -0
  79. {machineconfig-3.93.dist-info → machineconfig-3.95.dist-info}/top_level.txt +0 -0
@@ -2,10 +2,14 @@
2
2
 
3
3
 
4
4
  # Terminal-based CLI agents and tools for productivity and coding.
5
+ npm install -g @github/copilot
5
6
  npm install -g @google/gemini-cli
6
7
  npm install -g @charmland/crush
7
8
  npm install -g opencode-ai@latest # or curl -fsSL https://opencode.ai/install | bash
8
9
  uv tool install --force --python python3.12 --with pip aider-chat@latest
10
+ curl -fsSL https://app.factory.ai/cli | sh
11
+ # WARP TERMINAL CLI
12
+ # droid
9
13
 
10
14
 
11
15
  # cursor-cli
@@ -29,4 +33,5 @@ rm -rfd q
29
33
  # Editors based on AI
30
34
  # Kiro
31
35
  # Cursor
36
+ # Warp
32
37
 
@@ -147,11 +147,15 @@ def apply_mapper(choice: Optional[str] = None):
147
147
  """)
148
148
 
149
149
 
150
- def main():
150
+ def main_symlinks():
151
151
  console = Console()
152
152
  print("\n")
153
153
  console.rule("[bold blue]🔗 CREATING SYMLINKS 🔗")
154
154
  apply_mapper(choice="all")
155
+
156
+
157
+ def main_profile():
158
+ console = Console()
155
159
  print("\n")
156
160
  console.rule("[bold green]🐚 CREATING SHELL PROFILE 🐚")
157
161
  create_default_shell_profile()
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env bash
2
- uv run --python 3.13 --no-dev --project $HOME/code/machineconfig devops
2
+ uv run --python 3.13 --no-dev --project $HOME/code/machineconfig devops "$@"
@@ -69,7 +69,7 @@
69
69
  "customThemes": {
70
70
  "MyCustomTheme": {
71
71
  "name": "MyCustomTheme",
72
- "type": "custom",
72
+ "type": "CMD",
73
73
  "Background": "#181818",
74
74
  "Foreground": "#F8F8F2",
75
75
  "AccentBlue": "#61AFEF",
@@ -6,24 +6,131 @@ from platform import system
6
6
  from typing import Optional, Literal, TypeAlias
7
7
  from rich.console import Console
8
8
  from rich.panel import Panel
9
+ import typer
9
10
 
10
11
  console = Console()
12
+ app = typer.Typer(help="🛠️ DevOps operations with emojis", invoke_without_command=True, no_args_is_help=True)
11
13
 
12
14
  BOX_WIDTH = 150 # width for box drawing
13
15
 
14
16
 
15
- Options: TypeAlias = Literal["🔄 UPDATE essential repos", "⚙️ DEVAPPS install", "🔗 SYMLINKS, SHELL PROFILE, FONT, TERMINAL SETTINGS.", "🆕 SYMLINKS new", "🔑 SSH add pub key to this machine", "🗝️ SSH add identity (private key) to this machine", "🔐 SSH use key pair to connect two machines", "📡 SSH setup", "🐧 SSH setup wsl", "💾 BACKUP", "📥 RETRIEVE", "⏰ SCHEDULER"]
17
+ COMMANDS: TypeAlias = Literal["🔄 UPDATE essential repos", "⚙️ DEVAPPS install", "🔗 SYMLINKS, SHELL PROFILE, FONT, TERMINAL SETTINGS.", "🆕 SYMLINKS new", "🔑 SSH add pub key to this machine", "🗝️ SSH add identity (private key) to this machine", "🔐 SSH use key pair to connect two machines", "📡 SSH setup", "🐧 SSH setup wsl", "💾 BACKUP", "📥 RETRIEVE", "⏰ SCHEDULER"]
16
18
 
17
- options_list = list(Options.__args__)
19
+ options_list = list(COMMANDS.__args__)
20
+
21
+
22
+ @app.command()
23
+ def update():
24
+ """🔄 UPDATE essential repos"""
25
+ console.print(Panel("🔄 Updating essential repositories...", width=BOX_WIDTH, border_style="blue"))
26
+ import machineconfig.scripts.python.devops_update_repos as helper
27
+ helper.main()
28
+
29
+
30
+ @app.command()
31
+ def install():
32
+ """⚙️ DEVAPPS install"""
33
+ console.print(Panel("⚙️ Installing development applications...", width=BOX_WIDTH, border_style="blue"))
34
+ import machineconfig.scripts.python.devops_devapps_install as helper
35
+ helper.main(which=None)
36
+
37
+
38
+ @app.command()
39
+ def symlinks():
40
+ """🔗 SYMLINKS of dotfiles."""
41
+ console.print(Panel("🔗 Setting up symlinks, PATH, and shell profile...", width=BOX_WIDTH, border_style="blue"))
42
+ import machineconfig.profile.create as helper
43
+ helper.main_symlinks()
44
+
45
+
46
+ @app.command()
47
+ def profile():
48
+ """🔗 Update shell profile."""
49
+ console.print(Panel("🔗 Setting up symlinks, PATH, and shell profile...", width=BOX_WIDTH, border_style="blue"))
50
+ import machineconfig.profile.create as helper
51
+ helper.main_profile()
52
+
53
+
54
+ @app.command()
55
+ def symlinks_new():
56
+ """🆕 SYMLINKS new"""
57
+ console.print(Panel("🔄 Creating new symlinks...", width=BOX_WIDTH, border_style="blue"))
58
+ import machineconfig.jobs.python.python_ve_symlink as helper
59
+ helper.main()
60
+
61
+
62
+ @app.command()
63
+ def ssh_add_key():
64
+ """🔑 SSH add pub key to this machine"""
65
+ console.print(Panel("🔑 Adding public SSH key to this machine...", width=BOX_WIDTH, border_style="blue"))
66
+ import machineconfig.scripts.python.devops_add_ssh_key as helper
67
+ helper.main()
68
+
69
+
70
+ @app.command()
71
+ def ssh_add_identity():
72
+ """🗝️ SSH add identity (private key) to this machine"""
73
+ console.print(Panel("🗝️ Adding SSH identity (private key) to this machine...", width=BOX_WIDTH, border_style="blue"))
74
+ import machineconfig.scripts.python.devops_add_identity as helper
75
+ helper.main()
76
+
77
+
78
+ @app.command()
79
+ def ssh_connect():
80
+ """🔐 SSH use key pair to connect two machines"""
81
+ console.print(Panel("❌ ERROR: Not Implemented\nSSH key pair connection feature is not yet implemented", title_align="left", border_style="red", width=BOX_WIDTH))
82
+ raise NotImplementedError
83
+
84
+
85
+ @app.command()
86
+ def ssh_setup():
87
+ """📡 SSH setup"""
88
+ console.print(Panel("📡 Setting up SSH...", width=BOX_WIDTH, border_style="blue"))
89
+ _program_windows = """Invoke-WebRequest https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_windows/openssh_all.ps1 | Invoke-Expression # https://github.com/thisismygitrepo.keys"""
90
+ _program_linux = """curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_all.sh | sudo bash # https://github.com/thisismygitrepo.keys"""
91
+ import subprocess
92
+ subprocess.run(_program_linux if system() == "Linux" else _program_windows, shell=True, check=True)
93
+
94
+
95
+ @app.command()
96
+ def ssh_setup_wsl():
97
+ """🐧 SSH setup wsl"""
98
+ console.print(Panel("🐧 Setting up SSH for WSL...", width=BOX_WIDTH, border_style="blue"))
99
+ import subprocess
100
+ subprocess.run("curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_wsl.sh | sudo bash", shell=True, check=True)
101
+
102
+
103
+ @app.command()
104
+ def backup():
105
+ """💾 BACKUP"""
106
+ console.print(Panel("💾 Creating backup...", width=BOX_WIDTH, border_style="blue"))
107
+ from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
108
+ main_backup_retrieve(direction="BACKUP")
109
+
110
+
111
+ @app.command()
112
+ def retrieve():
113
+ """📥 RETRIEVE"""
114
+ console.print(Panel("📥 Retrieving backup...", width=BOX_WIDTH, border_style="blue"))
115
+ from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
116
+ main_backup_retrieve(direction="RETRIEVE")
117
+
118
+
119
+ @app.command()
120
+ def scheduler():
121
+ """⏰ SCHEDULER"""
122
+ console.print(Panel("⏰ Setting up scheduler...", width=BOX_WIDTH, border_style="blue"))
123
+ # from machineconfig.scripts.python.scheduler import main as helper
124
+ # helper()
18
125
 
19
126
 
20
127
  def args_parser():
21
- import typer
22
- typer.run(main)
128
+ app()
23
129
 
24
130
 
25
- def main(which: Optional[Options] = None):
26
- # PathExtended(_program_PATH).delete(sure=True, verbose=False)
131
+ @app.command()
132
+ def interactive(which: Optional[COMMANDS] = None):
133
+ """🛠️ Interactive menu mode (legacy)"""
27
134
  console.print(Panel("🚀 Initializing DevOps operation...", width=BOX_WIDTH, border_style="blue"))
28
135
  options = options_list
29
136
  if which is None:
@@ -38,75 +145,29 @@ def main(which: Optional[Options] = None):
38
145
  console.print(Panel(f"🔧 SELECTED OPERATION\n{choice_key}", title_align="left", border_style="green", width=BOX_WIDTH))
39
146
 
40
147
  if choice_key == "🔄 UPDATE essential repos":
41
- console.print(Panel("🔄 Updating essential repositories...", width=BOX_WIDTH, border_style="blue"))
42
- import machineconfig.scripts.python.devops_update_repos as helper
43
-
44
- helper.main()
148
+ update()
45
149
  elif choice_key == "⚙️ DEVAPPS install":
46
- console.print(Panel("⚙️ Installing development applications...", width=BOX_WIDTH, border_style="blue"))
47
- import machineconfig.scripts.python.devops_devapps_install as helper
48
-
49
- helper.main(which=None)
50
-
150
+ install()
51
151
  elif choice_key == "🆕 SYMLINKS new":
52
- console.print(Panel("🔄 Creating new symlinks...", width=BOX_WIDTH, border_style="blue"))
53
- import machineconfig.jobs.python.python_ve_symlink as helper
54
-
55
- helper.main()
56
-
152
+ symlinks_new()
57
153
  elif choice_key == "🔗 SYMLINKS, SHELL PROFILE, FONT, TERMINAL SETTINGS.":
58
- console.print(Panel("🔗 Setting up symlinks, PATH, and shell profile...", width=BOX_WIDTH, border_style="blue"))
59
- import machineconfig.profile.create as helper
60
-
61
- helper.main()
62
- "echo '✅ done with symlinks'"
63
-
154
+ symlinks()
64
155
  elif choice_key == "🔑 SSH add pub key to this machine":
65
- console.print(Panel("🔑 Adding public SSH key to this machine...", width=BOX_WIDTH, border_style="blue"))
66
- import machineconfig.scripts.python.devops_add_ssh_key as helper
67
-
68
- helper.main()
69
-
156
+ ssh_add_key()
70
157
  elif choice_key == "🔐 SSH use key pair to connect two machines":
71
- console.print(Panel("❌ ERROR: Not Implemented\nSSH key pair connection feature is not yet implemented", title_align="left", border_style="red", width=BOX_WIDTH))
72
- raise NotImplementedError
73
-
74
- elif choice_key == "🗝️ SSH add identity (private key) to this machine": # so that you can SSH directly withuot pointing to identity key.
75
- console.print(Panel("🗝️ Adding SSH identity (private key) to this machine...", width=BOX_WIDTH, border_style="blue"))
76
- import machineconfig.scripts.python.devops_add_identity as helper
77
-
78
- helper.main()
79
-
158
+ ssh_connect()
159
+ elif choice_key == "🗝️ SSH add identity (private key) to this machine":
160
+ ssh_add_identity()
80
161
  elif choice_key == "📡 SSH setup":
81
- console.print(Panel("📡 Setting up SSH...", width=BOX_WIDTH, border_style="blue"))
82
- _program_windows = """Invoke-WebRequest https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_windows/openssh_all.ps1 | Invoke-Expression # https://github.com/thisismygitrepo.keys"""
83
- _program_linux = """curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_all.sh | sudo bash # https://github.com/thisismygitrepo.keys"""
84
- _program_linux if system() == "Linux" else _program_windows
85
- import subprocess
86
-
87
- subprocess.run(_program_linux if system() == "Linux" else _program_windows, shell=True, check=True)
88
-
162
+ ssh_setup()
89
163
  elif choice_key == "🐧 SSH setup wsl":
90
- console.print(Panel("🐧 Setting up SSH for WSL...", width=BOX_WIDTH, border_style="blue"))
91
- """curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/openssh_wsl.sh | sudo bash"""
92
-
164
+ ssh_setup_wsl()
93
165
  elif choice_key == "💾 BACKUP":
94
- console.print(Panel("💾 Creating backup...", width=BOX_WIDTH, border_style="blue"))
95
- from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
96
-
97
- main_backup_retrieve(direction="BACKUP")
98
-
166
+ backup()
99
167
  elif choice_key == "📥 RETRIEVE":
100
- console.print(Panel("📥 Retrieving backup...", width=BOX_WIDTH, border_style="blue"))
101
- from machineconfig.scripts.python.devops_backup_retrieve import main_backup_retrieve
102
-
103
- main_backup_retrieve(direction="RETRIEVE")
104
-
168
+ retrieve()
105
169
  elif choice_key == "⏰ SCHEDULER":
106
- console.print(Panel("⏰ Setting up scheduler...", width=BOX_WIDTH, border_style="blue"))
107
- # from machineconfig.scripts.python.scheduler import main as helper
108
- # helper()
109
-
170
+ scheduler()
110
171
  else:
111
172
  console.print(Panel("❌ ERROR: Invalid choice", title_align="left", border_style="red", width=BOX_WIDTH))
112
173
  raise ValueError(f"Unimplemented choice: {choice_key}")
@@ -6,6 +6,7 @@ from rich.progress import Progress, SpinnerColumn, TextColumn
6
6
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT
7
7
  from machineconfig.utils.options import choose_from_options
8
8
  from machineconfig.utils.installer import get_installers, install_all
9
+ from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
9
10
  from platform import system
10
11
  from typing import Any, Optional, Literal, TypeAlias, get_args, Annotated
11
12
 
@@ -26,8 +27,7 @@ def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category
26
27
  if which is not None: # install by name
27
28
  total_messages: list[str] = []
28
29
  for a_which in which.split(",") if type(which) == str else which:
29
- # Use get_installers to get properly converted installer objects
30
- all_installers = get_installers(system=system(), dev=False) + get_installers(system=system(), dev=True)
30
+ all_installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL", "GITHUB_DEV", "CUSTOM_DEV"])
31
31
 
32
32
  # Find installer by exe_name or name
33
33
  selected_installer = None
@@ -53,33 +53,43 @@ def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category
53
53
  print(a_message)
54
54
  return None
55
55
 
56
- # interactive installation - get all installers including dev ones
57
- installers = get_installers(system=system(), dev=True)
58
-
56
+ installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL", "GITHUB_DEV", "CUSTOM_DEV"])
59
57
  # Check installed programs with progress indicator
60
58
  with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
61
59
  task = progress.add_task("✅ Checking installed programs...", total=len(installers))
62
- options = []
60
+ installer_options = []
63
61
  for x in installers:
64
- options.append(x.get_description())
62
+ installer_options.append(x.get_description())
65
63
  progress.update(task, advance=1)
66
64
 
67
- options += list(get_args(WHICH_CAT))
68
- # print("s"*1000)
69
- program_names = choose_from_options(multi=True, msg="", options=options, header="🚀 CHOOSE DEV APP", default="essentials", fzf=True)
65
+ # Add category options at the beginning for better visibility
66
+ category_options = [f"📦 {cat}" for cat in get_args(WHICH_CAT)]
67
+ options = category_options + ["" * 50] + installer_options
68
+
69
+ program_names = choose_from_options(multi=True, msg="Categories are prefixed with 📦", options=options, header="🚀 CHOOSE DEV APP OR CATEGORY", default="📦 essentials", fzf=True)
70
70
 
71
71
  total_commands = ""
72
72
  installation_messages: list[str] = []
73
73
  for _an_idx, a_program_name in enumerate(program_names):
74
+ # Skip separator lines
75
+ if a_program_name.startswith("─"):
76
+ continue
77
+
74
78
  print(f"""
75
79
  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
76
80
  ┃ 🔄 Processing: {a_program_name}
77
81
  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
78
- if a_program_name in get_args(WHICH_CAT):
79
- shell_commands = get_programs_by_category(program_name=a_program_name) # type: ignore
80
- total_commands += "\n" + shell_commands
82
+
83
+ # Handle category options (remove emoji prefix)
84
+ if a_program_name.startswith("📦 "):
85
+ category_name = a_program_name[2:] # Remove "📦 " prefix
86
+ if category_name in get_args(WHICH_CAT):
87
+ shell_commands = get_programs_by_category(program_name=category_name) # type: ignore
88
+ total_commands += "\n" + shell_commands
81
89
  else:
82
- an_installer = installers[options.index(a_program_name)]
90
+ # Handle individual installer options
91
+ installer_idx = installer_options.index(a_program_name)
92
+ an_installer = installers[installer_idx]
83
93
  status_message = an_installer.install_robust(version=None) # finish the task - this returns a status message, not a command
84
94
  installation_messages.append(status_message)
85
95
 
@@ -103,13 +113,14 @@ def get_programs_by_category(program_name: WHICH_CAT):
103
113
  ┃ 📦 Installing Category: {program_name}
104
114
  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
105
115
  match program_name:
106
- case "essentials" | "essentialsDev":
107
- installers_ = get_installers(dev=False, system=system())
108
- if program_name == "essentialsDev":
109
- installers_ += get_installers(dev=True, system=system())
116
+ case "essentials":
117
+ installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
118
+ install_all(installers=installers_)
119
+ program = ""
120
+ case "essentialsDev":
121
+ installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_DEV", "CUSTOM_DEV", "GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
110
122
  install_all(installers=installers_)
111
123
  program = ""
112
-
113
124
  case "systymPackages":
114
125
  if system() == "Windows":
115
126
  options_system = parse_apps_installer_windows(LIBRARY_ROOT.joinpath("setup_windows/apps.ps1").read_text(encoding="utf-8"))
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Interactive Machine Configuration Setup Script
4
+
5
+ A Python version of the interactive installation script that uses questionary
6
+ for better user experience with checkbox selections.
7
+
8
+
9
+ # echo # 📧 Thunderbird Setup Note:
10
+ # Run after installing Thunderbird and starting it once:
11
+ # cd ~/AppData/Roaming/ThunderBird/Profiles
12
+ # $res = ls
13
+ # $name = $res[0].Name
14
+ # mv $backup_folder $name
15
+ #
16
+
17
+
18
+ """
19
+
20
+ import subprocess
21
+ import sys
22
+
23
+ import questionary
24
+ from questionary import Choice
25
+ from rich.console import Console
26
+ from rich.panel import Panel
27
+ from rich.text import Text
28
+
29
+
30
+ console = Console()
31
+
32
+
33
+ def run_command(command: str, description: str) -> bool:
34
+ """Execute a shell command and return success status."""
35
+ console.print(f"\n🔧 {description}", style="bold cyan")
36
+ try:
37
+ result = subprocess.run(command, shell=True, check=True, capture_output=False)
38
+ return result.returncode == 0
39
+ except subprocess.CalledProcessError as e:
40
+ console.print(f"❌ Error executing command: {e}", style="bold red")
41
+ return False
42
+
43
+
44
+ def display_header() -> None:
45
+ """Display the script header."""
46
+ header_text = Text("MACHINE CONFIGURATION", style="bold magenta")
47
+ subtitle_text = Text("Interactive Installation Script", style="italic cyan")
48
+ console.print(Panel(
49
+ f"📦 {header_text}\n{subtitle_text}",
50
+ border_style="blue",
51
+ padding=(1, 2)
52
+ ))
53
+
54
+
55
+ def display_completion_message() -> None:
56
+ """Display completion message."""
57
+ completion_text = Text("INSTALLATION COMPLETE", style="bold green")
58
+ subtitle_text = Text("System setup finished successfully", style="italic green")
59
+ console.print(Panel(
60
+ f"✨ {completion_text}\n{subtitle_text}\n\n🎉 Your system has been configured successfully!\n🔄 You may need to reboot to apply all changes.",
61
+ border_style="green",
62
+ padding=(1, 2)
63
+ ))
64
+
65
+
66
+ def display_dotfiles_instructions() -> None:
67
+ """Display instructions for dotfiles migration."""
68
+ header_text = Text("DOTFILES MIGRATION", style="bold yellow")
69
+ subtitle_text = Text("Configuration transfer options", style="italic yellow")
70
+
71
+ instructions = """🖱️ [bold blue]Method 1: USING MOUSE WITHOUT KB OR BROWSER SHARE[/bold blue]
72
+ On original machine, run:
73
+ [dim]cd ~/dotfiles/creds/msc
74
+ easy-sharing . --password rew --username al[/dim]
75
+ Then open brave on new machine to get MouseWithoutBorders password
76
+
77
+ 🔐 [bold blue]Method 2: USING SSH[/bold blue]
78
+ FROM REMOTE, RUN:
79
+ [dim]fptx ~/dotfiles $USER@$(hostname):^ -z
80
+ # OR, using IP address if router has not yet found the hostname:
81
+ fptx ~/dotfiles $USER@$(hostname -I | awk '{print $1}'):^ -z[/dim]
82
+
83
+ ☁️ [bold blue]Method 3: USING INTERNET SECURE SHARE[/bold blue]
84
+ [dim]cd ~
85
+ cloud_copy SHARE_URL . --config ss[/dim]
86
+ (requires symlinks to be created first)"""
87
+
88
+ console.print(Panel(
89
+ f"📂 {header_text}\n{subtitle_text}\n\n{instructions}",
90
+ border_style="yellow",
91
+ padding=(1, 2)
92
+ ))
93
+
94
+
95
+ def get_installation_choices() -> list[str]:
96
+ """Get user choices for installation options."""
97
+ choices = [
98
+ Choice(value="install_apps", title="📥 Install Apps - Install base system applications", checked=False),
99
+ Choice(value="upgrade_system", title="🔄 Upgrade System Packages - Update all system packages", checked=False),
100
+ Choice(value="install_uv_repos", title="🐍 Install UV and Repos - Set up Python environment and repositories", checked=False),
101
+ Choice(value="install_ssh_server", title="🔒 Install SSH Server - Set up remote access", checked=False),
102
+ Choice(value="create_symlinks", title="🔗 Create Symlinks - Set up configuration symlinks (finish dotfiles transfer first)", checked=False),
103
+ Choice(value="install_cli_apps", title="⚡ Install CLI Apps - Command-line tools installation", checked=False),
104
+ Choice(value="install_dev_tools", title="🛠️ Install Development Tools - rust, libssl-dev, ffmpeg, wezterm, brave, code", checked=False),
105
+ Choice(value="retrieve_repositories", title="📚 Retrieve Repositories - Clone repositories to ~/code", checked=False),
106
+ Choice(value="retrieve_data", title="💾 Retrieve Data - Backup restoration", checked=False),
107
+ Choice(value="install_ascii_art", title="🎨 Install ASCII Art Libraries - Terminal visualization tools", checked=False),
108
+ ]
109
+
110
+ selected = questionary.checkbox(
111
+ "Select the installation options you want to execute:",
112
+ choices=choices,
113
+ show_description=True,
114
+ ).ask()
115
+
116
+ return selected or []
117
+
118
+
119
+ def execute_installations(selected_options: list[str]) -> None:
120
+ """Execute the selected installation options."""
121
+ # Always start with VE setup
122
+ console.print(Panel(
123
+ "🐍 [bold green]PYTHON ENVIRONMENT[/bold green]\n[italic]Setting up base virtual environment[/italic]",
124
+ border_style="green"
125
+ ))
126
+ run_command(
127
+ "curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/ve.sh | bash",
128
+ "Setting up base virtual environment"
129
+ )
130
+
131
+ if "install_apps" in selected_options:
132
+ console.print(Panel(
133
+ "📦 [bold blue]APPLICATIONS[/bold blue]\n[italic]Installing base system applications[/italic]",
134
+ border_style="blue"
135
+ ))
136
+ run_command(
137
+ "curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/apps.sh | bash",
138
+ "Installing base system applications"
139
+ )
140
+
141
+ if "upgrade_system" in selected_options:
142
+ console.print(Panel(
143
+ "🔄 [bold magenta]SYSTEM UPDATE[/bold magenta]\n[italic]Package management[/italic]",
144
+ border_style="magenta"
145
+ ))
146
+ run_command("sudo nala upgrade -y", "Upgrading system packages")
147
+
148
+ if "install_uv_repos" in selected_options:
149
+ console.print(Panel(
150
+ "🐍 [bold green]PYTHON ENVIRONMENT[/bold green]\n[italic]Virtual environment setup[/italic]",
151
+ border_style="green"
152
+ ))
153
+ run_command(
154
+ "curl https://raw.githubusercontent.com/thisismygitrepo/machineconfig/main/src/machineconfig/setup_linux/repos.sh | bash",
155
+ "Setting up Python environment and repositories"
156
+ )
157
+
158
+ if "install_ssh_server" in selected_options:
159
+ console.print(Panel(
160
+ "🔒 [bold red]SSH SERVER[/bold red]\n[italic]Remote access setup[/italic]",
161
+ border_style="red"
162
+ ))
163
+ run_command("sudo nala install openssh-server -y", "Installing SSH server")
164
+
165
+ # Always display dotfiles instructions if symlinks are selected
166
+ if "create_symlinks" in selected_options:
167
+ display_dotfiles_instructions()
168
+
169
+ dotfiles_ready = questionary.confirm(
170
+ "📂 Have you finished copying dotfiles?",
171
+ default=True
172
+ ).ask()
173
+
174
+ if dotfiles_ready:
175
+ console.print(Panel(
176
+ "🔗 [bold cyan]SYMLINK CREATION[/bold cyan]\n[italic]Configuration setup[/italic]",
177
+ border_style="cyan"
178
+ ))
179
+ run_command(
180
+ "uv run --python 3.13 --with machineconfig python -m fire machineconfig.profile.create main_symlinks --choice=all",
181
+ "Creating symlinks"
182
+ )
183
+ run_command("sudo chmod 600 $HOME/.ssh/*", "Setting SSH key permissions")
184
+ run_command("sudo chmod 700 $HOME/.ssh", "Setting SSH directory permissions")
185
+ else:
186
+ console.print("⏭️ Skipping symlink creation - finish dotfiles transfer first", style="yellow")
187
+
188
+ if "install_cli_apps" in selected_options:
189
+ console.print(Panel(
190
+ "⚡ [bold bright_yellow]CLI APPLICATIONS[/bold bright_yellow]\n[italic]Command-line tools installation[/italic]",
191
+ border_style="bright_yellow"
192
+ ))
193
+ run_command(
194
+ "uv run --python 3.13 --with machineconfig python -m fire machineconfig.scripts.python.devops_devapps_install main --which=essentials",
195
+ "Installing CLI applications"
196
+ )
197
+ run_command(". $HOME/.bashrc", "Reloading bash configuration")
198
+
199
+ if "install_dev_tools" in selected_options:
200
+ console.print(Panel(
201
+ "🛠️ [bold bright_blue]DEVELOPMENT TOOLS[/bold bright_blue]\n[italic]Software development packages[/italic]",
202
+ border_style="bright_blue"
203
+ ))
204
+ run_command(
205
+ "(curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh) || true",
206
+ "Installing Rust toolchain"
207
+ )
208
+ run_command("sudo nala install libssl-dev -y", "Installing libssl-dev")
209
+ run_command("sudo nala install ffmpeg -y", "Installing ffmpeg")
210
+ run_command(
211
+ "uv run --python 3.13 --with machineconfig python -m fire machineconfig.scripts.python.devops_devapps_install main --which=wezterm,brave,code",
212
+ "Installing development applications"
213
+ )
214
+
215
+ if "retrieve_repositories" in selected_options:
216
+ console.print(Panel(
217
+ "📚 [bold bright_magenta]REPOSITORIES[/bold bright_magenta]\n[italic]Project code retrieval[/italic]",
218
+ border_style="bright_magenta"
219
+ ))
220
+ run_command("repos ~/code --clone --cloud odg1", "Cloning repositories")
221
+
222
+ if "retrieve_data" in selected_options:
223
+ console.print(Panel(
224
+ "💾 [bold bright_cyan]DATA RETRIEVAL[/bold bright_cyan]\n[italic]Backup restoration[/italic]",
225
+ border_style="bright_cyan"
226
+ ))
227
+ run_command(
228
+ "uv run --python 3.13 --with machineconfig python -m fire machineconfig.scripts.python.devops_backup_retrieve main --direction=RETRIEVE",
229
+ "Retrieving backup data"
230
+ )
231
+
232
+ if "install_ascii_art" in selected_options:
233
+ console.print(Panel(
234
+ "🎨 [bold bright_green]ASCII ART[/bold bright_green]\n[italic]Terminal visualization tools[/italic]",
235
+ border_style="bright_green"
236
+ ))
237
+ run_command("curl bit.ly/cfgasciiartlinux -L | sudo bash", "Installing ASCII art libraries")
238
+
239
+
240
+ def main() -> None:
241
+ """Main function to run the interactive installation."""
242
+ display_header()
243
+
244
+ # Get user selections
245
+ selected_options = get_installation_choices()
246
+
247
+ if not selected_options:
248
+ console.print("❌ No options selected. Exiting...", style="bold red")
249
+ sys.exit(0)
250
+
251
+ console.print(f"\n✅ Selected options: {', '.join(selected_options)}", style="bold green")
252
+
253
+ # Confirm before proceeding
254
+ proceed = questionary.confirm("🚀 Proceed with installation?", default=True).ask()
255
+
256
+ if not proceed:
257
+ console.print("❌ Installation cancelled.", style="bold red")
258
+ sys.exit(0)
259
+
260
+ # Execute installations
261
+ execute_installations(selected_options)
262
+
263
+ display_completion_message()
264
+
265
+
266
+ if __name__ == "__main__":
267
+ main()