machineconfig 5.37__py3-none-any.whl → 5.38__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 (87) hide show
  1. machineconfig/cluster/remote/script_execution.py +0 -1
  2. machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +0 -2
  3. machineconfig/jobs/installer/custom_dev/nerfont_windows_helper.py +12 -12
  4. machineconfig/jobs/installer/installer_data.json +53 -2
  5. machineconfig/jobs/windows/archive/archive_pygraphviz.ps1 +1 -3
  6. machineconfig/scripts/linux/{share_cloud.sh → other/share_cloud.sh} +3 -0
  7. machineconfig/scripts/python/ai/solutions/generic.py +1 -0
  8. machineconfig/scripts/python/croshell.py +5 -2
  9. machineconfig/scripts/python/devops.py +4 -21
  10. machineconfig/scripts/python/devops_helpers/cli_nw.py +2 -1
  11. machineconfig/scripts/python/devops_helpers/cli_repos.py +1 -3
  12. machineconfig/scripts/python/devops_helpers/cli_self.py +6 -6
  13. machineconfig/scripts/python/devops_helpers/cli_share_server.py +109 -0
  14. machineconfig/scripts/python/devops_helpers/cli_terminal.py +35 -23
  15. machineconfig/scripts/python/devops_helpers/devops_update_repos.py +63 -44
  16. machineconfig/scripts/python/devops_helpers/themes/choose_pwsh_theme.ps1 +16 -15
  17. machineconfig/scripts/python/devops_navigator.py +183 -80
  18. machineconfig/scripts/python/helpers_fire/{fire_gemini.py → agentic_frameworks/fire_gemini.py} +12 -9
  19. machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_qwen.py +43 -0
  20. machineconfig/scripts/python/helpers_fire/fire_agents_help_launch.py +4 -4
  21. machineconfig/scripts/python/helpers_fire/template.ps1 +29 -0
  22. machineconfig/scripts/python/interactive.py +3 -2
  23. machineconfig/scripts/python/nw/mount_nw_drive +1 -2
  24. machineconfig/scripts/windows/mounts/share_nfs.ps1 +0 -0
  25. machineconfig/settings/lf/linux/lfrc +0 -2
  26. machineconfig/settings/lf/windows/lfrc +0 -4
  27. machineconfig/settings/shells/bash/commands.sh +24 -0
  28. machineconfig/settings/shells/bash/init.sh +5 -0
  29. machineconfig/settings/shells/pwsh/commands.ps1 +33 -0
  30. machineconfig/settings/shells/pwsh/init.ps1 +4 -0
  31. machineconfig/setup_windows/machineconfig.ps1 +2 -0
  32. machineconfig/utils/files/dbms.py +4 -1
  33. machineconfig/utils/installer_utils/installer.py +12 -0
  34. machineconfig/utils/installer_utils/installer_abc.py +26 -9
  35. machineconfig/utils/installer_utils/installer_class.py +1 -1
  36. machineconfig/utils/io.py +0 -18
  37. machineconfig/utils/scheduler.py +3 -4
  38. {machineconfig-5.37.dist-info → machineconfig-5.38.dist-info}/METADATA +7 -4
  39. {machineconfig-5.37.dist-info → machineconfig-5.38.dist-info}/RECORD +59 -82
  40. machineconfig/jobs/windows/start_terminal.ps1 +0 -6
  41. machineconfig/jobs/windows/startup_file.cmd +0 -2
  42. machineconfig/scripts/cloud/init.sh +0 -105
  43. machineconfig/scripts/linux/agents +0 -2
  44. machineconfig/scripts/linux/cloud +0 -2
  45. machineconfig/scripts/linux/croshell +0 -3
  46. machineconfig/scripts/linux/devops +0 -2
  47. machineconfig/scripts/linux/fire +0 -2
  48. machineconfig/scripts/linux/ftpx +0 -2
  49. machineconfig/scripts/linux/kill_process +0 -2
  50. machineconfig/scripts/linux/sessions +0 -2
  51. machineconfig/scripts/linux/start_terminals +0 -3
  52. machineconfig/scripts/windows/agents.ps1 +0 -1
  53. machineconfig/scripts/windows/cloud.ps1 +0 -1
  54. machineconfig/scripts/windows/croshell.ps1 +0 -1
  55. machineconfig/scripts/windows/devops.ps1 +0 -1
  56. machineconfig/scripts/windows/fire.ps1 +0 -1
  57. machineconfig/scripts/windows/ftpx.ps1 +0 -1
  58. machineconfig/scripts/windows/gpt.ps1 +0 -1
  59. machineconfig/scripts/windows/grep.ps1 +0 -2
  60. machineconfig/scripts/windows/kill_process.ps1 +0 -1
  61. machineconfig/scripts/windows/nano.ps1 +0 -3
  62. machineconfig/scripts/windows/scheduler.ps1 +0 -1
  63. machineconfig/scripts/windows/sessions.ps1 +0 -1
  64. machineconfig/scripts/windows/snapshot.ps1 +0 -1
  65. machineconfig/scripts/windows/start_terminals.ps1 +0 -1
  66. machineconfig/scripts/windows/wsl_rdp_windows_port_forwarding.ps1 +0 -46
  67. machineconfig/scripts/windows/wsl_ssh_windows_port_forwarding.ps1 +0 -76
  68. /machineconfig/scripts/linux/{share_nfs → other/share_nfs} +0 -0
  69. /machineconfig/scripts/linux/{share_smb → other/share_smb} +0 -0
  70. /machineconfig/scripts/linux/{start_docker → other/start_docker} +0 -0
  71. /machineconfig/scripts/linux/{switch_ip → other/switch_ip} +0 -0
  72. /machineconfig/scripts/{windows/share_nfs.ps1 → python/helpers_fire/agentic_frameworks/__init__.py} +0 -0
  73. /machineconfig/scripts/python/helpers_fire/{fire_crush.json → agentic_frameworks/fire_crush.json} +0 -0
  74. /machineconfig/scripts/python/helpers_fire/{fire_crush.py → agentic_frameworks/fire_crush.py} +0 -0
  75. /machineconfig/scripts/python/helpers_fire/{fire_cursor_agents.py → agentic_frameworks/fire_cursor_agents.py} +0 -0
  76. /machineconfig/scripts/windows/{mount_nfs.ps1 → mounts/mount_nfs.ps1} +0 -0
  77. /machineconfig/scripts/windows/{mount_nw.ps1 → mounts/mount_nw.ps1} +0 -0
  78. /machineconfig/scripts/windows/{mount_smb.ps1 → mounts/mount_smb.ps1} +0 -0
  79. /machineconfig/scripts/windows/{mount_ssh.ps1 → mounts/mount_ssh.ps1} +0 -0
  80. /machineconfig/scripts/windows/{pomodoro.ps1 → mounts/pomodoro.ps1} +0 -0
  81. /machineconfig/scripts/windows/{reload_path.ps1 → mounts/reload_path.ps1} +0 -0
  82. /machineconfig/scripts/windows/{share_cloud.cmd → mounts/share_cloud.cmd} +0 -0
  83. /machineconfig/scripts/windows/{share_smb.ps1 → mounts/share_smb.ps1} +0 -0
  84. /machineconfig/scripts/windows/{unlock_bitlocker.ps1 → mounts/unlock_bitlocker.ps1} +0 -0
  85. {machineconfig-5.37.dist-info → machineconfig-5.38.dist-info}/WHEEL +0 -0
  86. {machineconfig-5.37.dist-info → machineconfig-5.38.dist-info}/entry_points.txt +0 -0
  87. {machineconfig-5.37.dist-info → machineconfig-5.38.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,6 @@
1
1
  """Update repositories with fancy output"""
2
2
 
3
+ from concurrent.futures import ThreadPoolExecutor, as_completed
3
4
  from pathlib import Path
4
5
 
5
6
  import git
@@ -16,6 +17,55 @@ from machineconfig.utils.source_of_truth import DEFAULTS_PATH
16
17
  console = Console()
17
18
 
18
19
 
20
+ def _process_single_repo(expanded_path: Path, allow_password_prompt: bool) -> tuple[RepositoryUpdateResult, Path | None]:
21
+ """Process a single repository and return the result."""
22
+ try:
23
+ repo = git.Repo(str(expanded_path), search_parent_directories=True)
24
+ # Update repository and get detailed results
25
+ result = update_repository(repo, allow_password_prompt=allow_password_prompt, auto_sync=True)
26
+
27
+ # Keep track of repos with dependency changes for additional uv sync
28
+ repo_path = None
29
+ if result["dependencies_changed"] and not result["uv_sync_ran"]:
30
+ repo_path = Path(repo.working_dir)
31
+
32
+ return result, repo_path
33
+
34
+ except Exception as ex:
35
+ # Create a result for failed repos
36
+ error_result: RepositoryUpdateResult = {
37
+ "repo_path": str(expanded_path),
38
+ "status": "error",
39
+ "had_uncommitted_changes": False,
40
+ "uncommitted_files": [],
41
+ "commit_before": "",
42
+ "commit_after": "",
43
+ "commits_changed": False,
44
+ "pyproject_changed": False,
45
+ "dependencies_changed": False,
46
+ "uv_sync_ran": False,
47
+ "uv_sync_success": False,
48
+ "remotes_processed": [],
49
+ "remotes_skipped": [],
50
+ "error_message": str(ex),
51
+ "is_machineconfig_repo": False,
52
+ "permissions_updated": False,
53
+ }
54
+ console.print(
55
+ Panel(
56
+ "\n".join(
57
+ [
58
+ f"❌ Repository error: {expanded_path}",
59
+ f"Exception: {ex}",
60
+ ]
61
+ ),
62
+ border_style="red",
63
+ padding=(1, 2),
64
+ )
65
+ )
66
+ return error_result, None
67
+
68
+
19
69
  def _display_summary(results: list[RepositoryUpdateResult]) -> None:
20
70
  """Display a comprehensive summary of all repository update operations."""
21
71
 
@@ -189,54 +239,23 @@ def main(verbose: bool = True, allow_password_prompt: bool = False) -> None:
189
239
  )
