ellf-cli 19.0.18__tar.gz → 20.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. {ellf_cli-19.0.18/ellf_cli.egg-info → ellf_cli-20.0.0}/PKG-INFO +1 -1
  2. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/README.md +12 -3
  3. ellf_cli-20.0.0/ellf_cli/agents.py +367 -0
  4. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/cli.py +1 -0
  5. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/__init__.py +2 -0
  6. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/general.py +93 -70
  7. ellf_cli-20.0.0/ellf_cli/commands/mcp.py +44 -0
  8. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/support.py +31 -21
  9. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf.json +92 -61
  10. ellf_cli-20.0.0/ellf_cli/ellf_skills/render.py +278 -0
  11. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-annotate.assistant/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-annotate/SKILL.assistant.md +6 -6
  12. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-annotate.coding/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-annotate/SKILL.coding.md +10 -12
  13. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-annotate.assistant/references/builtin_ellf_annotation_recipes.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-annotate/references/builtin_ellf_annotation_recipes.assistant.md +1 -1
  14. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-annotate.coding/references/builtin_ellf_annotation_recipes.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-annotate/references/builtin_ellf_annotation_recipes.coding.md +1 -1
  15. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-ask/SKILL.md +0 -2
  16. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-monitor.assistant/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-monitor/SKILL.assistant.md +6 -6
  17. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-monitor.coding/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-monitor/SKILL.coding.md +15 -15
  18. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-monitor.coding/references/training_monitoring.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-monitor/references/training_monitoring.coding.md +4 -4
  19. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-monitor.coding/scripts → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-monitor/scripts.coding}/check_training.py +2 -2
  20. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-ops.coding/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-ops/SKILL.coding.md +2 -4
  21. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-patterns/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-patterns/SKILL.coding.md +14 -8
  22. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-prodigy/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-prodigy/SKILL.coding.md +26 -28
  23. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.assistant/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-project/SKILL.assistant.md +7 -7
  24. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.coding/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-project/SKILL.coding.md +8 -10
  25. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-support.coding/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-support/SKILL.coding.md +35 -35
  26. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-todo/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-todo/SKILL.coding.md +7 -6
  27. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.assistant/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/SKILL.assistant.md +10 -10
  28. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/SKILL.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/SKILL.coding.md +14 -16
  29. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/workflow.md → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/references/workflow.coding.md +4 -4
  30. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/interactivity.py +1 -1
  31. ellf_cli-20.0.0/ellf_cli/mcp_proxy.py +176 -0
  32. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/messages.py +7 -1
  33. ellf_cli-20.0.0/ellf_cli/version/19.0.18_2026-10-10-07-29-38_major_02601a1e-9bdb-45bf-ad67-a07b7dcd0002 +3 -0
  34. {ellf_cli-19.0.18 → ellf_cli-20.0.0/ellf_cli.egg-info}/PKG-INFO +1 -1
  35. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli.egg-info/SOURCES.txt +54 -56
  36. ellf_cli-20.0.0/tests/test_agents.py +262 -0
  37. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_login.py +203 -175
  38. ellf_cli-20.0.0/tests/test_mcp_proxy.py +248 -0
  39. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_support.py +71 -0
  40. ellf_cli-19.0.18/ellf_cli/ellf_skills/.claude-plugin/plugin.json +0 -12
  41. ellf_cli-19.0.18/ellf_cli/ellf_skills/skill_variants.json +0 -39
  42. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.coding/references/annotation_agents.md +0 -100
  43. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.coding/references/consulting_patterns.md +0 -444
  44. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.coding/references/explosion_strategy.md +0 -478
  45. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/diagnostics.md +0 -278
  46. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/evaluation_guide.md +0 -709
  47. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/model_selection.md +0 -468
  48. ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/training_paradigms.md +0 -322
  49. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/LICENSE +0 -0
  50. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/MANIFEST.in +0 -0
  51. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/__init__.py +0 -0
  52. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/__main__.py +0 -0
  53. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/about.json +0 -0
  54. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/about.py +0 -0
  55. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/appdirs.py +0 -0
  56. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/auth.py +0 -0
  57. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/cloud/__init__.py +0 -0
  58. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/cloud/gcp.py +0 -0
  59. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/cluster_config.py +0 -0
  60. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/_cluster_select.py +0 -0
  61. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/_org_select.py +0 -0
  62. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/_project_scope.py +0 -0
  63. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/_recipe_file.py +0 -0
  64. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/_recipe_subcommand.py +0 -0
  65. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/_state.py +0 -0
  66. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/_usage.py +0 -0
  67. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/actions.py +0 -0
  68. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/agents.py +0 -0
  69. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/assets.py +0 -0
  70. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/auth.py +0 -0
  71. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/clusters.py +0 -0
  72. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/config.py +0 -0
  73. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/datasets.py +0 -0
  74. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/files/__init__.py +0 -0
  75. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/files/cp.py +0 -0
  76. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/files/ls.py +0 -0
  77. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/files/rm.py +0 -0
  78. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/files/rsync.py +0 -0
  79. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/files/stats.py +0 -0
  80. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/import_export.py +0 -0
  81. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/__init__.py +0 -0
  82. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/_config_io.py +0 -0
  83. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/_helpers.py +0 -0
  84. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/configure.py +0 -0
  85. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/deploy.py +0 -0
  86. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/hibernate.py +0 -0
  87. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/init.py +0 -0
  88. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/init_values.py +0 -0
  89. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/pause.py +0 -0
  90. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/provision.py +0 -0
  91. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/register.py +0 -0
  92. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/setup.py +0 -0
  93. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/start.py +0 -0
  94. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/terraform.py +0 -0
  95. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/infra/tls.py +0 -0
  96. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/jobs.py +0 -0
  97. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/packages.py +0 -0
  98. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/paths.py +0 -0
  99. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/plans.py +0 -0
  100. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/projects.py +0 -0
  101. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/publish_code.py +0 -0
  102. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/publish_data.py +0 -0
  103. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/recipes.py +0 -0
  104. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/secrets.py +0 -0
  105. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/services.py +0 -0
  106. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/sessions.py +0 -0
  107. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/tasks.py +0 -0
  108. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/todos.py +0 -0
  109. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/commands/users.py +0 -0
  110. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/config.py +0 -0
  111. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/.gitignore +0 -0
  112. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-annotate.assistant/references/annotation_audit.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-annotate/references/annotation_audit.assistant.md +0 -0
  113. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-annotate.coding/references/annotation_audit.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-annotate/references/annotation_audit.coding.md +0 -0
  114. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-annotate.coding/references/builtin_prodigy_recipes.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-annotate/references/builtin_prodigy_recipes.coding.md +0 -0
  115. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-annotate.assistant/references/label_schemes.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-annotate/references/label_schemes.assistant.md +0 -0
  116. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-annotate.coding/references/label_schemes.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-annotate/references/label_schemes.coding.md +0 -0
  117. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-handoff/SKILL.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-handoff/SKILL.assistant.md +0 -0
  118. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-monitor.assistant/references/annotation_metrics.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-monitor/references/annotation_metrics.assistant.md +0 -0
  119. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-monitor.coding/references/annotation_metrics.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-monitor/references/annotation_metrics.coding.md +0 -0
  120. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-monitor.assistant/references/training_monitoring.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-monitor/references/training_monitoring.assistant.md +0 -0
  121. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-ops.assistant/SKILL.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-ops/SKILL.assistant.md +0 -0
  122. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-ops.coding/references → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-ops/references.coding}/data_infra_cli.md +0 -0
  123. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-ops.coding/scripts → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-ops/scripts.coding}/run_job.py +0 -0
  124. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-patterns/references/pattern_strategies.md +0 -0
  125. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_action_recipe.py +0 -0
  126. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_agent_recipe.py +0 -0
  127. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_blocks_ui.py +0 -0
  128. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_correct.py +0 -0
  129. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_custom_ui.py +0 -0
  130. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_manual.py +0 -0
  131. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_pages_ui.py +0 -0
  132. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_routing.py +0 -0
  133. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_service_recipe.py +0 -0
  134. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_task_recipe.py +0 -0
  135. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_teach.py +0 -0
  136. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/builtin_recipes.md +0 -0
  137. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/ellf_recipe_sdk.md +0 -0
  138. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/lint_recipe.py +0 -0
  139. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/prodigy_recipe_api.md +0 -0
  140. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/template_index.md +0 -0
  141. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.assistant → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-project}/references/annotation_agents.md +0 -0
  142. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.assistant → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-project}/references/consulting_patterns.md +0 -0
  143. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.assistant → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-project}/references/explosion_strategy.md +0 -0
  144. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.assistant/references/label_schemes.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-project/references/label_schemes.assistant.md +0 -0
  145. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-project.coding/references/label_schemes.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-project/references/label_schemes.coding.md +0 -0
  146. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-support.assistant/SKILL.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-support/SKILL.assistant.md +0 -0
  147. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/config_advanced.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/references/config_advanced.coding.md +0 -0
  148. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/config_architectures.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/references/config_architectures.coding.md +0 -0
  149. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/config_training.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/references/config_training.coding.md +0 -0
  150. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.assistant → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train}/references/diagnostics.md +0 -0
  151. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.assistant → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train}/references/evaluation_guide.md +0 -0
  152. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/experiment_patterns.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/references/experiment_patterns.coding.md +0 -0
  153. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.assistant → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train}/references/model_selection.md +0 -0
  154. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.assistant → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train}/references/training_paradigms.md +0 -0
  155. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/references/training_troubleshooting.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/references/training_troubleshooting.coding.md +0 -0
  156. /ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.assistant/references/workflow.md → /ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/references/workflow.assistant.md +0 -0
  157. {ellf_cli-19.0.18/ellf_cli/ellf_skills/skills/ellf-train.coding/scripts → ellf_cli-20.0.0/ellf_cli/ellf_skills/skills/ellf-train/scripts.coding}/ellf_logger.py +0 -0
  158. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/errors.py +0 -0
  159. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/helm.py +0 -0
  160. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/key_pair.py +0 -0
  161. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/main.py +0 -0
  162. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/pypi_auth.py +0 -0
  163. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/query.py +0 -0
  164. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/cookiecutter.json +0 -0
  165. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/.gitignore +0 -0
  166. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/README.md.tmpl +0 -0
  167. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/requirements-dev.in +0 -0
  168. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/requirements.in +0 -0
  169. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/setup.py.tmpl +0 -0
  170. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/__init__.py +0 -0
  171. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/about.py +0 -0
  172. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/recipes/__init__.py +0 -0
  173. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/recipes/example_task.py +0 -0
  174. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/testing/__init__.py +0 -0
  175. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ty.py +0 -0
  176. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/ui.py +0 -0
  177. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/url.py +0 -0
  178. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/util.py +0 -0
  179. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.114_2026-08-19-08-36-57__1a4e37c1-471e-4a81-b4d5-1ffe7dec3a61 +0 -0
  180. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.114_2026-08-19-09-25-21_patch_33ff1e26-0e5e-46d8-8052-ab1d032e8b6c +0 -0
  181. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.115_2026-08-19-09-27-13_patch_4ac728c3-0342-4a36-adbc-e28d2d99b1ba +0 -0
  182. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.116_2026-08-19-09-30-47_patch_c706fef6-6813-4183-b268-12e7b00d7d0b +0 -0
  183. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.117_2026-08-19-09-39-14_patch_c6b0495f-2f88-4aa8-9ebf-0a235b4c407e +0 -0
  184. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.118_2026-08-19-09-52-00_patch_b395655a-8d78-4344-9266-6901c20f6517 +0 -0
  185. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.119_2026-08-19-10-22-38_patch_8f95c49d-aedc-41b8-816d-ccb95f048831 +0 -0
  186. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.120_2026-08-19-10-26-58_patch_7fbf35e6-cc01-4b75-8c9a-f5d054bcaf93 +0 -0
  187. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.121_2026-08-19-10-42-02_patch_31a81b02-a886-4dea-84e0-67cc6ca412d5 +0 -0
  188. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.122_2026-08-19-11-16-49_patch_1c4d7307-48d4-493e-936d-80af799d644b +0 -0
  189. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.123_2026-08-19-11-47-32_patch_d3d78d04-9989-45b1-91b1-93b571d8814a +0 -0
  190. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.124_2026-08-20-08-03-17_patch_57f4c389-2d19-41ce-aca4-13b61c62f387 +0 -0
  191. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.125_2026-08-20-08-25-05_patch_7f368148-0d1c-4525-bbdf-c6d257ad861a +0 -0
  192. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.126_2026-08-20-14-51-36_patch_a99abcc8-3371-4c63-a759-bb7ea5b32432 +0 -0
  193. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.127_2026-08-21-05-48-58_patch_34b4ccee-7596-4f57-93e9-774973cca58e +0 -0
  194. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.128_2026-08-21-10-47-20_patch_693112b9-927c-4a8f-8553-b06eef86079d +0 -0
  195. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.129_2026-08-21-11-16-54_patch_7a981666-01d9-4d1b-9ba3-2129744e3bd5 +0 -0
  196. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.130_2026-08-21-13-09-36_patch_b7ad1a76-ce70-4d70-9d1a-7c414eba5bb4 +0 -0
  197. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.131_2026-08-21-14-31-10_patch_9128ef66-193e-4caf-8710-afd86128e638 +0 -0
  198. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.132_2026-08-24-08-59-34_patch_c600fc14-86a5-460f-9c4e-f0177056f756 +0 -0
  199. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.133_2026-08-24-10-28-29_patch_b6ce3e32-9d7b-48ac-981a-270c22c180dd +0 -0
  200. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.134_2026-08-24-11-00-51_patch_a4fc0484-4a64-46a2-94f8-aa805254c7b0 +0 -0
  201. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.135_2026-08-24-12-12-41_patch_a870a56f-9a65-49eb-92da-f572b26667d8 +0 -0
  202. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.136_2026-08-24-12-42-46_patch_9b399356-6482-4291-8da7-e748a99c4b53 +0 -0
  203. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.137_2026-08-24-12-53-57_patch_f7979348-1910-40cd-a535-90299eca84ee +0 -0
  204. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.138_2026-08-24-14-36-30_patch_ed0f8750-f663-498b-85e7-0d3f2213fcfe +0 -0
  205. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.139_2026-08-25-08-37-26_patch_3ba87e19-902b-4f76-b64c-90e5c0ca1fc6 +0 -0
  206. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.140_2026-08-25-09-52-45_patch_abc830f2-df15-4385-b797-cdaf72c10752 +0 -0
  207. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.141_2026-08-25-11-37-20_patch_1d9ec01e-06f6-4c8e-b095-af17d5b62b00 +0 -0
  208. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.142_2026-08-26-07-38-49_patch_3dd23e36-e7df-494c-986f-a412861a8d40 +0 -0
  209. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.143_2026-08-26-09-32-32_patch_7b7ebd34-de27-4b73-98a7-3e1501e16cd5 +0 -0
  210. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.144_2026-08-26-10-56-43_patch_166064f2-2208-4c9b-9e25-25dc4cd32084 +0 -0
  211. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.145_2026-08-26-11-37-29_patch_b997f3ee-d7d3-4408-9f2f-c8b6d08bdb3b +0 -0
  212. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.146_2026-08-26-12-15-20_patch_afbbb893-25db-468c-81db-2663ca373068 +0 -0
  213. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.147_2026-08-26-14-10-50_patch_fd753b1f-2fa1-4ddb-a9e7-de690da85254 +0 -0
  214. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.148_2026-08-27-09-08-35_patch_23814c0b-7f77-489c-b4a8-ceadd18146e3 +0 -0
  215. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.149_2026-08-27-09-40-17_patch_8879d72e-a3d8-4abc-a16a-d9dcf75f0fa1 +0 -0
  216. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.150_2026-08-27-10-57-25_patch_afbe60ed-3e23-4d88-be3c-f800d7002a7d +0 -0
  217. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.151_2026-08-28-09-02-46_patch_1d4ca23b-aeae-4ea8-96b1-8cf57371f29d +0 -0
  218. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.152_2026-08-28-15-37-24_patch_c9d0bdc1-a7e1-432b-92b9-92dc76fe0c78 +0 -0
  219. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.153_2026-08-29-09-03-27_patch_7531573a-1b33-4092-aa9c-0e65f47b201f +0 -0
  220. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.154_2026-08-29-11-56-35_patch_919f5787-39c8-4dc1-ae6a-f27c28380f21 +0 -0
  221. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.155_2026-08-29-15-15-59_patch_822f9ed8-c366-4e5f-9791-dee8467cf3ce +0 -0
  222. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.156_2026-08-29-16-19-01_patch_3ac2bf36-20f7-4c9f-9fdb-295d4466d59e +0 -0
  223. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.157_2026-08-30-17-32-17_patch_4302354c-c9c5-4be7-acd3-542872a748d8 +0 -0
  224. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.158_2026-08-31-09-28-33_patch_3523774f-c25d-4102-8c1a-92fff046a48d +0 -0
  225. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.159_2026-08-31-10-31-01_patch_fe3e6290-2553-4154-a0a0-8b8a418280ed +0 -0
  226. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.160_2026-08-31-11-23-39_patch_e701a085-3d23-4212-b0af-73b1d419a4c1 +0 -0
  227. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.161_2026-08-31-12-41-01_patch_074d7bde-c493-44db-bc15-e81fd91e2921 +0 -0
  228. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.162_2026-08-31-13-58-06_patch_84db1d60-4280-433b-bd3a-22e5611cd315 +0 -0
  229. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.163_2026-08-31-15-25-54_patch_1931c5ba-73df-48cb-8dcb-555ace0af267 +0 -0
  230. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.163_2026-08-31-15-44-37_patch_3962e805-2a92-494a-a87b-b6e6d66c40a0 +0 -0
  231. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.165_2026-08-31-19-48-59_patch_86e5b923-2b99-4b86-b542-469b197614be +0 -0
  232. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.166_2026-09-01-07-39-57_patch_c344892f-d542-4e7b-8f27-02365a411e15 +0 -0
  233. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.167_2026-09-01-08-21-53_patch_e199d419-282a-4dbb-8756-cf98b7037e2b +0 -0
  234. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.168_2026-09-01-09-12-31_patch_235c9fe0-da15-431d-bb56-01e2b9b15f4b +0 -0
  235. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.169_2026-09-01-11-54-19_patch_98b617ab-d130-42b5-93f2-19cae56d4c4c +0 -0
  236. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.170_2026-09-02-09-27-28_patch_e448d2e6-b7ec-4235-96bf-0173b3623c87 +0 -0
  237. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.171_2026-09-02-12-52-44_patch_e6a241c2-1d62-482c-a9eb-9e3373395c50 +0 -0
  238. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.172_2026-09-04-08-47-04_patch_daae079f-c104-4fcd-bb57-7bff68e80ad9 +0 -0
  239. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.173_2026-09-04-12-34-42_patch_399c4cbd-0c28-4dfd-a4ec-e569420a36e4 +0 -0
  240. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.174_2026-09-04-13-08-48_patch_f5cfe3d5-808e-45e4-bafc-00d0554838ee +0 -0
  241. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.175_2026-09-04-17-20-46_patch_1ef542fa-5d8e-4d90-aa15-9fc4cea3dfec +0 -0
  242. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.176_2026-09-05-08-25-05_patch_ced5521f-f9da-4640-a921-95fcb5cd2e6d +0 -0
  243. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.177_2026-09-05-09-00-16_patch_803c1ad4-a9af-4953-92c5-d882dec03ea2 +0 -0
  244. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.178_2026-09-05-09-30-34_patch_012f6259-2e3f-4591-9806-1920fd06cb1f +0 -0
  245. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.179_2026-09-05-09-33-43_patch_f4bdf28c-d584-47a5-b699-8c883330162c +0 -0
  246. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.180_2026-09-05-12-02-21_patch_34a14b01-d22d-44a8-ac63-be0370a61422 +0 -0
  247. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.181_2026-09-05-12-47-46_patch_56b18867-99f6-4d5c-8215-7b9d60d34010 +0 -0
  248. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.182_2026-09-05-13-35-18_patch_61b7d4d1-73c8-4603-9b0c-593e7405587f +0 -0
  249. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.183_2026-09-06-07-27-09_patch_d76331b2-e3a3-4c0b-8412-ecd131b6ac02 +0 -0
  250. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.184_2026-09-06-10-21-47_patch_7680b7a1-49f0-4eef-b12e-4c854407448c +0 -0
  251. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.185_2026-09-06-10-30-40_patch_e56c2183-77f8-44ef-a92e-7377ea6ce8c1 +0 -0
  252. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.186_2026-09-07-10-00-51_patch_67de5683-d208-4bc0-8fb6-7677377908e7 +0 -0
  253. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.187_2026-09-07-10-18-13_patch_2086cee2-276b-48f7-80ce-6a17397b9541 +0 -0
  254. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.188_2026-09-07-12-51-28_patch_d6590822-068f-4a19-814d-34bbf204ba6e +0 -0
  255. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.189_2026-09-07-12-55-23_patch_7e0fb04b-4d40-4490-974f-c74ba2ae55a1 +0 -0
  256. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.190_2026-09-08-08-58-03_patch_15e3ac1e-4475-4272-bdd8-d00bb0db8f17 +0 -0
  257. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.191_2026-09-08-09-55-58_patch_3d350e50-ee53-4282-bc75-d2251142c46e +0 -0
  258. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.192_2026-09-08-11-12-21_patch_0733223b-1ae2-4b5b-897f-dfc57574ff83 +0 -0
  259. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.193_2026-09-08-21-48-17_patch_8d07d4e6-3555-4720-85c9-9452570fae2d +0 -0
  260. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.194_2026-09-09-07-53-43_patch_69559429-aa42-4b62-9bd7-cdfded1c00d0 +0 -0
  261. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.195_2026-09-09-09-55-40_patch_bbf67f1d-3b9a-43a2-b1bc-22df3fed8a34 +0 -0
  262. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.196_2026-09-09-09-59-47_patch_70d76812-7b3c-4192-ad49-fcaccc29b0da +0 -0
  263. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.197_2026-09-09-13-06-06_patch_d455be0b-5421-492a-b952-fab0fd8110f8 +0 -0
  264. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.198_2026-09-09-13-14-34_patch_267f54e5-311e-435e-882f-8e19191325ea +0 -0
  265. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.199_2026-09-09-22-24-18_patch_81e3e453-ca0e-42fa-9c21-8f94d43c05f2 +0 -0
  266. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.200_2026-09-10-07-19-50_patch_911714fa-1fa3-4165-bfe6-d10c650bf5bf +0 -0
  267. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.201_2026-09-10-10-14-19_patch_864015f2-b0b0-4563-a1c8-155629cb9126 +0 -0
  268. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.202_2026-09-10-11-00-05_patch_18270ecf-e770-4e69-8bcf-e5143c39929b +0 -0
  269. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.203_2026-09-10-11-10-41_patch_ff273ab1-44f3-4bc0-b184-3396e943df04 +0 -0
  270. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.204_2026-09-10-13-02-02_patch_d4ee41e2-d13c-4941-8605-3f1a42b56b22 +0 -0
  271. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.205_2026-09-10-13-57-50_patch_284df67e-5957-4b0c-bc64-5581db6ddecc +0 -0
  272. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.206_2026-09-11-10-18-50_patch_1ac7e410-0e62-4eef-bbe4-ebf93c9d0869 +0 -0
  273. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/17.0.207_2026-09-11-15-26-02_major_3f1b3ed7-eaac-41f5-b740-0af3331595d9 +0 -0
  274. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.0_2026-09-12-10-01-10_patch_8995783a-a9fa-4c4e-90b3-6386a4c481eb +0 -0
  275. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.10_2026-09-14-16-09-38_patch_9403d562-eed0-4125-a8b3-09cd92a13298 +0 -0
  276. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.11_2026-09-15-09-05-57_patch_8b22dba2-d931-4c4d-ae60-db3238d5e73d +0 -0
  277. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.12_2026-09-15-11-18-52_patch_81314afa-e70d-4ad8-b45b-3f8d62b983e7 +0 -0
  278. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.13_2026-09-16-08-00-55_patch_bfa30fc0-3281-4de6-bb56-d7290c98d1c3 +0 -0
  279. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.14_2026-09-16-14-38-26_patch_aae6e9b0-88f4-4bcf-b611-3308c7fcd6eb +0 -0
  280. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.15_2026-09-17-07-58-54_patch_43d40582-effd-4925-a8bd-e70fecf1faab +0 -0
  281. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.16_2026-09-17-08-12-37_patch_b4db2d23-88f1-45c1-82d9-78d38014fcb6 +0 -0
  282. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.17_2026-09-18-09-38-19_patch_25697fc3-e9a8-4980-962b-e6cb0a4760c5 +0 -0
  283. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.18_2026-09-18-09-54-33_patch_d37d9c71-c469-4d94-90d7-4898915ee991 +0 -0
  284. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.19_2026-09-18-10-47-33_patch_47607b3c-d1b6-4864-b9b0-00a2a8d2ac32 +0 -0
  285. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.1_2026-09-12-17-33-30_patch_f6ea2c99-a715-4c4d-876a-23ed8c62a83d +0 -0
  286. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.20_2026-09-18-11-07-21_patch_5a336f91-63a6-4877-97ed-da89395cc8f5 +0 -0
  287. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.21_2026-09-18-13-34-52_patch_c56462e1-63d9-498f-a912-c80c5f0171d1 +0 -0
  288. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.22_2026-09-20-08-10-45_patch_6afa2c20-bcef-4b7d-8685-2c9815d8683f +0 -0
  289. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.23_2026-09-20-08-38-35_patch_a7f169e5-37ab-4ec0-bf89-d14770181303 +0 -0
  290. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.24_2026-09-20-15-49-27_patch_c1222081-ff44-4f20-aea2-5840b6d76efd +0 -0
  291. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.25_2026-09-21-06-11-40_patch_6df46dd9-e7d3-4e71-bec4-e5c93b4ac863 +0 -0
  292. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.26_2026-09-21-07-54-11_patch_cc52dd36-5eba-4094-a1b0-d6f79f103441 +0 -0
  293. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.27_2026-09-21-08-36-49_patch_a25fa125-9bcd-4317-8da5-851c1c329631 +0 -0
  294. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.28_2026-09-21-09-44-01_patch_4430a721-0b3c-4f6a-b9bc-a53e667161bb +0 -0
  295. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.29_2026-09-21-10-58-07_patch_83b2b942-60a4-4bef-afd1-99690ba52b69 +0 -0
  296. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.2_2026-09-13-06-36-33_patch_176bb944-1c49-4dd3-a001-8fce908825a0 +0 -0
  297. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.30_2026-09-21-12-51-16_patch_519b9a65-d400-4234-b113-36b46e315507 +0 -0
  298. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.31_2026-09-22-06-53-35_patch_5c45a235-81b6-4d05-801a-07dc7db61400 +0 -0
  299. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.32_2026-09-22-07-42-04_patch_f12c6415-8166-4063-9e5d-26601b929d63 +0 -0
  300. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.33_2026-09-22-08-12-32_patch_cec31bb0-a6cb-43e6-8407-25aba322b54c +0 -0
  301. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.34_2026-09-23-07-09-16_patch_659fccbb-c0a0-4f6f-bc87-e6abaa8815a7 +0 -0
  302. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.35_2026-09-23-09-38-52_patch_023f904d-807a-4833-8a40-570365e8ec06 +0 -0
  303. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.36_2026-09-23-10-05-33_patch_846fb491-2b1b-47ed-ac1f-ba40e744e199 +0 -0
  304. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.37_2026-09-23-13-08-30_patch_8e4b1d24-156e-4ffe-8e4a-b8740ec18588 +0 -0
  305. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.38_2026-09-24-06-41-37_patch_67adb1d6-3f49-4357-a67f-b1d48f23a972 +0 -0
  306. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.39_2026-09-24-15-24-32_patch_e5dd375d-5643-4514-9b65-8d877c4a2bb2 +0 -0
  307. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.3_2026-09-13-12-32-46_patch_58e5ce3a-f2a7-4789-b2cd-5cc75c72b6ec +0 -0
  308. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.40_2026-09-24-19-58-14_patch_ff18824b-be51-4a3d-a621-e96279e53c3e +0 -0
  309. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.41_2026-09-26-09-24-52_patch_b9979267-30f9-440a-a4ce-c611991d4886 +0 -0
  310. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.42_2026-09-28-12-39-34_patch_dda535d9-8922-4eb9-ab51-6ecff0650c10 +0 -0
  311. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.43_2026-09-28-13-35-27_minor_aca1168a-1286-4326-9d0c-2f2587c9fe92 +0 -0
  312. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.4_2026-09-13-12-45-14_patch_b6c79d55-8f85-4f47-a304-df52b122c38c +0 -0
  313. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.5_2026-09-13-14-11-18_patch_9b111116-5e62-472a-b72c-d1bbafa22c97 +0 -0
  314. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.5_2026-09-13-17-01-11_patch_d4bf61c0-83ac-4dd3-b512-a65805d298c8 +0 -0
  315. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.6_2026-09-14-11-31-04_patch_fd2ebda6-22cb-4e7d-9452-2f6f2640e828 +0 -0
  316. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.7_2026-09-13-17-06-08_patch_428af161-0b27-43c2-8751-e5f7874df120 +0 -0
  317. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.0.9_2026-09-14-12-37-42_patch_b2ca0529-4b67-4fa4-8fdc-5f5e9f5d5166 +0 -0
  318. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.1.0_2026-09-28-14-27-54_patch_324444f7-d24e-4189-b21f-1188894a3109 +0 -0
  319. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/18.1.1_2026-09-28-21-03-07_major_e266a14a-7d96-4ece-92a3-8f34e64438a5 +0 -0
  320. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.0_2026-09-29-11-05-31_patch_77d6f9f8-ead3-4d79-a4b2-b084b2dffc98 +0 -0
  321. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.10_2026-10-02-12-56-52_patch_14e97576-73ca-44b8-82c9-7dad6f1789ab +0 -0
  322. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.11_2026-10-04-10-31-19_patch_088eb371-1799-4949-a119-286cf1cd55d1 +0 -0
  323. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.12_2026-10-06-18-00-25_patch_36554bed-49c5-41cb-9fd4-48cc6af74c09 +0 -0
  324. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.13_2026-10-07-12-24-08_patch_a540a364-3a0d-4960-b278-06ba2c7cc258 +0 -0
  325. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.14_2026-10-07-12-52-39_patch_e3a6fc5c-2ee4-414c-a2dd-4910a655a7dd +0 -0
  326. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.15_2026-10-09-04-15-56_patch_bd7a9b06-867b-4fea-9678-973a05e3022d +0 -0
  327. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.16_2026-10-09-16-11-56_patch_a1135435-7dea-4f00-8c98-203ba3974382 +0 -0
  328. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.17_2026-10-09-17-44-55_patch_faeacad8-541a-40f2-ab9c-abcd66fcd00e +0 -0
  329. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.1_2026-09-29-11-59-38_patch_bbf4753c-d641-4c2f-ac7c-02be6bd8e7c2 +0 -0
  330. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.2_2026-09-29-12-44-07_patch_19fdaa94-60dc-464b-93b8-c17607ebc7b6 +0 -0
  331. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.3_2026-09-29-14-16-00_patch_3cb60272-95cf-4311-8897-721e1b5c2c88 +0 -0
  332. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.4_2026-09-29-16-24-53_patch_9fe8ad2b-e3ec-4558-a5fc-9c44c5c266dc +0 -0
  333. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.5_2026-09-29-17-13-16_patch_e48d2dd2-f41a-402e-a441-756b23c01dcb +0 -0
  334. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.6_2026-09-29-17-22-11_patch_3b1c79e9-9002-4e96-ba78-10668c33be6a +0 -0
  335. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.7_2026-09-30-07-50-58_patch_e8b1f046-d819-499c-9cd5-3e1a20fc9acf +0 -0
  336. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.8_2026-10-01-13-41-44_patch_7d63af18-e0af-4127-ab58-aede2407490f +0 -0
  337. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/19.0.9_2026-10-01-15-57-35_patch_143863cb-8f63-4ef7-bd78-c1114fc93a2d +0 -0
  338. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/__init__.py +0 -0
  339. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli/version/read_version.py +0 -0
  340. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli.egg-info/dependency_links.txt +0 -0
  341. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli.egg-info/entry_points.txt +0 -0
  342. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli.egg-info/not-zip-safe +0 -0
  343. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli.egg-info/requires.txt +0 -0
  344. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/ellf_cli.egg-info/top_level.txt +0 -0
  345. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/pyproject.toml +0 -0
  346. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/setup.cfg +0 -0
  347. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/setup.py +0 -0
  348. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_agents_info_stats.py +0 -0
  349. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_appdirs.py +0 -0
  350. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_auth.py +0 -0
  351. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_clusters_info_stats.py +0 -0
  352. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_config.py +0 -0
  353. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_datasets_export.py +0 -0
  354. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_errors.py +0 -0
  355. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_files_cp.py +0 -0
  356. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_files_cp_helpers.py +0 -0
  357. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_helm.py +0 -0
  358. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_import_export.py +0 -0
  359. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_info.py +0 -0
  360. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_config_io.py +0 -0
  361. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_configure.py +0 -0
  362. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_deploy_node_labels.py +0 -0
  363. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_destroy.py +0 -0
  364. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_get_terraform.py +0 -0
  365. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_hibernate.py +0 -0
  366. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_init.py +0 -0
  367. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_pause.py +0 -0
  368. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_provision.py +0 -0
  369. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_start_fixes.py +0 -0
  370. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_start_validation.py +0 -0
  371. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_state_bucket.py +0 -0
  372. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_infra_terraform_init.py +0 -0
  373. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_invalid_secrets.py +0 -0
  374. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_job_list_project_filter.py +0 -0
  375. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_jobs_info_hides_creator.py +0 -0
  376. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_jobs_list_unmatched.py +0 -0
  377. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_key_pair.py +0 -0
  378. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_logout.py +0 -0
  379. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_main.py +0 -0
  380. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_org_select.py +0 -0
  381. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_plans.py +0 -0
  382. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_projects.py +0 -0
  383. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_projects_delete_confirm.py +0 -0
  384. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_publish_build_poll.py +0 -0
  385. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_publish_data.py +0 -0
  386. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_publish_import_root.py +0 -0
  387. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_publish_requirements.py +0 -0
  388. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_pypi_auth.py +0 -0
  389. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_query.py +0 -0
  390. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_recipe_file.py +0 -0
  391. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_recipe_required_args.py +0 -0
  392. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_recipes.py +0 -0
  393. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_sessions.py +0 -0
  394. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_state.py +0 -0
  395. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_todos.py +0 -0
  396. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_ty.py +0 -0
  397. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_ui.py +0 -0
  398. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_ui_extras.py +0 -0
  399. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_usage_counts.py +0 -0
  400. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_users_assign.py +0 -0
  401. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_users_info_stats.py +0 -0
  402. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_users_list.py +0 -0
  403. {ellf_cli-19.0.18 → ellf_cli-20.0.0}/tests/test_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ellf-cli
