attacklm 0.7.0__tar.gz → 0.8.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 (214) hide show
  1. {attacklm-0.7.0 → attacklm-0.8.0}/CHANGELOG.md +51 -0
  2. {attacklm-0.7.0 → attacklm-0.8.0}/PKG-INFO +76 -22
  3. {attacklm-0.7.0 → attacklm-0.8.0}/README.md +75 -21
  4. attacklm-0.8.0/attacklm-gui/README.md +145 -0
  5. attacklm-0.8.0/attacklm-gui/pyproject.toml +19 -0
  6. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/__init__.py +3 -0
  7. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/app.py +58 -0
  8. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/cli.py +17 -0
  9. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/presets.py +170 -0
  10. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/runner.py +223 -0
  11. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/screens/__init__.py +1 -0
  12. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/screens/command_forms.py +353 -0
  13. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/screens/main_menu.py +91 -0
  14. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/screens/train_form.py +451 -0
  15. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/screens/train_live.py +328 -0
  16. attacklm-0.8.0/attacklm-gui/src/attacklm_gui/widgets/__init__.py +1 -0
  17. attacklm-0.8.0/attacklm-gui/tests/test_gui.py +208 -0
  18. {attacklm-0.7.0 → attacklm-0.8.0}/hf/README.md +4 -0
  19. {attacklm-0.7.0 → attacklm-0.8.0}/pyproject.toml +11 -2
  20. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/device_utils.py +34 -1
  21. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/train_template.py +186 -7
  22. attacklm-0.8.0/src/attacklm/__version__.py +1 -0
  23. {attacklm-0.7.0 → attacklm-0.8.0}/src/attacklm/_project_root.py +1 -1
  24. attacklm-0.8.0/src/attacklm/cli.py +636 -0
  25. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_init_pipeline.py +2 -2
  26. attacklm-0.7.0/src/attacklm/__version__.py +0 -1
  27. attacklm-0.7.0/src/attacklm/cli.py +0 -236
  28. {attacklm-0.7.0 → attacklm-0.8.0}/.github/workflows/release.yml +0 -0
  29. {attacklm-0.7.0 → attacklm-0.8.0}/.gitignore +0 -0
  30. {attacklm-0.7.0 → attacklm-0.8.0}/ATTRIBUTION.md +0 -0
  31. {attacklm-0.7.0 → attacklm-0.8.0}/CONTRIBUTING.md +0 -0
  32. {attacklm-0.7.0 → attacklm-0.8.0}/EVALUATION.md +0 -0
  33. {attacklm-0.7.0 → attacklm-0.8.0}/LICENSE +0 -0
  34. {attacklm-0.7.0 → attacklm-0.8.0}/MANIFEST.in +0 -0
  35. {attacklm-0.7.0 → attacklm-0.8.0}/Makefile +0 -0
  36. {attacklm-0.7.0 → attacklm-0.8.0}/NOTICE +0 -0
  37. {attacklm-0.7.0 → attacklm-0.8.0}/QA_BEFORE_RELEASES.md +0 -0
  38. {attacklm-0.7.0 → attacklm-0.8.0}/REPLAY_PLAN.md +0 -0
  39. {attacklm-0.7.0 → attacklm-0.8.0}/data/ATTRIBUTION.md +0 -0
  40. {attacklm-0.7.0 → attacklm-0.8.0}/data/LEGAL.md +0 -0
  41. {attacklm-0.7.0 → attacklm-0.8.0}/data/REMOVAL.md +0 -0
  42. {attacklm-0.7.0 → attacklm-0.8.0}/data/bench/questions.jsonl +0 -0
  43. {attacklm-0.7.0 → attacklm-0.8.0}/data/bench/speed_context.txt +0 -0
  44. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/ATTRIBUTION.md +0 -0
  45. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/GEMINI_RESEARCH_2026-06-11.md +0 -0
  46. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/acquisition_report.json +0 -0
  47. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/manifest.json +0 -0
  48. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/README.md +0 -0
  49. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/_index.json +0 -0
  50. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/atomic-red-team/LICENSE.md +0 -0
  51. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/atomic-red-team/SOURCE.md +0 -0
  52. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/atomic-red-team/base/collection/data.jsonl +0 -0
  53. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/atomic-red-team/base/discovery/data.jsonl +0 -0
  54. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/atomic-red-team/base/execution/data.jsonl +0 -0
  55. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/atomic-red-team/base/exfiltration/data.jsonl +0 -0
  56. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/atomic-red-team/base/persistence/data.jsonl +0 -0
  57. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/attacklm-synthetic/LICENSE.md +0 -0
  58. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/attacklm-synthetic/SOURCE.md +0 -0
  59. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/attacklm-synthetic/orchestrator/data.jsonl +0 -0
  60. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/azure-pyrit/LICENSE.md +0 -0
  61. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/azure-pyrit/SOURCE.md +0 -0
  62. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/cyberark-fuzzyai/LICENSE.md +0 -0
  63. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/cyberark-fuzzyai/SOURCE.md +0 -0
  64. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/elastic-rules/LICENSE.md +0 -0
  65. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/elastic-rules/SOURCE.md +0 -0
  66. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/elastic-rules/defensive/detection_engineering/data.jsonl +0 -0
  67. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/llm-generated/LICENSE.md +0 -0
  68. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/llm-generated/SOURCE.md +0 -0
  69. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/llm-generated/cloud/attacks/data_llm.jsonl +0 -0
  70. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/llm-generated/ics/attacks/data_llm.jsonl +0 -0
  71. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/llm-generated/social_engineering/phishing/data_llm.jsonl +0 -0
  72. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/llm-generated/wireless/attacks/data_llm.jsonl +0 -0
  73. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/LICENSE.md +0 -0
  74. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/SOURCE.md +0 -0
  75. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/base/collection/data.jsonl +0 -0
  76. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/base/credential_access/data.jsonl +0 -0
  77. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/base/defense_evasion/data.jsonl +0 -0
  78. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/base/discovery/data.jsonl +0 -0
  79. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/base/execution/data.jsonl +0 -0
  80. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/base/lateral_movement/data.jsonl +0 -0
  81. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/base/persistence/data.jsonl +0 -0
  82. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/base/privilege_escalation/data.jsonl +0 -0
  83. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/metasploit-framework/tools/metasploit/data.jsonl +0 -0
  84. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-atlas-arsenal/LICENSE.md +0 -0
  85. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-atlas-arsenal/SOURCE.md +0 -0
  86. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-atlas-arsenal/base/discovery/data.jsonl +0 -0
  87. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-stockpile/LICENSE.md +0 -0
  88. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-stockpile/SOURCE.md +0 -0
  89. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-stockpile/base/collection/data.jsonl +0 -0
  90. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-stockpile/base/discovery/data.jsonl +0 -0
  91. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-stockpile/base/execution/data.jsonl +0 -0
  92. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-stockpile/base/exfiltration/data.jsonl +0 -0
  93. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mitre-stockpile/base/persistence/data.jsonl +0 -0
  94. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mordor/LICENSE.md +0 -0
  95. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mordor/SOURCE.md +0 -0
  96. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/mordor/defensive/threat_hunting/data.jsonl +0 -0
  97. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/nist-ir/LICENSE.md +0 -0
  98. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/nist-ir/SOURCE.md +0 -0
  99. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/nist-ir/defensive/incident_response/data.jsonl +0 -0
  100. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/nvidia-garak/LICENSE.md +0 -0
  101. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/nvidia-garak/SOURCE.md +0 -0
  102. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/nvidia-garak/ai/jailbreaking/data.jsonl +0 -0
  103. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/promptfoo/LICENSE.md +0 -0
  104. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/promptfoo/SOURCE.md +0 -0
  105. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/promptfoo/ai/prompt-injection/data.jsonl +0 -0
  106. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/promptmap/LICENSE.md +0 -0
  107. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/promptmap/SOURCE.md +0 -0
  108. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/promptmap/ai/prompt-injection/data.jsonl +0 -0
  109. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/replay-general/LICENSE.md +0 -0
  110. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/replay-general/SOURCE.md +0 -0
  111. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/replay-general/base/replay/data_code.jsonl +0 -0
  112. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/replay-general/base/replay/data_conversation.jsonl +0 -0
  113. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/replay-general/base/replay/data_factual.jsonl +0 -0
  114. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/replay-general/base/replay/data_reasoning.jsonl +0 -0
  115. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/sigma-hq/LICENSE.md +0 -0
  116. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/sigma-hq/SOURCE.md +0 -0
  117. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/sigma-hq/defensive/detection_engineering/data.jsonl +0 -0
  118. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/splunk-content/LICENSE.md +0 -0
  119. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/splunk-content/SOURCE.md +0 -0
  120. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/splunk-content/defensive/detection_engineering/data.jsonl +0 -0
  121. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/threathunter-playbook/LICENSE.md +0 -0
  122. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/threathunter-playbook/SOURCE.md +0 -0
  123. {attacklm-0.7.0 → attacklm-0.8.0}/data/datasets/buckets/sources/threathunter-playbook/defensive/threat_hunting/data.jsonl +0 -0
  124. {attacklm-0.7.0 → attacklm-0.8.0}/data/golden/prompts.jsonl +0 -0
  125. {attacklm-0.7.0 → attacklm-0.8.0}/data/reference/prompts.jsonl +0 -0
  126. {attacklm-0.7.0 → attacklm-0.8.0}/data/steering/prompts/opsec_aware.txt +0 -0
  127. {attacklm-0.7.0 → attacklm-0.8.0}/data/steering/prompts/opsec_unaware.txt +0 -0
  128. {attacklm-0.7.0 → attacklm-0.8.0}/data/steering/prompts/succinct.txt +0 -0
  129. {attacklm-0.7.0 → attacklm-0.8.0}/data/steering/prompts/verbose.txt +0 -0
  130. {attacklm-0.7.0 → attacklm-0.8.0}/experiments/README.md +0 -0
  131. {attacklm-0.7.0 → attacklm-0.8.0}/experiments/synthetic_dataset_mutator_evol_instruct.py +0 -0
  132. {attacklm-0.7.0 → attacklm-0.8.0}/hf/.gitattributes +0 -0
  133. {attacklm-0.7.0 → attacklm-0.8.0}/hf/data/manifest.json +0 -0
  134. {attacklm-0.7.0 → attacklm-0.8.0}/hf/dataset_infos.json +0 -0
  135. {attacklm-0.7.0 → attacklm-0.8.0}/hf/scripts/build_hf_dataset.py +0 -0
  136. {attacklm-0.7.0 → attacklm-0.8.0}/hf/scripts/push_to_hf.py +0 -0
  137. {attacklm-0.7.0 → attacklm-0.8.0}/hpo_runs/.gitkeep +0 -0
  138. {attacklm-0.7.0 → attacklm-0.8.0}/hpo_runs/hpo_state.json +0 -0
  139. {attacklm-0.7.0 → attacklm-0.8.0}/hpo_runs/hpo_trial_dataset.jsonl +0 -0
  140. {attacklm-0.7.0 → attacklm-0.8.0}/logs/.gitkeep +0 -0
  141. {attacklm-0.7.0 → attacklm-0.8.0}/notes/BLUE_TEAM_DESIGN_v0.5.0.md +0 -0
  142. {attacklm-0.7.0 → attacklm-0.8.0}/notes/EVAL_DESIGN_v0.4.0.md +0 -0
  143. {attacklm-0.7.0 → attacklm-0.8.0}/notes/STEERING_REVIEW_v0.4.0.md +0 -0
  144. {attacklm-0.7.0 → attacklm-0.8.0}/pipeline.example.yaml +0 -0
  145. {attacklm-0.7.0 → attacklm-0.8.0}/presets/blue-team.json +0 -0
  146. {attacklm-0.7.0 → attacklm-0.8.0}/presets/purple-team.json +0 -0
  147. {attacklm-0.7.0 → attacklm-0.8.0}/presets/red-team.json +0 -0
  148. {attacklm-0.7.0 → attacklm-0.8.0}/requirements.txt +0 -0
  149. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/_eval_loader.py +0 -0
  150. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/acquire_cloud_attack_dataset.py +0 -0
  151. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/acquire_ics_dataset.py +0 -0
  152. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/acquire_phishing_dataset.py +0 -0
  153. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/acquire_red_team_tactics.py +0 -0
  154. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/acquire_replay_general.py +0 -0
  155. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/acquire_supply_chain_dataset.py +0 -0
  156. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/acquire_web_attack_dataset.py +0 -0
  157. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/acquire_wireless_dataset.py +0 -0
  158. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/audit_dataset.py +0 -0
  159. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/balance_buckets.py +0 -0
  160. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/bucket_loader.py +0 -0
  161. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/build.py +0 -0
  162. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/clone_repos.sh +0 -0
  163. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/collect_reference.py +0 -0
  164. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/compare_scores.py +0 -0
  165. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/convert_to_gguf.py +0 -0
  166. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/demo.py +0 -0
  167. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/domain_bench.py +0 -0
  168. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/eval_retention.py +0 -0
  169. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_ai_tools_to_jsonl.py +0 -0
  170. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_atomic_red_team_to_jsonl.py +0 -0
  171. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_by_tactic.py +0 -0
  172. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_caldera_plugins_to_jsonl.py +0 -0
  173. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_elastic_rules.py +0 -0
  174. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_infection_monkey_to_jsonl.py +0 -0
  175. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_mordor.py +0 -0
  176. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_nist_ir.py +0 -0
  177. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_rta_to_jsonl.py +0 -0
  178. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_sigma_defensive.py +0 -0
  179. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_splunk_content.py +0 -0
  180. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/extract_threathunter_playbook.py +0 -0
  181. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/generate_synthetic_scarce.py +0 -0
  182. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/golden_vectors.py +0 -0
  183. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/hpo_runner.py +0 -0
  184. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/import_gguf.sh +0 -0
  185. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/import_to_lmstudio.sh +0 -0
  186. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/infer.py +0 -0
  187. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/init_pipeline.py +0 -0
  188. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/merge_adapter.py +0 -0
  189. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/mitre_tactic_lookup.py +0 -0
  190. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/parse_metasploit_to_jsonl.py +0 -0
  191. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/pipeline.py +0 -0
  192. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/rebuild_manifest.py +0 -0
  193. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/register_ollama.py +0 -0
  194. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/reorganize_buckets.py +0 -0
  195. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/replay_mixer.py +0 -0
  196. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/score_candidates.py +0 -0
  197. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/setup_buckets.py +0 -0
  198. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/speed_bench.py +0 -0
  199. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/steering.py +0 -0
  200. {attacklm-0.7.0 → attacklm-0.8.0}/scripts/train_all.py +0 -0
  201. {attacklm-0.7.0 → attacklm-0.8.0}/src/attacklm/__init__.py +0 -0
  202. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_balance_buckets.py +0 -0
  203. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_collect_reference.py +0 -0
  204. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_compare_scores.py +0 -0
  205. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_domain_bench.py +0 -0
  206. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_eval_loader.py +0 -0
  207. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_eval_retention.py +0 -0
  208. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_golden_vectors.py +0 -0
  209. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_replay_mixer.py +0 -0
  210. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_score_candidates.py +0 -0
  211. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_speed_bench.py +0 -0
  212. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_steering.py +0 -0
  213. {attacklm-0.7.0 → attacklm-0.8.0}/tests/test_thinking_models.py +0 -0
  214. {attacklm-0.7.0 → attacklm-0.8.0}/uv.lock +0 -0