190
240
  )
191
241
 
192
- # Process repositories
242
+ # Process repositories in parallel
193
243
  results: list[RepositoryUpdateResult] = []
194
244
  repos_with_changes = []
195
245
 
196
- for expanded_path in repos:
197
- try:
198
- repo = git.Repo(str(expanded_path), search_parent_directories=True)
199
- # Update repository and get detailed results
200
- result = update_repository(repo, allow_password_prompt=allow_password_prompt, auto_sync=True)
246
+ with ThreadPoolExecutor(max_workers=min(len(repos), 8)) as executor:
247
+ # Submit all tasks
248
+ future_to_repo = {
249
+ executor.submit(_process_single_repo, expanded_path, allow_password_prompt): expanded_path
250
+ for expanded_path in repos
251
+ }
252
+
253
+ # Collect results as they complete
254
+ for future in as_completed(future_to_repo):
255
+ result, repo_path = future.result()
201
256
  results.append(result)
202
-
203
- # Keep track of repos with dependency changes for additional uv sync
204
- if result["dependencies_changed"] and not result["uv_sync_ran"]:
205
- repos_with_changes.append(Path(repo.working_dir))
206
-
207
- except Exception as ex:
208
- # Create a result for failed repos
209
- error_result: RepositoryUpdateResult = {
210
- "repo_path": str(expanded_path),
211
- "status": "error",
212
- "had_uncommitted_changes": False,
213
- "uncommitted_files": [],
214
- "commit_before": "",
215
- "commit_after": "",
216
- "commits_changed": False,
217
- "pyproject_changed": False,
218
- "dependencies_changed": False,
219
- "uv_sync_ran": False,
220
- "uv_sync_success": False,
221
- "remotes_processed": [],
222
- "remotes_skipped": [],
223
- "error_message": str(ex),
224
- "is_machineconfig_repo": False,
225
- "permissions_updated": False,
226
- }
227
- results.append(error_result)
228
- console.print(
229
- Panel(
230
- "\n".join(
231
- [
232
- f"❌ Repository error: {expanded_path}",
233
- f"Exception: {ex}",
234
- ]
235
- ),
236
- border_style="red",
237
- padding=(1, 2),
238
- )
239
- )
257
+ if repo_path is not None:
258
+ repos_with_changes.append(repo_path)
240
259
  # Run uv sync for repositories where pyproject.toml changed but sync wasn't run yet