3
- Version: 19.0.18
3
+ Version: 20.0.0
4
4
  Summary: Ellf Command Line Interface
5
5
  Home-page: https://prodi.gy
6
6
  Author: ExplosionAI GmbH
@@ -939,6 +939,14 @@ Stop a job on the cluster by its ID. Works for workloads that have no matching j
939
939
  | `--type` | `str` | Job type, if the cluster does not report one | `None` |
940
940
  | `--json` | `bool` | Output the result as JSON | `False` |
941
941
 
942
+ ### `ellf mcp`
943
+
944
+ MCP servers that coding agents start themselves after 'ellf login --agent'
945
+
946
+ #### `ellf mcp kb`
947
+
948
+ Run the Ellf knowledge base MCP server over stdio, using your ellf login. Coding agents start this themselves once 'ellf login --agent' has set them up.
949
+
942
950
  ### `ellf packages`
943
951
 
944
952
  View and manage Python packages on the cluster
@@ -1401,8 +1409,8 @@ Send a support request to the Ellf team.
1401
1409
  | `--project` | `str` | Name, slug, or ID of support request's project or the last project if not set | `None` |
1402
1410
  | `--no-project` | `bool` | Explicitly send the request without any project association | `False` |
1403
1411
  | `--conversation` | `UUID` | Conversation ID to attach from PAM when available | `None` |