@@ -4,6 +4,57 @@ All notable changes to AttackLM are documented in this file. Versions follow [Se
4
4
 
5
5
  ---
6
6
 
7
+ ## [0.8.0] — 2026-06-30 — Unified CLI with subcommands
8
+
9
+ ### Added
10
+ - **Unified CLI**: New `attacklm` command with argparse subcommands replaces 21 hyphenated commands
11
+ - `attacklm train [--dataset all] [--hpo]` — consolidates `attacklm-train`, `attacklm-train-all`, `attacklm-train-lora`, `attacklm-hpo`
12
+ - `attacklm init [--extract-only|--buckets-only|--attribute-only|--clone-only]` — consolidates `attacklm-init`, `attacklm-extract`, `attacklm-buckets`, `attacklm-attribute`, `attacklm-clone`
13
+ - `attacklm build [--merge-only|--gguf-only|--register-ollama]` — consolidates `attacklm-build`, `attacklm-merge`, `attacklm-gguf`, `attacklm-register-ollama`
14
+ - `attacklm eval [--collect-ref|--score|--compare|--golden]` — consolidates `attacklm-eval`, `attacklm-collect-ref`, `attacklm-score`, `attacklm-compare`, `attacklm-golden`
15
+ - `attacklm balance` — replaces `attacklm-balance`
16
+ - `attacklm infer` — replaces `attacklm-infer`
17
+ - `attacklm gui` — replaces `attacklm-gui`
18
+ - `attacklm demo` — replaces `attacklm-demo`
19
+ - **`attacklm --version`**: Shows version number
20
+ - **Evaluation screen in GUI**: New `EvalFormScreen` with buttons for all eval subcommands (Retention, Collect Ref, Score, Compare, Golden)
21
+ - **Build screen in GUI**: Consolidated buttons for Full Build, Merge Only, GGUF Only
22
+
23
+ ### Changed
24
+ - **GUI main menu**: Consolidated from 8 buttons to 6 (Train, Init, Balance, Build, Infer, Eval) — removed separate Extract/Merge/Pipeline buttons
25
+ - **GUI train form**: Now calls `attacklm train` instead of `attacklm-train`
26
+ - **GUI command forms**: All commands now use `attacklm <subcommand>` format instead of `attacklm-<command>`
27
+ - **Deprecation warnings**: All old hyphenated commands print a deprecation notice before delegating to the new subcommand
28
+
29
+ ### Deprecated
30
+ - All 21 hyphenated commands (`attacklm-train`, `attacklm-train-all`, etc.) still work but print deprecation warnings. They will be removed in v0.9.0.
31
+
32
+ ---
33
+
34
+ ## [0.7.1] — 2026-06-30 — GUI, VRAM fixes, dataset caching
35
+
36
+ ### Added
37
+ - **attacklm-gui**: Terminal-based TUI wrapper (Textual) for all CLI commands
38
+ - Form-based training config with 40+ params in 5 tabs (Basic, LoRA, GaLore, Advanced, Hardware)
39
+ - Live training monitor with loss sparkline, VRAM gauge, progress bar, log viewer
40
+ - One-click screens for extract, balance, infer, merge, build, pipeline, init
41
+ - 5 built-in presets (3B Q-GaLore, 3B LoRA, 7B Q-GaLore, 7B QLoRA, etc.)
42
+ - Pause/resume/quit controls during training
43
+ - Works in terminal-only environments (no X11/WSLg required)
44
+ - **Dataset caching**: Tokenized datasets saved to disk after first run, reloaded in ~1s on subsequent runs (keyed by dataset + model + max_length + packing)
45
+ - **config.json fix**: Training runs now preserve HF model architecture fields (model_type, architectures, hidden_size, etc.) for GGUF conversion compatibility
46
+
47
+ ### Fixed
48
+ - **VRAM fragmentation**: Removed `device_map="auto"` for single-GPU training — was splitting model across GPU+CPU, creating meta tensors, and leaving VRAM fragmented. Model now loads directly to GPU.
49
+ - **Spectrum crash on 7B**: Skip meta-device tensors in SNR computation (caused by CPU-offloaded layers from device_map="auto")
50
+ - **VRAM parsing**: Added regex for compact VRAM format (`VRAM X/Y GB (A alloc + C cache)`) in training output parser
51
+
52
+ ### Changed
53
+ - Moved attacklm-gui into the main AttackLM repo under `attacklm-gui/`
54
+ - 17 GUI tests passing
55
+
56
+ ---
57
+
7
58
  ## [0.7.0] — 2026-06-29 — Defensive data extraction, test fixes, script cleanup
8
59
 
9
60
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: attacklm
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: QLoRA-fine-tuned Qwen2.5-Coder for offensive/defensive security and AI red-teaming
5
5
  Project-URL: Homepage, https://github.com/Veedubin/AttackLM
6
6
  Project-URL: Repository, https://github.com/Veedubin/AttackLM
@@ -205,6 +205,27 @@ AttackLM — QLoRA fine-tuning pipeline for a MITRE ATT&CK-grounded security AI
205
205
 
206
206
  ---
207
207
 
208
+ ## GUI (New in v0.7.1)
209
+
210
+ AttackLM now includes a terminal-based GUI for all commands. No more memorizing 40+ CLI flags.
211
+
212
+ ```bash
213
+ pip install attacklm-gui
214
+ attacklm-gui
215
+ ```
216
+
217
+ Features:
218
+ - **Training form** with 40+ params in 5 tabs (Basic, LoRA, GaLore, Advanced, Hardware)
219
+ - **Live training monitor** with loss sparkline, VRAM gauge, progress bar, and log viewer
220
+ - **One-click screens** for extract, balance, infer, merge, build, pipeline, and init
221
+ - **5 built-in presets** (3B Q-GaLore, 3B LoRA, 7B Q-GaLore, 7B QLoRA, etc.)
222
+ - **Pause/resume/quit** controls during training
223
+ - Works in **terminal-only** environments — no X11, no browser, no GPU required. Works over SSH and WSL.
224
+
225
+ The CLI still works exactly as before. The GUI is a thin wrapper that constructs and runs CLI commands.
226
+
227
+ ---
228
+
208
229
  ## Install
209
230
  The recommended way to install the full CUDA training stack:
210
231
 
@@ -346,29 +367,62 @@ This layout allows the pipeline to deterministically extract data from upstream
346
367
  ---
347
368
 
348
369
  ## CLI Reference
370
+
371
+ > **v0.8.0**: The 21 hyphenated commands are consolidated into a single
372
+ > `attacklm` command with subcommands. The old commands still work but
373
+ > print a deprecation warning. They will be removed in v0.9.0.
374
+
375
+ ### Unified Command (v0.8.0+)
376
+
349
377
  | Command | Description |
350
378
  |---------|-------------|
351
- | `attacklm-init` | One-shot init: clone $\rightarrow$ extract $\rightarrow$ attribute $\rightarrow$ buckets |
352
- | `attacklm-train` | Train a single QLoRA adapter |
353
- | `attacklm-train-all` | Orchestrated training for all buckets / HPO |
354
- | `attacklm-balance` | Build a balanced subset of buckets |
355
- | `attacklm-hpo` | Coordinate-descent HPO sweep |
356
- | `attacklm-infer` | Smoke-test inference |
357
- | `attacklm-merge` | Merge LoRA adapter into base model |
358
- | `attacklm-gguf` | Convert merged model to GGUF (llama.cpp) |
359
- | `attacklm-build` | One-shot merge $\rightarrow$ GGUF $\rightarrow$ install |
360
- | `attacklm-demo` | Multi-agent orchestrator demo |
361
- | `attacklm-extract` | Extract data from cloned repositories |
362
- | `attacklm-buckets` | Organize data into bucket structure |
363
- | `attacklm-attribute` | Add source and license to JSONL records |
364
- | `attacklm-clone` | Clone upstream data repositories |
365
- | `attacklm-train-lora` | Direct LoRA training on single dataset |
366
- | `attacklm-eval` | Run retention evaluation suite |
367
- | `attacklm-collect-ref` | Collect reference model outputs |
368
- | `attacklm-score` | Score candidate models against reference |
369
- | `attacklm-compare` | Compare multiple candidate model scores |
370
- | `attacklm-golden` | Execute golden vector regression gates |
371
- | `attacklm-register-ollama`| Register GGUF model with Ollama |
379
+ | `attacklm train` | Train a model (QLoRA, GaLore, Q-GaLore, Spectrum, PiSSA) |
380
+ | `attacklm train --dataset all` | Train all buckets (replaces `attacklm-train-all`) |
381
+ | `attacklm train --hpo` | Run HPO sweep (replaces `attacklm-hpo`) |
382
+ | `attacklm init` | One-shot init: clone extract → attribute → buckets |
383
+ | `attacklm init --extract-only` | Extract data only (replaces `attacklm-extract`) |
384
+ | `attacklm init --buckets-only` | Organize into buckets only (replaces `attacklm-buckets`) |
385
+ | `attacklm init --attribute-only` | Add attribution only (replaces `attacklm-attribute`) |
386
+ | `attacklm init --clone-only` | Clone repos only (replaces `attacklm-clone`) |
387
+ | `attacklm balance` | Build a balanced subset of buckets |
388
+ | `attacklm build` | One-shot merge GGUF → install to LM Studio |
389
+ | `attacklm build --merge-only` | Merge adapter only (replaces `attacklm-merge`) |
390
+ | `attacklm build --gguf-only` | Convert to GGUF only (replaces `attacklm-gguf`) |
391
+ | `attacklm build --register-ollama` | Register GGUF with Ollama (replaces `attacklm-register-ollama`) |
392
+ | `attacklm infer` | Smoke-test inference |
393
+ | `attacklm eval` | Run retention evaluation suite |
394
+ | `attacklm eval --collect-ref` | Collect reference model outputs |
395
+ | `attacklm eval --score` | Score candidate models against reference |
396
+ | `attacklm eval --compare` | Compare multiple candidate model scores |
397
+ | `attacklm eval --golden` | Execute golden vector regression gates |
398
+ | `attacklm gui` | Terminal GUI for all commands |
399
+ | `attacklm demo` | Multi-agent orchestrator demo |
400
+
401
+ ### Legacy Commands (Deprecated, removed in v0.9.0)
402
+
403
+ | Old Command | New Command |
404
+ |-------------|-------------|
405
+ | `attacklm-train` | `attacklm train` |
406
+ | `attacklm-train-all` | `attacklm train --dataset all` |
407
+ | `attacklm-train-lora` | `attacklm train` |
408
+ | `attacklm-hpo` | `attacklm train --hpo` |
409
+ | `attacklm-init` | `attacklm init` |
410
+ | `attacklm-extract` | `attacklm init --extract-only` |
411
+ | `attacklm-buckets` | `attacklm init --buckets-only` |
412
+ | `attacklm-attribute` | `attacklm init --attribute-only` |
413
+ | `attacklm-clone` | `attacklm init --clone-only` |
414
+ | `attacklm-balance` | `attacklm balance` |
415
+ | `attacklm-build` | `attacklm build` |
416
+ | `attacklm-merge` | `attacklm build --merge-only` |
417
+ | `attacklm-gguf` | `attacklm build --gguf-only` |
418
+ | `attacklm-register-ollama` | `attacklm build --register-ollama` |
419
+ | `attacklm-infer` | `attacklm infer` |
420
+ | `attacklm-eval` | `attacklm eval` |
421
+ | `attacklm-collect-ref` | `attacklm eval --collect-ref` |
422
+ | `attacklm-score` | `attacklm eval --score` |
423
+ | `attacklm-compare` | `attacklm eval --compare` |
424
+ | `attacklm-golden` | `attacklm eval --golden` |
425
+ | `attacklm-demo` | `attacklm demo` |
372
426
 
373
427
  ---
374
428
 
@@ -7,6 +7,27 @@ AttackLM — QLoRA fine-tuning pipeline for a MITRE ATT&CK-grounded security AI
7
7
 
8
8
  ---
9
9
 
10
+ ## GUI (New in v0.7.1)
11
+
12
+ AttackLM now includes a terminal-based GUI for all commands. No more memorizing 40+ CLI flags.
13
+
14
+ ```bash
15
+ pip install attacklm-gui
16
+ attacklm-gui
17
+ ```
18
+
19
+ Features:
20
+ - **Training form** with 40+ params in 5 tabs (Basic, LoRA, GaLore, Advanced, Hardware)
21
+ - **Live training monitor** with loss sparkline, VRAM gauge, progress bar, and log viewer
22
+ - **One-click screens** for extract, balance, infer, merge, build, pipeline, and init
23
+ - **5 built-in presets** (3B Q-GaLore, 3B LoRA, 7B Q-GaLore, 7B QLoRA, etc.)
24
+ - **Pause/resume/quit** controls during training
25
+ - Works in **terminal-only** environments — no X11, no browser, no GPU required. Works over SSH and WSL.
26
+
27
+ The CLI still works exactly as before. The GUI is a thin wrapper that constructs and runs CLI commands.
28
+
29
+ ---
30
+
10
31
  ## Install
11
32
  The recommended way to install the full CUDA training stack:
12
33
 
@@ -148,29 +169,62 @@ This layout allows the pipeline to deterministically extract data from upstream
148
169
  ---
149
170
 
150
171
  ## CLI Reference
172
+
173
+ > **v0.8.0**: The 21 hyphenated commands are consolidated into a single
174
+ > `attacklm` command with subcommands. The old commands still work but
175
+ > print a deprecation warning. They will be removed in v0.9.0.
176
+
177
+ ### Unified Command (v0.8.0+)
178
+
151
179
  | Command | Description |
152
180
  |---------|-------------|
153
- | `attacklm-init` | One-shot init: clone $\rightarrow$ extract $\rightarrow$ attribute $\rightarrow$ buckets |
154
- | `attacklm-train` | Train a single QLoRA adapter |
155
- | `attacklm-train-all` | Orchestrated training for all buckets / HPO |
156
- | `attacklm-balance` | Build a balanced subset of buckets |
157
- | `attacklm-hpo` | Coordinate-descent HPO sweep |
158
- | `attacklm-infer` | Smoke-test inference |
159
- | `attacklm-merge` | Merge LoRA adapter into base model |
160
- | `attacklm-gguf` | Convert merged model to GGUF (llama.cpp) |
161
- | `attacklm-build` | One-shot merge $\rightarrow$ GGUF $\rightarrow$ install |
162
- | `attacklm-demo` | Multi-agent orchestrator demo |
163
- | `attacklm-extract` | Extract data from cloned repositories |
164
- | `attacklm-buckets` | Organize data into bucket structure |
165
- | `attacklm-attribute` | Add source and license to JSONL records |
166
- | `attacklm-clone` | Clone upstream data repositories |
167
- | `attacklm-train-lora` | Direct LoRA training on single dataset |
168
- | `attacklm-eval` | Run retention evaluation suite |
169
- | `attacklm-collect-ref` | Collect reference model outputs |
170
- | `attacklm-score` | Score candidate models against reference |
171
- | `attacklm-compare` | Compare multiple candidate model scores |
172
- | `attacklm-golden` | Execute golden vector regression gates |
173
- | `attacklm-register-ollama`| Register GGUF model with Ollama |
181
+ | `attacklm train` | Train a model (QLoRA, GaLore, Q-GaLore, Spectrum, PiSSA) |
182
+ | `attacklm train --dataset all` | Train all buckets (replaces `attacklm-train-all`) |
183
+ | `attacklm train --hpo` | Run HPO sweep (replaces `attacklm-hpo`) |
184
+ | `attacklm init` | One-shot init: clone extract → attribute → buckets |
185
+ | `attacklm init --extract-only` | Extract data only (replaces `attacklm-extract`) |
186
+ | `attacklm init --buckets-only` | Organize into buckets only (replaces `attacklm-buckets`) |
187
+ | `attacklm init --attribute-only` | Add attribution only (replaces `attacklm-attribute`) |
188
+ | `attacklm init --clone-only` | Clone repos only (replaces `attacklm-clone`) |
189
+ | `attacklm balance` | Build a balanced subset of buckets |
190
+ | `attacklm build` | One-shot merge GGUF → install to LM Studio |
191
+ | `attacklm build --merge-only` | Merge adapter only (replaces `attacklm-merge`) |
192
+ | `attacklm build --gguf-only` | Convert to GGUF only (replaces `attacklm-gguf`) |
193
+ | `attacklm build --register-ollama` | Register GGUF with Ollama (replaces `attacklm-register-ollama`) |
194
+ | `attacklm infer` | Smoke-test inference |
195
+ | `attacklm eval` | Run retention evaluation suite |
196
+ | `attacklm eval --collect-ref` | Collect reference model outputs |
197
+ | `attacklm eval --score` | Score candidate models against reference |
198
+ | `attacklm eval --compare` | Compare multiple candidate model scores |
199
+ | `attacklm eval --golden` | Execute golden vector regression gates |
200
+ | `attacklm gui` | Terminal GUI for all commands |
201
+ | `attacklm demo` | Multi-agent orchestrator demo |
202
+
203
+ ### Legacy Commands (Deprecated, removed in v0.9.0)
204
+
205
+ | Old Command | New Command |
206
+ |-------------|-------------|
207
+ | `attacklm-train` | `attacklm train` |
208
+ | `attacklm-train-all` | `attacklm train --dataset all` |
209
+ | `attacklm-train-lora` | `attacklm train` |
210
+ | `attacklm-hpo` | `attacklm train --hpo` |
211
+ | `attacklm-init` | `attacklm init` |
212
+ | `attacklm-extract` | `attacklm init --extract-only` |
213
+ | `attacklm-buckets` | `attacklm init --buckets-only` |
214
+ | `attacklm-attribute` | `attacklm init --attribute-only` |
215
+ | `attacklm-clone` | `attacklm init --clone-only` |
216
+ | `attacklm-balance` | `attacklm balance` |
217
+ | `attacklm-build` | `attacklm build` |
218
+ | `attacklm-merge` | `attacklm build --merge-only` |
219
+ | `attacklm-gguf` | `attacklm build --gguf-only` |
220
+ | `attacklm-register-ollama` | `attacklm build --register-ollama` |
221
+ | `attacklm-infer` | `attacklm infer` |
222
+ | `attacklm-eval` | `attacklm eval` |
223
+ | `attacklm-collect-ref` | `attacklm eval --collect-ref` |
224
+ | `attacklm-score` | `attacklm eval --score` |
225
+ | `attacklm-compare` | `attacklm eval --compare` |
226
+ | `attacklm-golden` | `attacklm eval --golden` |
227
+ | `attacklm-demo` | `attacklm demo` |
174
228
 
175
229
  ---
176
230
 
@@ -0,0 +1,145 @@
1
+ # AttackLM GUI
2
+
3
+ Terminal-based GUI wrapper for the [AttackLM](https://github.com/Veedubin/AttackLM) CLI training tools. Built with [Textual](https://textual.textualize.io/).
4
+
5
+ ## Why?
6
+
7
+ AttackLM has a unified CLI (`attacklm train`, `attacklm init`, etc.) with 8 subcommands. `attacklm train` alone has 40+ parameters. Remembering all the flags is painful. The GUI provides:
8
+
9
+ - **Form-based parameter input** with tabs, presets, and validation
10
+ - **Live training monitoring** with loss charts, VRAM gauges, and log streaming
11
+ - **One-click commands** for extract, balance, infer, merge, build, and more
12
+ - **Works everywhere** — terminal-only, no X11 required (WSL, SSH, headless)
13
+
14
+ The unified CLI (`attacklm <subcommand>`) still works as before. The GUI is a thin wrapper that constructs and runs CLI commands.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install attacklm-gui
20
+ ```
21
+
22
+ Or from source:
23
+
24
+ ```bash
25
+ git clone https://github.com/Veedubin/AttackLM.git
26
+ cd AttackLM-Models/attacklm-gui
27
+ pip install -e .
28
+ ```
29
+
30
+ Requires `attacklm` (the CLI package) and `textual>=2.0`.
31
+
32
+ ## Usage
33
+
34
+ ```bash
35
+ attacklm-gui
36
+ ```
37
+
38
+ ### Main Menu
39
+
40
+ ```
41
+ ┌──────────────────────────────────────┐
42
+ │ AttackLM GUI v0.1.0 │
43
+ │ │
44
+ │ 🏋️ Train Model │
45
+ │ 🚀 Init Dataset │
46
+ │ ⚖️ Balance Dataset │
47
+ │ 📦 Build & Install │
48
+ │ 🧠 Run Inference │
49
+ │ 📊 Evaluate │
50
+ └──────────────────────────────────────┘
51
+ ```
52
+
53
+ ### Training Form
54
+
55
+ The training form organizes 40+ parameters into tabs:
56
+
57
+ | Tab | Parameters |
58
+ |-----|-----------|
59
+ | **Basic** | dataset, output, base model, epochs, batch size, max length |
60
+ | **LoRA** | rank, alpha, dropout, DoRA, RSLoRA, target modules, PiSSA |
61
+ | **GaLore** | Q-GaLore, rank, 32-bit, Spectrum layer freezing |
62
+ | **Advanced** | eval split, early stopping, save steps, gradient accum, optimizer, packing, live LR |
63
+ | **Hardware** | precision (BF16/FP16/FP32), multi-GPU, MoE safe, auto-tune |
64
+
65
+ **Presets** save and load complete configurations. Built-in presets:
66
+ - `3B Q-GaLore Spectrum` — full-parameter training on 16GB GPU
67
+ - `3B Q-GaLore Rank 128` — higher quality variant
68
+ - `3B LoRA Default` — standard QLoRA
69
+ - `7B Q-GaLore` — for 24GB GPUs
70
+ - `7B QLoRA Default` — standard QLoRA for 7B
71
+
72
+ ### Live Training Monitor
73
+
74
+ ```
75
+ ┌─────────────────────────────────────────────────────┐
76
+ │ Training: attacklm-3b-qgalore-spectrum │
77
+ │ Epoch 12/30 | Step 1896 | Elapsed: 1h 23m │
78
+ ├──────────────────────┬──────────────────────────────┤
79
+ │ Loss: 1.1143 ▂▃▅▆▇ │ VRAM: 5.9/15.6 GB (62%) │
80
+ │ Eval Loss: 1.176 │ alloc: 5.9 cache: 4.8 │
81
+ │ Trend: ↓ -0.0116 │ ████████░░░░ │
82
+ ├──────────────────────┴──────────────────────────────┤
83
+ │ Log Output (scrolling) │
84
+ │ Epoch 12/20 58% | loss 1.1143 | 2,844 tok/s ... │
85
+ ├─────────────────────────────────────────────────────┤
86
+ │ [P]ause [S]top at checkpoint [Q]uit │
87
+ └─────────────────────────────────────────────────────┘
88
+ ```
89
+
90
+ Controls:
91
+ - **Pause/Resume** — SIGSTOP/SIGCONT the training process
92
+ - **Stop at Checkpoint** — graceful stop after current eval
93
+ - **Quit** — kill training immediately
94
+
95
+ ### Other Commands
96
+
97
+ | Screen | What it does |
98
+ |--------|-------------|
99
+ | **Init** | Clone repos, extract data, organize buckets |
100
+ | **Balance** | Balance a dataset with cap size |
101
+ | **Inference** | Run a trained model with a prompt |
102
+ | **Build** | Merge → GGUF → install to LM Studio |
103
+ | **Eval** | Retention eval, collect-ref, score, compare, golden |
104
+ | **Pipeline** | Run a YAML training pipeline |
105
+
106
+ ## Keyboard Shortcuts
107
+
108
+ | Key | Action |
109
+ |-----|--------|
110
+ | `q` | Quit |
111
+ | `m` | Return to main menu |
112
+ | `Tab` | Next field |
113
+ | `Enter` | Activate button |
114
+ | `Esc` | Go back |
115
+
116
+ ## Architecture
117
+
118
+ ```
119
+ attacklm-gui/
120
+ ├── src/attacklm_gui/
121
+ │ ├── app.py # Textual App entry point
122
+ │ ├── cli.py # CLI entry point
123
+ │ ├── runner.py # Subprocess manager + output parser
124
+ │ ├── presets.py # Save/load training presets
125
+ │ ├── screens/
126
+ │ │ ├── main_menu.py # Command launcher (6 buttons)
127
+ │ │ ├── train_form.py # Training parameter form
128
+ │ │ ├── train_live.py # Live training monitor
129
+ │ │ └── command_forms.py # Init, Balance, Infer, Build, Eval, Pipeline screens
130
+ │ └── widgets/
131
+ │ └── __init__.py
132
+ └── tests/
133
+ └── test_gui.py
134
+ ```
135
+
136
+ The GUI never touches AttackLM's internal logic. It constructs CLI command strings and runs them via `asyncio.create_subprocess_exec`. All training, extraction, and inference logic stays in `scripts/*.py`.
137
+
138
+ ## Requirements
139
+
140
+ - Python 3.10+
141
+ - Linux (any flavor) or WSL
142
+ - Terminal with 256-color support
143
+ - AttackLM installed (`pip install attacklm[all]`)
144
+
145
+ No X11, no GPU, no browser required. Works over SSH.
@@ -0,0 +1,19 @@
1
+ [project]
2
+ name = "attacklm-gui"
3
+ version = "0.1.0"
4
+ description = "Terminal GUI wrapper for AttackLM CLI training tools"
5
+ requires-python = ">=3.10"
6
+ dependencies = [
7
+ "textual>=2.0",
8
+ "attacklm",
9
+ ]
10
+
11
+ [project.scripts]
12
+ attacklm-gui = "attacklm_gui.cli:main"
13
+
14
+ [build-system]
15
+ requires = ["setuptools>=75"]
16
+ build-backend = "setuptools.build_meta"
17
+
18
+ [tool.setuptools.packages.find]
19
+ where = ["src"]
@@ -0,0 +1,3 @@
1
+ """AttackLM GUI — Terminal-based wrapper for the AttackLM CLI."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,58 @@
1
+ """Main Textual application for AttackLM GUI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ from textual.app import App, ComposeResult
8
+ from textual.binding import Binding
9
+ from textual.widgets import Header, Footer
10
+
11
+ from attacklm_gui.presets import ensure_builtin_presets
12
+ from attacklm_gui.screens.main_menu import MainMenuScreen
13
+
14
+
15
+ class AttackLMApp(App):
16
+ """Terminal GUI wrapper for AttackLM CLI tools."""
17
+
18
+ TITLE = "AttackLM GUI"
19
+ SUB_TITLE = "v0.1.0"
20
+ CSS_PATH = None # We'll use inline CSS for now
21
+
22
+ BINDINGS = [
23
+ Binding("q", "quit", "Quit", show=True),
24
+ Binding("m", "main_menu", "Main Menu", show=True),
25
+ Binding("?", "help", "Help", show=False),
26
+ ]
27
+
28
+ def __init__(self) -> None:
29
+ super().__init__()
30
+ self.attacklm_dir = self._find_attacklm_dir()
31
+
32
+ def _find_attacklm_dir(self) -> Path:
33
+ """Find the AttackLM project directory."""
34
+ # Try common locations
35
+ candidates = [
36
+ Path.cwd(),
37
+ Path.home() / "Projects" / "reverse_engineering" / "AttackLM",
38
+ Path.home() / "AttackLM",
39
+ ]
40
+ for c in candidates:
41
+ if (c / "pyproject.toml").exists() and (
42
+ c / "scripts" / "train_template.py"
43
+ ).exists():
44
+ return c
45
+ return Path.cwd()
46
+
47
+ def compose(self) -> ComposeResult:
48
+ yield Header()
49
+ yield Footer()
50
+
51
+ def on_mount(self) -> None:
52
+ ensure_builtin_presets()
53
+ self.push_screen(MainMenuScreen())
54
+
55
+ def action_main_menu(self) -> None:
56
+ """Return to main menu."""
57
+ while len(self.screen_stack) > 1:
58
+ self.pop_screen()
@@ -0,0 +1,17 @@
1
+ """CLI entry point for attacklm-gui."""
2
+
3
+ import sys
4
+ from pathlib import Path
5
+
6
+
7
+ def main() -> int:
8
+ """Launch the AttackLM TUI."""
9
+ from attacklm_gui.app import AttackLMApp
10
+
11
+ app = AttackLMApp()
12
+ app.run()
13
+ return 0
14
+
15
+
16
+ if __name__ == "__main__":
17
+ sys.exit(main())