241
260
  for repo_path in repos_with_changes:
242
261
  run_uv_sync(repo_path)
@@ -49,29 +49,30 @@ if ($selectedThemeName) {
49
49
  }
50
50
 
51
51
  # Read existing profile content or create empty array
52
- $profileContent = @()
53
52
  if (Test-Path $profilePath) {
54
- $profileContent = Get-Content $profilePath
53
+ $profileContent = Get-Content $profilePath -Raw
54
+ } else {
55
+ $profileContent = ""
55
56
  }
56
57
 
57
- # Check if oh-my-posh line already exists and replace it, or add it
58
- $found = $false
59
- for ($i = 0; $i -lt $profileContent.Count; $i++) {
60
- if ($profileContent[$i] -match "oh-my-posh init pwsh") {
61
- $profileContent[$i] = $ompLine
62
- $found = $true
63
- break
58
+ # Check if oh-my-posh line already exists and replace it
59
+ if ($profileContent -match "oh-my-posh init pwsh[^\r\n]*") {
60
+ # Replace existing oh-my-posh line
61
+ $profileContent = $profileContent -replace "oh-my-posh init pwsh[^\r\n]*", $ompLine
62
+ } else {
63
+ # Add the oh-my-posh line with proper newlines
64
+ if ($profileContent.Length -gt 0 -and -not $profileContent.EndsWith("`n")) {
65
+ $profileContent += "`n"
66
+ }
67
+ if ($profileContent.Length -gt 0) {
68
+ $profileContent += "`n"
64
69
  }
65
- }
66
-
67
- if (-not $found) {
68
- # Add the line at the end with a blank line before it
69
- $profileContent += ""
70
70
  $profileContent += $ompLine
71
+ $profileContent += "`n"
71
72
  }
72
73
 
73
74
  # Write back to profile
74
- $profileContent | Set-Content $profilePath -Encoding UTF8
75
+ $profileContent | Set-Content $profilePath -Encoding UTF8 -NoNewline
75
76
 
76
77
  Write-Host "Profile updated successfully!" -ForegroundColor Green
77
78
  Write-Host "The theme will be applied automatically in future PowerShell sessions." -ForegroundColor Cyan
@@ -174,48 +174,80 @@ class CommandTree(Tree[CommandInfo]):
174
174
  command="devops repos",
175
175
  parent="devops",
176
176
  is_group=True,
177
- module_path="machineconfig.scripts.python.repos"
177
+ module_path="machineconfig.scripts.python.devops_helpers.cli_repos"
178
178
  ))