1404
- | `--session-id` | `str` | Claude Code session ID to use for transcript/debug attachment lookup | `None` |
1405
- | `--transcript-path` | `str` | Path to a Claude transcript .jsonl file to attach explicitly | `None` |
1412
+ | `--session-id` | `str` | Agent session ID to use for transcript/debug attachment lookup (defaults to the current session) | `None` |
1413
+ | `--transcript-path` | `str` | Path to a session transcript file to attach explicitly | `None` |
1406
1414
  | `--transcript-consent` | `str` | Explicit transcript consent mode: 'summary_only' or 'attach_full_transcript' | `'summary_only'` |
1407
1415
  | `--json` | `bool` | Output the result as JSON | `False` |
1408
1416
 
@@ -1671,7 +1679,8 @@ Log in to your Ellf account. You normally don't need to call this manually. It w
1671
1679
  | `--org` | `str` | Name or ID of the organization to log into. If omitted: auto-select when only one is available, or prompt interactively | `None` |
1672
1680
  | `--cluster` | `str` | Name or ID of the cluster to log into. If omitted: auto-select when only one is available, or prompt interactively | `None` |
1673
1681
  | `--json` | `bool` | Output the result as JSON | `False` |
1674
- | `--claude` | `bool` | Install Ellf Claude Code skills and transcript hook into ~/.claude/ | `False` |
1682
+ | `--agent` | `str` | Set up coding agents to work with Ellf: install the Ellf skills and the knowledge base MCP server. One of claude, codex, opencode, copilot; repeat the option or comma-separate them for several | `None` |
1683
+ | `--claude` | `bool` | Shortcut for --agent claude | `False` |
1675
1684
 
1676
1685
  ### `ellf logout`
1677
1686
 
@@ -0,0 +1,367 @@
1
+ """Local coding agents: where their skills and MCP servers are configured, and
2
+ where they keep session transcripts."""
3
+
4
+ import importlib.util
5
+ import json
6
+ import os
7
+ import re
8
+ import shutil
9
+ import sys
10
+ from dataclasses import dataclass
11
+ from pathlib import Path
12
+ from types import ModuleType
13
+ from typing import Any, Callable, Optional, Union
14
+
15
+ AGENTS = ("claude", "codex", "opencode", "copilot")
16
+ AGENT_NAMES = {
17
+ "claude": "Claude Code",
18
+ "codex": "Codex",
19
+ "opencode": "OpenCode",
20
+ "copilot": "GitHub Copilot",
21
+ }
22
+ MCP_SERVER_NAME = "ellf-kb"
23
+
24
+
25
+ def _home() -> Path:
26
+ return Path.home()
27
+
28
+
29
+ def _env_dir(var: str, default: Path) -> Path:
30
+ value = (os.environ.get(var) or "").strip()
31
+ return Path(value).expanduser() if value else default
32
+
33
+
34
+ def _codex_home() -> Path:
35
+ return _env_dir("CODEX_HOME", _home() / ".codex")
36
+
37
+
38
+ def _copilot_home() -> Path:
39
+ return _env_dir("COPILOT_HOME", _home() / ".copilot")
40
+
41
+
42
+ def _opencode_config_dir() -> Path:
43
+ return _env_dir("XDG_CONFIG_HOME", _home() / ".config") / "opencode"
44
+
45
+
46
+ def _vscode_user_dir() -> Path:
47
+ if sys.platform == "darwin":
48
+ return _home() / "Library" / "Application Support" / "Code" / "User"
49
+ if sys.platform == "win32":
50
+ return _env_dir("APPDATA", _home() / "AppData" / "Roaming") / "Code" / "User"
51
+ return _env_dir("XDG_CONFIG_HOME", _home() / ".config") / "Code" / "User"
52
+
53
+
54
+ def skills_dirs(agent: str) -> list[Path]:
55
+ """The user-level skill directories an agent reads ellf skills from."""
56
+ if agent == "claude":
57
+ return [_home() / ".claude" / "skills"]
58
+ # Codex, OpenCode and Copilot (CLI and VS Code) all read ~/.agents/skills.
59
+ dirs = [_home() / ".agents" / "skills"]
60
+ if agent == "copilot" and os.environ.get("COPILOT_HOME"):
61
+ # Copilot CLI stops reading ~/.agents/skills when COPILOT_HOME is set.
62
+ dirs.append(_copilot_home() / "skills")
63
+ return dirs
64
+
65
+
66
+ def ellf_skills_dir() -> Optional[Path]:
67
+ path = Path(__file__).resolve().parent / "ellf_skills"
68
+ return path if (path / "render.py").exists() else None
69
+
70
+
71
+ def _load_renderer(skills_dir: Path) -> ModuleType:
72
+ spec = importlib.util.spec_from_file_location(
73
+ "ellf_skills_render", skills_dir / "render.py"
74
+ )
75
+ assert spec is not None and spec.loader is not None
76
+ module = importlib.util.module_from_spec(spec)
77
+ spec.loader.exec_module(module)
78
+ return module
79
+
80
+
81
+ def install_skills(
82
+ agents: list[str],
83
+ skills_dir: Path,
84
+ confirm_removal: Callable[[list[Path]], bool],
85
+ ) -> dict[Path, list[str]]:
86
+ """Render the coding skills into every directory the agents read.
87
+
88
+ Skill folders left by an install from before the renderer kept a record
89
+ are passed to ``confirm_removal`` and only removed if it returns True.
90
+ """
91
+ renderer = _load_renderer(skills_dir)
92
+ dests: list[Path] = []
93
+ for agent in agents:
94
+ for path in skills_dirs(agent):
95
+ if path not in dests:
96
+ dests.append(path)
97
+ installed = {}
98
+ for dest in dests:
99
+ stale = renderer.unrecorded_skills("coding", dest)
100
+ if stale and not confirm_removal([dest / name for name in stale]):
101
+ stale = []
102
+ installed[dest] = renderer.render_skills("coding", dest, remove=stale)
103
+ return installed
104
+
105
+
106
+ # MCP configuration
107
+
108
+
109
+ def mcp_command() -> Optional[list[str]]:
110
+ """How agents start the knowledge base server: this install's ellf script
111
+ by absolute path, as agents don't run it from the user's shell. Not
112
+ ``python -m ellf_cli``, which puts the agent's working directory first on
113
+ sys.path, where a project's own modules would shadow the CLI's imports."""
114
+ script = Path(sys.argv[0])
115
+ if not (script.stem == "ellf" and script.is_file()):
116
+ found = shutil.which("ellf")
117
+ if found is None:
118
+ return None
119
+ script = Path(found)
120
+ return [str(script.absolute()), "mcp", "kb"]
121
+
122
+
123
+ class MCPConfigError(Exception):
124
+ """The agent's config file couldn't be updated; ``snippet`` is what to add
125
+ by hand."""
126
+
127
+ def __init__(self, path: Path, reason: str, snippet: str) -> None:
128
+ super().__init__(f"Could not update {path}: {reason}")
129
+ self.path = path
130
+ self.snippet = snippet
131
+
132
+
133
+ def _write_private(path: Path, text: str) -> None:
134
+ """Replace a config file atomically. Agent configs often hold other MCP
135
+ servers' tokens, so the file is readable by the user only, from the moment
136
+ it's created. A symlinked config is written through to its target."""
137
+ path = path.resolve()
138
+ path.parent.mkdir(parents=True, exist_ok=True)
139
+ tmp_path = path.with_name(path.name + ".ellf.tmp")
140
+ tmp_path.unlink(missing_ok=True)
141
+ flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_BINARY", 0)
142
+ with open(os.open(tmp_path, flags, 0o600), "w", encoding="utf-8") as f:
143
+ f.write(text)
144
+ tmp_path.replace(path)
145
+
146
+
147
+ def _set_json_entry(path: Path, keys: tuple[str, ...], entry: dict) -> None:
148
+ nested: dict[str, Any] = entry
149
+ for key in reversed(keys):
150
+ nested = {key: nested}
151
+ snippet = json.dumps(nested, indent=2)
152
+ config: dict[str, Any] = {}
153
+ if path.exists():
154
+ try:
155
+ config = json.loads(path.read_text(encoding="utf-8") or "{}")
156
+ except json.JSONDecodeError as e:
157
+ raise MCPConfigError(path, f"not plain JSON ({e})", snippet) from e
158
+ if not isinstance(config, dict):
159
+ raise MCPConfigError(path, "not a JSON object", snippet)
160
+ parent = config
161
+ for key in keys[:-1]:
162
+ child = parent.setdefault(key, {})
163
+ if not isinstance(child, dict):
164
+ raise MCPConfigError(path, f"'{key}' is not an object", snippet)
165
+ parent = child
166
+ parent[keys[-1]] = entry
167
+ _write_private(path, json.dumps(config, indent=2, ensure_ascii=False) + "\n")
168
+
169
+
170
+ _TOML_HEADER_RE = re.compile(r"^\s*\[")
171
+
172
+
173
+ def _is_server_table(line: str, name: str) -> bool:
174
+ quoted = rf"(?:{re.escape(name)}|\"{re.escape(name)}\"|'{re.escape(name)}')"
175
+ return bool(
176
+ re.match(
177
+ rf"^\s*\[\s*mcp_servers\s*\.\s*{quoted}\s*(\.[^\]]*)?\]\s*(#.*)?$", line
178
+ )
179
+ )
180
+
181
+
182
+ def _trailing_comments(lines: list[str]) -> list[str]:
183
+ start = len(lines)
184
+ while start > 0 and lines[start - 1].strip()[:1] in ("", "#"):
185
+ start -= 1
186
+ return lines[start:]
187
+
188
+
189
+ def set_codex_mcp_server(text: str, name: str, command: list[str]) -> str:
190
+ """Return config.toml with the ``[mcp_servers.<name>]`` table replaced.
191
+
192
+ Edited as text so the user's formatting and comments survive; the result
193
+ is re-parsed and refused unless it holds exactly the new server.
194
+ """
195
+ table = (
196
+ f"[mcp_servers.{name}]\n"
197
+ f"command = {json.dumps(command[0])}\n"
198
+ f"args = {json.dumps(command[1:])}\n"
199
+ )
200
+ kept: list[str] = []
201
+ dropped: list[str] = []
202
+ skipping = False
203
+ for line in text.splitlines(keepends=True):
204
+ if _TOML_HEADER_RE.match(line):
205
+ ours = _is_server_table(line, name)
206
+ if skipping and not ours:
207
+ # Comments right above the next table belong to it.
208
+ kept.extend(_trailing_comments(dropped))
209
+ skipping = ours
210
+ dropped = []
211
+ (dropped if skipping else kept).append(line)
212
+ body = "".join(kept).rstrip("\n")
213
+ result = (body + "\n\n" if body else "") + table
214
+ try:
215
+ import tomllib
216
+ except ImportError:
217
+ if body.strip():
218
+ raise ValueError("can't check the edited file without Python 3.11+")
219
+ return result
220
+ try:
221
+ parsed = tomllib.loads(result)
222
+ except tomllib.TOMLDecodeError as e:
223
+ raise ValueError(f"not valid TOML after the edit ({e})") from e
224
+ server = parsed.get("mcp_servers", {}).get(name)
225
+ if server != {"command": command[0], "args": command[1:]}:
226
+ raise ValueError(f"mcp_servers.{name} is also defined outside its own table")
227
+ return result
228
+
229
+
230
+ def _configure_codex(command: list[str]) -> Path:
231
+ path = _codex_home() / "config.toml"
232
+ text = path.read_text(encoding="utf-8") if path.exists() else ""
233
+ try:
234
+ updated = set_codex_mcp_server(text, MCP_SERVER_NAME, command)
235
+ except ValueError as e:
236
+ snippet = set_codex_mcp_server("", MCP_SERVER_NAME, command)
237
+ raise MCPConfigError(path, str(e), snippet) from e
238
+ _write_private(path, updated)
239
+ return path
240
+
241
+
242
+ def _configure_claude(command: list[str]) -> Path:
243
+ # Claude Code keeps user-scoped MCP servers at the top level of
244
+ # ~/.claude.json, which makes the server available in every project.
245
+ path = _home() / ".claude.json"
246
+ entry = {"type": "stdio", "command": command[0], "args": command[1:]}
247
+ _set_json_entry(path, ("mcpServers", MCP_SERVER_NAME), entry)
248
+ return path
249
+
250
+
251
+ def _configure_opencode(command: list[str]) -> Path:
252
+ config_dir = _opencode_config_dir()
253
+ candidates = [
254
+ config_dir / n for n in ("opencode.json", "opencode.jsonc", "config.json")
255
+ ]
256
+ path = next((p for p in candidates if p.exists()), candidates[0])
257
+ entry = {"type": "local", "command": command, "enabled": True}
258
+ _set_json_entry(path, ("mcp", MCP_SERVER_NAME), entry)
259
+ return path
260
+
261
+
262
+ def _configure_copilot_cli(command: list[str]) -> Path:
263
+ path = _copilot_home() / "mcp-config.json"
264
+ entry = {
265
+ "type": "local",
266
+ "command": command[0],
267
+ "args": command[1:],
268
+ "tools": ["*"],
269
+ }
270
+ _set_json_entry(path, ("mcpServers", MCP_SERVER_NAME), entry)
271
+ return path
272
+
273
+
274
+ def _configure_vscode(command: list[str]) -> Optional[Path]:
275
+ # VS Code keeps its own user mcp.json; only touch it when VS Code is there.
276
+ vscode_dir = _vscode_user_dir()
277
+ if not vscode_dir.is_dir():
278
+ return None
279
+ path = vscode_dir / "mcp.json"
280
+ entry = {"type": "stdio", "command": command[0], "args": command[1:]}
281
+ _set_json_entry(path, ("servers", MCP_SERVER_NAME), entry)
282
+ return path
283
+
284
+
285
+ _MCP_CONFIGURERS: dict[str, list[Callable[[list[str]], Optional[Path]]]] = {
286
+ "claude": [_configure_claude],
287
+ "codex": [_configure_codex],
288
+ "opencode": [_configure_opencode],
289
+ "copilot": [_configure_copilot_cli, _configure_vscode],
290
+ }
291
+
292
+
293
+ def configure_mcp(agent: str, command: list[str]) -> list[Union[Path, MCPConfigError]]:
294
+ """Point the agent's user MCP configs at the knowledge base ``command``.
295
+
296
+ Returns, per config file, the path written or the error that left it as
297
+ it was, so one file that can't be edited doesn't hide the others.
298
+ """
299
+ results: list[Union[Path, MCPConfigError]] = []
300
+ for configure in _MCP_CONFIGURERS[agent]:
301
+ try:
302
+ path = configure(command)
303
+ except MCPConfigError as e:
304
+ results.append(e)
305
+ else:
306
+ if path is not None:
307
+ results.append(path)
308
+ return results
309
+
310
+
311
+ # Session transcripts
312
+
313
+
314
+ @dataclass
315
+ class AgentSession:
316
+ agent: str
317
+ session_id: str
318
+
319
+
320
+ # Ordered: Codex sets both, and its rollout files are named after the thread.
321
+ _SESSION_ENV_VARS = (
322
+ ("CLAUDE_CODE_SESSION_ID", "claude"),
323
+ ("CODEX_THREAD_ID", "codex"),
324
+ ("CODEX_SESSION_ID", "codex"),
325
+ ("COPILOT_AGENT_SESSION_ID", "copilot"),
326
+ )
327
+
328
+
329
+ def current_session() -> Optional[AgentSession]:
330
+ """The agent session this process runs in, from the variables agents set
331
+ for the commands they run. OpenCode sets none.
332
+
333
+ An agent started from another agent's shell inherits the outer agent's
334
+ variables too, and nothing says which one is running this command. Rather
335
+ than attach the wrong conversation, that case counts as no session.
336
+ """
337
+ sessions = {}
338
+ for var, agent in _SESSION_ENV_VARS:
339
+ value = (os.environ.get(var) or "").strip()
340
+ if value and agent not in sessions:
341
+ sessions[agent] = AgentSession(agent=agent, session_id=value)
342
+ return next(iter(sessions.values())) if len(sessions) == 1 else None
343
+
344
+
345
+ def find_transcript(session: AgentSession) -> Optional[Path]:
346
+ if session.agent == "claude":
347
+ root = _home() / ".claude" / "projects"
348
+ pattern = f"{session.session_id}.jsonl"
349
+ elif session.agent == "codex":
350
+ root = _codex_home() / "sessions"
351
+ pattern = f"rollout-*-{session.session_id}.jsonl"
352
+ elif session.agent == "copilot":
353
+ path = _copilot_home() / "session-state" / session.session_id / "events.jsonl"
354
+ return path if path.exists() else None
355
+ else:
356
+ return None
357
+ if not root.exists():
358
+ return None
359
+ matches = sorted(root.rglob(pattern))
360
+ return matches[0] if matches else None
361
+
362
+
363
+ def debug_log_path(session: AgentSession) -> Optional[Path]:
364
+ """Only Claude Code keeps a per-session debug log."""
365
+ if session.agent != "claude":
366
+ return None
367
+ return _home() / ".claude" / "debug" / f"{session.session_id}.txt"
@@ -114,6 +114,7 @@ cli.placeholder("files", description=Messages.doc_files)
114
114
  cli.placeholder("gcp", description=Messages.doc_gcp)