179
179
 
180
180
  # repos subcommands
181
- sync_node = repos_node.add("🔄 sync - Synchronize repositories", data=CommandInfo(
181
+ repos_node.add("🚀 push - Push changes across repositories", data=CommandInfo(
182
+ name="push",
183
+ description="Push changes across repositories",
184
+ command="devops repos push",
185
+ parent="repos",
186
+ help_text="devops repos push --directory <dir> --recursive --no-sync"
187
+ ))
188
+
189
+ repos_node.add("⬇️ pull - Pull changes across repositories", data=CommandInfo(
190
+ name="pull",
191
+ description="Pull changes across repositories",
192
+ command="devops repos pull",
193
+ parent="repos",
194
+ help_text="devops repos pull --directory <dir> --recursive --no-sync"
195
+ ))
196
+
197
+ repos_node.add("💾 commit - Commit changes across repositories", data=CommandInfo(
198
+ name="commit",
199
+ description="Commit changes across repositories",
200
+ command="devops repos commit",
201
+ parent="repos",
202
+ help_text="devops repos commit --directory <dir> --recursive --no-sync"
203
+ ))
204
+
205
+ repos_node.add("🔄 sync - Sync changes across repositories", data=CommandInfo(
182
206
  name="sync",
183
- description="Synchronize repositories",
207
+ description="Pull, commit, and push changes across repositories",
184
208
  command="devops repos sync",
185
209
  parent="repos",
210
+ help_text="devops repos sync --directory <dir> --recursive --no-sync"
211
+ ))
212
+
213
+ mirror_node = repos_node.add("🔄 mirror - Manage repository specifications", data=CommandInfo(
214
+ name="mirror",
215
+ description="Manage repository specifications and syncing",
216
+ command="devops repos mirror",
217
+ parent="repos",
186
218
  is_group=True
187
219
  ))
188
220
 
189
- sync_node.add("📝 capture - Record repositories into repos.json", data=CommandInfo(
221
+ mirror_node.add("📝 capture - Record repositories into repos.json", data=CommandInfo(
190
222
  name="capture",
191
223
  description="Record repositories into a repos.json specification",
192
- command="devops repos sync capture",
193
- parent="sync",
194
- help_text="devops repos sync capture --directory <dir> --cloud <cloud>"
224
+ command="devops repos mirror capture",
225
+ parent="mirror",
226
+ help_text="devops repos mirror capture --directory <dir> --cloud <cloud>"
195
227
  ))
196
228
 
197
- sync_node.add("📥 clone - Clone repositories from repos.json", data=CommandInfo(
229
+ mirror_node.add("📥 clone - Clone repositories from repos.json", data=CommandInfo(
198
230
  name="clone",
199
231
  description="Clone repositories described by repos.json",
200
- command="devops repos sync clone",
201
- parent="sync",
202
- help_text="devops repos sync clone --directory <dir> --cloud <cloud>"
232
+ command="devops repos mirror clone",
233
+ parent="mirror",
234
+ help_text="devops repos mirror clone --directory <dir> --cloud <cloud>"
203
235
  ))
204
236
 
205
- sync_node.add("🔀 checkout-to-commit - Check out specific commits", data=CommandInfo(
237
+ mirror_node.add("🔀 checkout-to-commit - Check out specific commits", data=CommandInfo(
206
238
  name="checkout-to-commit",
207
239
  description="Check out specific commits listed in specification",
208
- command="devops repos sync checkout-to-commit",
209
- parent="sync",
210
- help_text="devops repos sync checkout-to-commit --directory <dir> --cloud <cloud>"
240
+ command="devops repos mirror checkout-to-commit",
241
+ parent="mirror",
242
+ help_text="devops repos mirror checkout-to-commit --directory <dir> --cloud <cloud>"
211
243
  ))
212
244
 
213
- sync_node.add("🔀 checkout-to-branch - Check out to main branch", data=CommandInfo(
245
+ mirror_node.add("🔀 checkout-to-branch - Check out to main branch", data=CommandInfo(
214
246
  name="checkout-to-branch",
215
247
  description="Check out to the main branch defined in specification",
216
- command="devops repos sync checkout-to-branch",
217
- parent="sync",
218
- help_text="devops repos sync checkout-to-branch --directory <dir> --cloud <cloud>"
248
+ command="devops repos mirror checkout-to-branch",
249
+ parent="mirror",
250
+ help_text="devops repos mirror checkout-to-branch --directory <dir> --cloud <cloud>"
219
251
  ))
220
252
 
221
253
  repos_node.add("🔍 analyze - Analyze repositories", data=CommandInfo(
@@ -226,6 +258,30 @@ class CommandTree(Tree[CommandInfo]):
226
258
  help_text="devops repos analyze --directory <dir>"
227
259
  ))
228
260
 
261
+ repos_node.add("🔐 secure - Securely sync git repository", data=CommandInfo(
262
+ name="secure",
263
+ description="Securely sync git repository to/from cloud with encryption",
264
+ command="devops repos secure",
265
+ parent="repos",
266
+ help_text="devops repos secure <path> --cloud <cloud> --encrypt --decrypt"
267
+ ))
268
+
269
+ repos_node.add("🎬 viz - Visualize repository activity", data=CommandInfo(
270
+ name="viz",
271
+ description="Visualize repository activity using Gource",
272
+ command="devops repos viz",
273
+ parent="repos",
274
+ help_text="devops repos viz --repo <path> --output <file> --resolution <res> --seconds-per-day <spd>"
275
+ ))
276
+
277
+ repos_node.add("🧹 cleanup - Clean repository directories", data=CommandInfo(
278
+ name="cleanup",
279
+ description="Clean repository directories from cache files",
280
+ command="devops repos cleanup",
281
+ parent="repos",
282
+ help_text="devops repos cleanup --repo <path> --recursive"
283
+ ))
284
+
229
285
  # config subcommands
230
286
  config_node = devops_node.add("⚙️ config - Configuration management", data=CommandInfo(
231
287
  name="config",
@@ -267,6 +323,14 @@ class CommandTree(Tree[CommandInfo]):
267
323
  help_text="devops config shell <copy|reference>"
268
324
  ))
269
325
 
326
+ config_node.add("🔗 pwsh_theme - Configure PowerShell theme", data=CommandInfo(
327
+ name="pwsh_theme",
328
+ description="Configure your PowerShell theme",
329
+ command="devops config pwsh_theme",
330
+ parent="config",
331
+ help_text="devops config pwsh_theme"
332
+ ))
333
+
270
334
  # data subcommands
271
335
  data_node = devops_node.add("💾 data - Data operations", data=CommandInfo(
272
336
  name="data",
@@ -309,28 +373,28 @@ class CommandTree(Tree[CommandInfo]):
309
373
  help_text="devops network share-terminal"
310
374
  ))
311
375
 
312
- network_node.add("🔑 add-key - Add SSH public key", data=CommandInfo(
313
- name="add-key",
314
- description="SSH add pub key to this machine",
315
- command="devops network add-key",
376
+ network_node.add(" install_ssh_server - Install SSH server", data=CommandInfo(
377
+ name="install_ssh_server",
378
+ description="Install SSH server",
379
+ command="devops network install_ssh_server",
316
380
  parent="network",
317
- help_text="devops network add-key"
381
+ help_text="devops network install_ssh_server"
318
382
  ))
319
383
 
320
- network_node.add("🗝️ add-identity - Add SSH identity", data=CommandInfo(
321
- name="add-identity",
322
- description="SSH add identity (private key) to this machine",
323
- command="devops network add-identity",
384
+ network_node.add(" add_ssh_key - Add SSH public key", data=CommandInfo(
385
+ name="add_ssh_key",
386
+ description="Add SSH public key to this machine",
387
+ command="devops network add_ssh_key",
324
388
  parent="network",
325
- help_text="devops network add-identity"
389
+ help_text="devops network add_ssh_key --path <file> --choose --value --github <username>"
326
390
  ))
327
391
 
328
- network_node.add("📡 setup - SSH setup", data=CommandInfo(
329
- name="setup",
330
- description="SSH setup",
331
- command="devops network setup",
392
+ network_node.add("�️ add_ssh_identity - Add SSH identity", data=CommandInfo(
393
+ name="add_ssh_identity",
394
+ description="Add SSH identity (private key) to this machine",
395
+ command="devops network add_ssh_identity",
332
396
  parent="network",
333
- help_text="devops network setup"
397
+ help_text="devops network add_ssh_identity"
334
398
  ))
335
399
 
336
400
  # self subcommands
@@ -344,7 +408,7 @@ class CommandTree(Tree[CommandInfo]):
344
408
 
345
409
  self_node.add("🔄 update - Update essential repos", data=CommandInfo(
346
410
  name="update",
347
- description="UPDATE essential repos",
411
+ description="Update essential repos",
348
412
  command="devops self update",
349
413
  parent="self",
350
414
  help_text="devops self update"
@@ -352,7 +416,7 @@ class CommandTree(Tree[CommandInfo]):
352
416
 
353
417
  self_node.add("🤖 interactive - Interactive configuration", data=CommandInfo(
354
418
  name="interactive",
355
- description="INTERACTIVE configuration of machine",
419
+ description="Interactive configuration of machine",
356
420
  command="devops self interactive",
357
421
  parent="self",
358
422
  help_text="devops self interactive"
@@ -360,7 +424,7 @@ class CommandTree(Tree[CommandInfo]):
360
424
 
361
425
  self_node.add("📊 status - Machine status", data=CommandInfo(
362
426
  name="status",
363
- description="STATUS of machine, shell profile, apps, symlinks, dotfiles, etc.",
427
+ description="Status of machine, shell profile, apps, symlinks, dotfiles, etc.",
364
428
  command="devops self status",
365
429
  parent="self",
366
430
  help_text="devops self status"
@@ -368,12 +432,20 @@ class CommandTree(Tree[CommandInfo]):
368
432
 
369
433
  self_node.add("📋 clone - Clone machineconfig", data=CommandInfo(
370
434
  name="clone",
371
- description="CLONE machineconfig locally and incorporate to shell profile",
435
+ description="Clone machineconfig locally and incorporate to shell profile",
372
436
  command="devops self clone",
373
437
  parent="self",
374
438
  help_text="devops self clone"
375
439
  ))
376
440
 
441
+ self_node.add("📚 navigate - Navigate command structure", data=CommandInfo(
442
+ name="navigate",
443
+ description="Navigate command structure with TUI",
444
+ command="devops self navigate",
445
+ parent="self",
446
+ help_text="devops self navigate"
447
+ ))
448
+
377
449
  # fire command
378
450
  self.root.add("🔥 fire - Fire jobs execution", data=CommandInfo(
379
451
  name="fire",
@@ -398,7 +470,7 @@ class CommandTree(Tree[CommandInfo]):
398
470
  description="Create a new AI agent",
399
471
  command="agents create",
400
472
  parent="agents",
401
- help_text="agents create"
473
+ help_text="agents create --context-path <file> --keyword-search <term> --filename-pattern <pattern> --agent <type> --machine <target> --model <model> --provider <provider> --prompt <text> --prompt-path <file> --job-name <name> --tasks-per-prompt <num> --separate-prompt-from-context --output-path <file> --agents-dir <dir>"
402
474
  ))
403
475
 
404
476
  agents_node.add("📦 collect - Collect agent data", data=CommandInfo(
@@ -406,15 +478,31 @@ class CommandTree(Tree[CommandInfo]):
406
478
  description="Collect agent data",
407
479
  command="agents collect",
408
480
  parent="agents",
409
- help_text="agents collect"
481
+ help_text="agents collect --agent-dir <dir> --output-path <file> --separator <sep>"
410
482
  ))
411
483
 
412
- agents_node.add("📝 create-template - Create agent template", data=CommandInfo(
413
- name="create-template",
484
+ agents_node.add("📝 make-template - Create agent template", data=CommandInfo(
485
+ name="make-template",
414
486
  description="Create a template for fire agents",
415
- command="agents create-template",
487
+ command="agents make-template",
416
488
  parent="agents",
417
- help_text="agents create-template"
489
+ help_text="agents make-template"
490
+ ))
491
+
492
+ agents_node.add("⚙️ make-config - Initialize AI configurations", data=CommandInfo(
493
+ name="make-config",
494
+ description="Initialize AI configurations in the current repository",
495
+ command="agents make-config",
496
+ parent="agents",
497
+ help_text="agents make-config"
498
+ ))
499
+
500
+ agents_node.add("📝 make-todo - Generate todo markdown", data=CommandInfo(
501
+ name="make-todo",
502
+ description="Generate a markdown file listing all Python files in the repo",
503
+ command="agents make-todo",
504
+ parent="agents",
505
+ help_text="agents make-todo"
418
506
  ))
419
507
 
420
508
  # sessions command
@@ -439,7 +527,7 @@ class CommandTree(Tree[CommandInfo]):
439
527
  description="Run session layout",
440
528
  command="sessions run",
441
529
  parent="sessions",
442
- help_text="sessions run"
530
+ help_text="sessions run --layout-path <file> --max-tabs <num> --max-layouts <num> --sleep-inbetween <sec> --monitor --parallel --kill-upon-completion --choose <names> --choose-interactively"
443
531
  ))
444
532
 
445
533
  sessions_node.add("⚖️ balance-load - Balance load", data=CommandInfo(
@@ -447,56 +535,71 @@ class CommandTree(Tree[CommandInfo]):
447
535
  description="Balance load across sessions",
448
536
  command="sessions balance-load",
449
537
  parent="sessions",
450
- help_text="sessions balance-load"
538
+ help_text="sessions balance-load --layout-path <file> --max-thresh <num> --thresh-type <number|weight> --breaking-method <moreLayouts|combineTabs> --output-path <file>"
451
539
  ))
452
540
 
453
- # Other utility commands
454
- utils_node = self.root.add("🔧 Utilities", data=CommandInfo(
455
- name="utilities",
456
- description="Utility commands",
457
- command="",
458
- is_group=True
541
+ # cloud command
542
+ cloud_node = self.root.add("☁️ cloud - Cloud storage operations", data=CommandInfo(
543
+ name="cloud",
544
+ description="Cloud storage operations",
545
+ command="cloud",
546
+ is_group=True,
547
+ module_path="machineconfig.scripts.python.cloud"
548
+ ))
549
+
550
+ cloud_node.add("🔄 sync - Synchronize with cloud", data=CommandInfo(
551
+ name="sync",
552
+ description="Synchronize files/folders between local and cloud storage",
553
+ command="cloud sync",
554
+ parent="cloud",
555
+ help_text="cloud sync <source> <target> --cloud <provider> --recursive --exclude <patterns>"
459
556
  ))
460
557
 
461
- utils_node.add("☁️ cloud_mount - Mount cloud storage", data=CommandInfo(
462
- name="cloud_mount",
463
- description="Mount cloud storage using rclone",
464
- command="cloud_mount",
465
- parent="utilities",
466
- help_text="cloud_mount --cloud <cloud> --destination <path> --network <network>"
558
+ cloud_node.add("📤 copy - Copy to/from cloud", data=CommandInfo(
559
+ name="copy",
560
+ description="Copy files/folders to/from cloud storage",
561
+ command="cloud copy",
562
+ parent="cloud",
563
+ help_text="cloud copy <source> <target> --cloud <provider> --recursive --exclude <patterns>"
467
564
  ))
468
565
 
469
- utils_node.add("☁️ cloud_copy - Copy to/from cloud", data=CommandInfo(
470
- name="cloud_copy",
471
- description="Copy files to/from cloud storage",
472
- command="cloud_copy",
473
- parent="utilities",
474
- help_text="cloud_copy"
566
+ cloud_node.add("🔗 mount - Mount cloud storage", data=CommandInfo(
567
+ name="mount",
568
+ description="Mount cloud storage as local drive",
569
+ command="cloud mount",
570
+ parent="cloud",
571
+ help_text="cloud mount <remote> <mount_point> --cloud <provider> --daemon --allow-other"
475
572
  ))
476
573
 
477
- utils_node.add("☁️ cloud_sync - Sync with cloud", data=CommandInfo(
478
- name="cloud_sync",
479
- description="Sync files with cloud storage",
480
- command="cloud_sync",
481
- parent="utilities",
482
- help_text="cloud_sync"
574
+ # croshell command
575
+ self.root.add("� croshell - Interactive shell", data=CommandInfo(
576
+ name="croshell",
577
+ description="Interactive shell with various options",
578
+ command="croshell",
579
+ is_group=False,
580
+ module_path="machineconfig.scripts.python.croshell",
581
+ help_text="croshell --python --fzf --ve <env> --profile <profile> --read <file> --jupyter --streamlit --visidata"
483
582
  ))
484
583
 
485
- utils_node.add("🔧 kill_process - Kill processes", data=CommandInfo(
584
+ # ftpx command
585
+ self.root.add("📡 ftpx - File transfer", data=CommandInfo(
586
+ name="ftpx",
587
+ description="File transfer between machines",
588
+ command="ftpx",
589
+ is_group=False,
590
+ module_path="machineconfig.scripts.python.ftpx",
591
+ help_text="ftpx <source> <target> --recursive --zipFirst --cloud"
592
+ ))
593
+
594
+ # kill_process command
595
+ self.root.add("💀 kill_process - Kill processes", data=CommandInfo(
486
596
  name="kill_process",
487
597
  description="Kill running processes",
488
598
  command="kill_process",
489
- parent="utilities",
599
+ is_group=False,
600
+ module_path="machineconfig.utils.procs",
490
601
  help_text="kill_process"
491
602
  ))
492
-
493
- utils_node.add("🎨 choose_wezterm_theme - Choose terminal theme", data=CommandInfo(
494
- name="choose_wezterm_theme",
495
- description="Choose WezTerm theme interactively",
496
- command="choose_wezterm_theme",
497
- parent="utilities",
498
- help_text="choose_wezterm_theme"
499
- ))
500
603
 
501
604
 
502
605
  class CommandDetail(Static):
@@ -2,11 +2,11 @@
2
2
  from pathlib import Path
3
3
  import shlex
4
4
  from machineconfig.scripts.python.helpers_fire.fire_agents_helper_types import MATCHINE
5
- from typing import Optional
5
+ from typing import Optional, Literal
6
6
 
7
7
 
8
- def fire_gemini(api_key: Optional[str], prompt_path: Path, machine: MATCHINE) -> str:
9
- model = "gemini-2.5-pro"
8
+ def fire_gemini(api_key: Optional[str], model: Literal["gemini-2.5-pro"], provider: Literal["google"], machine: MATCHINE, prompt_path: Path, repo_root: Path) -> str:
9
+ _ = provider
10
10
  # model = "gemini-2.5-flash-lite"
11
11
  # model = None # auto-select
12
12
  # if model is None:
@@ -27,14 +27,17 @@ def fire_gemini(api_key: Optional[str], prompt_path: Path, machine: MATCHINE) ->
27
27
  {define_api_key}
28
28
  echo "Using Gemini API key $GEMINI_API_KEY"
29
29
  gemini {model_arg} --yolo --prompt {safe_path}
30
- """
30
+ """
31
+
32
+
31
33
  case "docker":
32
- cmd = """
34
+ assert api_key is not None, "When using docker, api_key must be provided."
35
+ cmd = f"""
33
36
  docker run -it --rm \
34
- -e GEMINI_API_KEY="$GEMINI_API_KEY" \
35
- -v "/home/alex/code/machineconfig:/workspace/machineconfig" \
36
- -w "/workspace/machineconfig" \
37
- gemini-cli:latest \
37
+ -e GEMINI_API_KEY="{api_key}" \
38
+ -v "{repo_root}:/workspace/{repo_root.name}" \
39
+ -w "/workspace/{repo_root.name}" \
40
+ statistician/machineconfig:latest \
38
41
  gemini --prompt "$PATH_PROMPT"
39
42
  """
40
43
  return cmd
@@ -0,0 +1,43 @@
1
+
2
+ from pathlib import Path
3
+ import shlex
4
+ from machineconfig.scripts.python.helpers_fire.fire_agents_helper_types import MATCHINE
5
+ from typing import Optional, Literal
6
+
7
+
8
+ def fire_qwen(config_dir: Optional[str], model: Literal["qwen"], provider: Literal["qwen"], machine: MATCHINE, prompt_path: Path, repo_root: Path) -> str:
9
+ # assert model == "qwen", "Only qwen is supported currently."
10
+ # assert provider == "qwen", "Only qwen is supported currently."
11
+ # model = "qwen"
12
+ # model = "gemini-2.5-flash-lite"
13
+ # model = None # auto-select
14
+ # if model is None:
15
+ # model_arg = ""
16
+ # else:
17
+ _ = provider
18
+ # model_arg = f"--model {shlex.quote(model)}"
19
+ # Need a real shell for the pipeline; otherwise '| gemini ...' is passed as args to 'cat'
20
+ safe_path = shlex.quote(str(prompt_path))
21
+
22
+ match machine:
23
+ case "local":
24
+ # Export the environment variable so it's available to subshells
25
+ cmd = f"""
26
+ qwen --yolo --prompt {safe_path}
27
+ """
28
+ case "docker":
29
+ assert config_dir is not None, "When using docker, config_dir must be provided."
30
+ assert Path(config_dir).exists(), f"Provided config_dir {config_dir} does not exist."
31
+ oauth_creds = Path(config_dir).joinpath("oauth_creds.json")
32
+ settings = Path(config_dir).joinpath("settings.json")
33
+
34
+ cmd = f"""
35
+ docker run -it --rm \
36
+ -v "{repo_root}:/workspace/{repo_root.name}" \
37
+ -v {shlex.quote(str(oauth_creds))}:/root/.qwen/oauth_creds.json \
38
+ -v {shlex.quote(str(settings))}:/root/.qwen/settings.json \
39
+ -w "/workspace/{repo_root.name}" \
40
+ statistician/machineconfig:latest \
41
+ qwen --prompt "$PATH_PROMPT"
42
+ """
43
+ return cmd