115
115
  cli.placeholder("infra", description=Messages.doc_infra)
116
116
  cli.placeholder("jobs", description=Messages.doc_jobs)
117
+ cli.placeholder("mcp", description=Messages.doc_mcp)
117
118
  cli.placeholder("packages", description=Messages.doc_packages)
118
119
  cli.placeholder("plans", description="Manage project plans")
119
120
  cli.placeholder("paths", description=Messages.doc_paths)
@@ -11,6 +11,7 @@ from . import (
11
11
  import_export,
12
12
  infra,
13
13
  jobs,
14
+ mcp,
14
15
  packages,
15
16
  paths,
16
17
  plans,
@@ -45,6 +46,7 @@ __all__ = [
45
46
  "files",
46
47
  "infra",
47
48
  "jobs",
49
+ "mcp",
48
50
  "packages",
49
51
  "paths",
50
52
  "projects",
@@ -1,6 +1,6 @@
1
- import json
2
1
  import os
3
- import shutil
2
+ import shlex
3
+ import sys
4
4
  from pathlib import Path
5
5
  from typing import Any, Dict, List, Literal, Optional, Union
6
6
  from uuid import UUID
@@ -12,91 +12,111 @@ from wasabi import msg
12
12
  from ellf_pam_sdk.models import OrgMembership
13
13
 
14
14
  from .. import about
15
+ from ..agents import (
16
+ AGENT_NAMES,
17
+ AGENTS,
18
+ MCP_SERVER_NAME,
19
+ MCPConfigError,
20
+ configure_mcp,
21
+ ellf_skills_dir,
22
+ install_skills,
23
+ mcp_command,
24
+ )
15
25
  from ..auth import AuthState
16
26
  from ..cli import cli
17
27
  from ..config import SavedSettings, global_config_dir
18
28
  from ..errors import CLIError, EllfError, NoClustersError
19
29
  from ..messages import CLUSTER_DOCS_URL, Messages
20
- from ..ui import is_silent, print_as_json, print_mutation_result
30
+ from ..ui import is_silent, isatty, print_as_json, print_mutation_result
21
31
  from ..util import URL
22
32
  from ._cluster_select import select_cluster
23
33
  from ._org_select import list_person_orgs, select_org
24
34
  from ._state import get_auth_state, get_root_cfg, get_saved_settings
25
35
 
26
36
 
27
- def _ellf_claude_plugin_dir() -> Path | None:
28
- package_root = Path(__file__).resolve().parents[1]
29
- plugin_dir = package_root / "ellf_skills"
30
- if (plugin_dir / "skill_variants.json").exists():
31
- return plugin_dir
32
- return None
33
-
34
-
35
- def _ellf_skill_variants(plugin_dir: Path) -> dict[str, dict[str, str]]:
36
- manifest_path = plugin_dir / "skill_variants.json"
37
- return json.loads(manifest_path.read_text(encoding="utf-8"))
37
+ def _resolve_agents(agent: Optional[List[str]], claude: bool) -> List[str]:
38
+ agents = [
39
+ name.strip().lower()
40
+ for value in agent or []
41
+ for name in value.split(",")
42
+ if name.strip()
43
+ ]
44
+ if claude:
45
+ agents.append("claude")
46
+ unknown = sorted(set(agents) - set(AGENTS))
47
+ if unknown:
48
+ raise CLIError(
49
+ f"Unknown agent: {', '.join(unknown)}",
50
+ f"Choose from: {', '.join(AGENTS)}",
51
+ )
52
+ return [a for a in AGENTS if a in agents]
53
+
54
+
55
+ def _confirm_skill_removal(paths: List[Path]) -> bool:
56
+ """Ask before removing skills an older ellf login installed. They're
57
+ named after Ellf skills but may hold the user's own edits."""
58
+ msg.warn("Found Ellf skills that Ellf no longer installs:")
59
+ for path in paths:
60
+ print(f" - {path}")
61
+ if isatty(sys.stdin) and isatty(sys.stdout):
62
+ if input("Remove them? [y/N]: ").strip().lower() in ("y", "yes"):
63
+ return True
64
+ print(
65
+ "Kept them. To remove them later, run: rm -rf "
66
+ + " ".join(shlex.quote(str(path)) for path in paths)
67
+ )
68
+ return False
38
69
 
39
70
 
40
- def _configure_claude_mcp(auth: AuthState) -> None:
41
- ellf_core_token = auth.get_ellf_core_token()
42
- if not ellf_core_token:
71
+ def _install_agent_skills(agents: List[str]) -> None:
72
+ skills_dir = ellf_skills_dir()
73
+ if skills_dir is None:
43
74
  msg.warn(
44
- "Could not get ellf-core token; skipping MCP server configuration. "
45
- "Re-run 'ellf login --claude' after a fresh login."
75
+ "Packaged Ellf skills not found; skipping skill installation. "
76
+ "Reinstall ellf-cli to get them."
46
77
  )
47
78
  return
48
- mcp_url = str(auth.pam_url / "ellf-core" / "mcp")
49
- # CC stores user-scoped MCP servers at the top level of ~/.claude.json.
50
- # Writing there makes the KB available in every project, not just this one.
51
- claude_json_path = Path.home() / ".claude.json"
52
- config: dict = {}
53
- if claude_json_path.exists():
54
- try:
55
- config = json.loads(claude_json_path.read_text(encoding="utf-8"))
56
- except json.JSONDecodeError as e:
57
- msg.fail(
58
- f"Could not parse {claude_json_path}: {e}",
59
- "Fix the file manually, then re-run 'ellf login --claude'.",
60
- )
61
- return
62
- config.setdefault("mcpServers", {})
63
- config["mcpServers"]["ellf-kb"] = {
64
- "type": "http",
65
- "url": mcp_url,
66
- "headers": {"Authorization": f"Bearer {ellf_core_token}"},
67
- }
68
- tmp_path = claude_json_path.with_suffix(".json.tmp")
69
- tmp_path.write_text(
70
- json.dumps(config, indent=2, ensure_ascii=False), encoding="utf-8"
71
- )
72
- tmp_path.replace(claude_json_path)
73
- msg.good(f"Configured ellf-kb MCP server in {claude_json_path}")
79
+ try:
80
+ installed = install_skills(agents, skills_dir, _confirm_skill_removal)
81
+ except (OSError, ValueError) as e:
82
+ msg.fail(
83
+ f"Could not install the Ellf skills: {e}",
84
+ "Fix that, then re-run 'ellf login --agent <agent>'.",
85
+ )
86
+ return
87
+ for dest, names in installed.items():
88
+ msg.good(f"Installed {len(names)} Ellf skills to {dest}")
89
+ for name in names:
90
+ print(f" - {name}")
74
91
 
75
92
 
76
- def _install_claude_skills() -> None:
77
- plugin_dir = _ellf_claude_plugin_dir()
78
- if plugin_dir is None:
93
+ def _configure_agent_mcp(auth: AuthState, agents: List[str]) -> None:
94
+ if not auth.get_ellf_core_token():
95
+ msg.warn(
96
+ "Could not get an ellf-core token, so the knowledge base MCP server "
97
+ "won't work until a fresh 'ellf login'."
98
+ )
99
+ command = mcp_command()
100
+ if command is None:
79
101
  msg.warn(
80
- "Packaged ellf Claude plugin not found. "
81
- "Install the ellf-skills plugin assets to use --claude."
102
+ "Could not find the ellf command; skipping MCP server configuration. "
103
+ "Run 'ellf login --agent <agent>' from the environment it's installed in."
82
104
  )
83
105
  return
84
- claude_dir = Path.home() / ".claude"
85
- dest = claude_dir / "skills"
86
- dest.mkdir(parents=True, exist_ok=True)
87
- selected_skills = {
88
- canonical_name: plugin_dir / "skills" / variants["coding"]
89
- for canonical_name, variants in _ellf_skill_variants(plugin_dir).items()
90
- if "coding" in variants
91
- }
92
- for canonical_name, skill_dir in sorted(selected_skills.items()):
93
- dst = dest / canonical_name
94
- if dst.exists():
95
- shutil.rmtree(dst)
96
- shutil.copytree(skill_dir, dst)
97
- msg.good(f"Installed {len(selected_skills)} Claude Code skills to {dest}")
98
- for canonical_name in sorted(selected_skills):
99
- print(f" - {canonical_name}")
106
+ for agent in agents:
107
+ try:
108
+ results = configure_mcp(agent, command)
109
+ except (OSError, ValueError) as e:
110
+ msg.fail(f"Could not configure {AGENT_NAMES[agent]}: {e}")
111
+ continue
112
+ for result in results:
113
+ if isinstance(result, MCPConfigError):
114
+ msg.fail(str(result), f"Add this to it by hand:\n{result.snippet}")
115
+ else:
116
+ msg.good(
117
+ f"Configured {MCP_SERVER_NAME} MCP server for "
118
+ f"{AGENT_NAMES[agent]} in {result}"
119
+ )
100
120
 
101
121
 
102
122
  def _configure_venv_pypi(auth: AuthState, *, as_json: bool = False) -> None:
@@ -158,6 +178,7 @@ def _configure_venv_pypi(auth: AuthState, *, as_json: bool = False) -> None:
158
178
  org=Arg("--org", help=Messages.login_org),
159
179
  cluster=Arg("--cluster", help=Messages.login_cluster),
160
180
  as_json=Arg("--json", help=Messages.as_json),
181
+ agent=Arg("--agent", help=Messages.login_agent),
161
182
  claude=Arg("--claude", help=Messages.claude),
162
183
  )
163
184
  def login(
@@ -167,12 +188,14 @@ def login(
167
188
  org: Optional[Union[str, UUID]] = None,
168
189
  cluster: Optional[Union[str, UUID]] = None,
169
190
  as_json: bool = False,
191
+ agent: Optional[List[str]] = None,
170
192
  claude: bool = False,
171
193
  ) -> None:
172
194
  """
173
195
  Log in to your Ellf account. You normally don't need to call this
174
196
  manually. It will automatically authenticate when needed.
175
197
  """
198
+ agents = _resolve_agents(agent, claude)
176
199
  auth = get_auth_state()
177
200
  auth.no_browser = no_browser
178
201
  auth._ensure_readable_secrets()
@@ -187,14 +210,14 @@ def login(
187
210
  # --no-org keeps whatever org the device flow landed in, so the role
188
211
  # check has to look that org's membership up itself.
189
212
  _require_cli_role(_active_org_membership(auth))
190
- if claude:
191
- # Claude setup needs only the packaged skill assets and the
213
+ if agents:
214
+ # Agent setup needs only the packaged skill assets and the
192
215
  # ellf-core token minted by the device flow above — not the
193
216
  # cluster. Run it before cluster selection so cluster failures
194
217
  # (token mint errors, unreachable broker, no cluster registered)
195
218
  # can't block skill installation.
196
- _install_claude_skills()
197
- _configure_claude_mcp(auth)
219
+ _install_agent_skills(agents)
220
+ _configure_agent_mcp(auth, agents)
198
221
  # Best-effort: needs only the api token minted above, and must not
199
222
  # block login (or cluster selection below) when it fails.
200
223
  _configure_venv_pypi(auth, as_json=as_json)