Commit Graph
98 Commits
Author SHA1 Message Date
Justin Bollinger 289da25609 docs: document non-interactive attack subcommands 2026-07-24 20:19:43 -04:00
Justin BollingerandClaude 6448f550ee feat(llm): pre-fill LLM target industry/location from local model research
Target-info mode (menu 12) asked for company, industry, and location as three
blank prompts. Once the company name is known the local Ollama model can often
supply the other two, so ask it and offer the answers as editable defaults.

- llm.research_target(): TargetResearchInput/TargetResearchOutput schemas plus a
  research SystemPromptGenerator that tells the model to return empty strings
  when it does not genuinely recognize the organization, so an unknown small
  client yields blank prompts instead of a confident hallucination.
  APITimeoutError is translated to LLMTimeoutError like generate_candidates.
- clean_research_field(): strips, collapses whitespace, caps at 80 chars, and
  turns anything non-string into "" so model output cannot be pasted unbounded
  into a prompt default.
- main.hcatOllamaResearchTarget(): runs the call inside the existing spinner and
  degrades to blank suggestions on timeout or any other failure, so research can
  never block the attack.
- attacks.ollama_attack(): shows suggestions as "Industry (freight rail): "
  defaults, labelled explicitly as the model's GUESSES rather than OSINT.
- New ollamaAutoResearch config toggle (default true) in both config examples.

Research uses only the configured local Ollama server; the client name is never
sent to a search engine or third-party company-data API.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 18:42:50 -04:00
Justin BollingerandClaude 39e0dd956a feat(llm): add cracked-password generation mode to the LLM attack
Adds a third LLM Attack generation mode ("cracked") that samples the
plaintexts already recovered this session from <hashfile>.out and asks the
model to infer the target organization's password conventions and emit new
candidates in the same style.

- llm.py: new _CRACKED_PROMPT (offensive candidate generation, explicitly
  not the denylist-oriented _WORDLIST_PROMPT), a _PROMPTS mode->prompt map,
  and a "cracked" branch in _build_request that tells the model not to
  repeat already-cracked passwords.
- main.py: extract the wordlist sampling logic into the shared module-level
  helper _sample_plaintext_file(path, cap, source_label) and call it from
  both the wordlist and cracked branches of hcatOllama; guard missing and
  empty .out files.
- attacks.py: offer mode 3 only when <hashfile>.out exists and is non-empty
  (matching _markov_pick_training_source), with a clear message otherwise.
- README: document the three modes and the widened ollamaMaxSampleLines
  scope.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 18:18:52 -04:00
Justin BollingerandClaude fef606dbf4 fix(llm): fix stride sampling exactness, zero-cap crash, and test quality
- Defect 1 (main.py): Replace floating-point stride loop with exact
  floor(k * total / cap) index formula so sampling always returns
  EXACTLY cap items for any 1 <= cap <= total_usable, including the
  stride < 2 regime where the old approach returned cap-1 items.

- Defect 2 (main.py): Validate ollamaMaxSampleLines before computing
  the stride; values <= 0 are nonsensical and fall back to 500
  (same as the default) rather than raising ZeroDivisionError.

- Defect 3 (test_progress_spinner.py): Rewrite test_non_tty_no_extra_thread
  to patch threading.Thread and assert it was never called, so the test
  actually fails when the spinner starts a thread in the non-TTY path.

- Defect 4 (test_progress_spinner.py): Simplify test_non_tty_prints_message
  to use monkeypatch.setattr instead of the dead mock.patch.object +
  manual assign/restore layering; removes two # type: ignore comments.

- docs(README.md): Document ollamaMaxSampleLines alongside ollamaNumCtx /
  ollamaTimeout in the Ollama Configuration section.

- tests: Add boundary-case tests for stride < 2 (total==cap, total==cap+1,
  total=3/cap=2, cap=1) and zero-cap fallback; make
  test_ollama_max_sample_lines_default exercise behaviour rather than
  the ambient config value.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 17:57:09 -04:00
Justin BollingerandClaude 549c5a0a64 fix(llm): bound Ollama requests with a configurable timeout
The Atomic Agents client was built with no timeout, so an Ollama server that
accepted the TCP connection but never replied (most commonly a large model still
loading into VRAM) left the CLI blocked in agent.run() forever. The caller's
`except Exception` handler only ever fired on connection-refused.

- llm.generate_candidates() takes a `timeout` parameter (default
  DEFAULT_TIMEOUT_SECONDS = 300.0) and forwards it to the OpenAI client.
- openai.APITimeoutError is translated into a new domain-level
  llm.LLMTimeoutError so main.py need not import openai itself, keeping the
  atomic-agents/instructor dependency isolated to llm.py as documented.
- hcatOllama passes the new `ollamaTimeout` config value and prints
  timeout-specific guidance (elapsed seconds, VRAM-loading hint, the setting to
  raise) instead of the misleading "ensure Ollama is running" message.
- Documented `ollamaTimeout` in config.json.example and README.

Also closes two test gaps: the defensive `except ValueError` handler in
hcatOllama now has coverage, and the misleadingly-named `test_unknown_mode_raises`
is split into explicit unit tests of _build_request's mode validation. Ticked the
completed steps in the LLM Atomic Agents plan doc.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 17:17:58 -04:00
Justin BollingerandClaude Opus 4.8 519d395708 docs(llm): document Atomic Agents refactor, new default model, wordlist mode (2.12.0)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 12:11:26 -04:00
Justin BollingerandClaude Opus 4.8 5510755c12 feat(wordlist): shard into all N parts in one run with numbered filenames
Shard Wordlist (option 7) now prompts for an output base path and a shard
count, then writes all N interleaved parts as base.001..base.00N in a single
pass instead of one file per modulus/offset invocation. Matches the intended
distributed-cracking workflow: split once, copy one part per node.

Updates tests and README usage docs; bumps CHANGELOG to 2.10.11.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 12:51:07 -04:00
Justin BollingerandClaude Opus 4.8 8ee36d0eab docs: move version history from README into CHANGELOG.md
Consolidate the release notes into a single dedicated CHANGELOG.md
(Keep a Changelog format) and replace the README's inline Version
History with a pointer, so the two no longer drift.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 18:16:32 -04:00
Justin BollingerandClaude Opus 4.8 144d1a5334 feat(hashview): download rule files from /v1/rules
Add HashviewAPI.list_rules and download_rules wrapping the Hashview
rule endpoints. The server gzip-compresses plaintext rules on the
fly, so download_rules decompresses before saving, yielding a file
usable directly with hashcat -r. Wired into the interactive Hashview
menu (Download Rule) and the CLI (hashview download-rules
--rules-id/--output). Unknown rule ids surface the real HTTP 404.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 18:06:19 -04:00
Justin BollingerandClaude Opus 4.8 6c7b31dbb7 fix(update): repair master->main tracking in self-updater
Old clones made before the default-branch rename sit on a local `master`
whose upstream still points at the deleted refs/heads/master, so both a
bare `git pull` and `_run_upgrade()`'s `git checkout main` failed on stale
clones. The updater now fetches origin first, checks out main via
`git checkout -B main origin/main`, repairs the upstream to origin/main,
and pulls explicitly with `git pull origin main` so it never consults the
dangling branch.*.merge config. Existing dirty-branch and detached-HEAD
guards are unchanged.

Adds tests covering the renamed-clone migration and the fetch-failure bail.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 10:42:42 -04:00
Justin BollingerandClaude Opus 4.8 1b31ecf705 docs: add v2.10.6 version-history entries for env override + local test harness
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 11:52:29 -04:00
Justin Bollinger 1af6984ff4 Merge branch 'feat/hashview-live-tests-local' into integrate/hashview-routes
# Conflicts:
#	hate_crack/api.py
#	tests/test_hashview.py
2026-06-25 10:55:49 -04:00
Justin BollingerandClaude Opus 4.8 048ed7cac1 feat(test): run live Hashview tests against a local docker stack
The live Hashview tests previously could only run against a remote server
configured in config.json, and the CLI ignored env-var overrides, so the
suite always hit prod. Prod runs an older Hashview whose /v1/jobs/add 500s
on a notify_email kwarg, which masked real client/server drift.

Wire the suite up to a local Hashview docker stack:

- main.py: HASHVIEW_URL / HASHVIEW_API_KEY env vars now override config.json,
  so the CLI can be pointed at a local instance without editing config.
- tests/_hashview_local.py + pytest_configure: when HASHVIEW_TEST_LOCAL=1,
  bring up + seed the Hashview compose stack (HASHVIEW_REPO), verify
  authenticated API access, export the HASHVIEW_* env, and tear down
  (HASHVIEW_KEEP=1 keeps it). Runs in configure so collection-time skipif
  on HASHVIEW_TEST_REAL sees the exported env.
- tests/hashview_local_seed.py: seed an admin api_key + non-default password
  (else Hashview's setup guard redirects every request to /setup), a
  customer, a hashfile, and cracked "effective task" data (else /v1/jobs/add
  has no tasks to schedule).
- api.py: download_left_hashes now uses GET /v1/hashfiles/<id>; the old
  /v1/hashfiles/<id>/left route 404s on current servers.
- subprocess tests: assert on the CLI's actual output ("Job ID:") rather than
  the literal "Job created", and strip ambient HASHVIEW_* creds from the
  no-key-configured check so the env override doesn't defeat it.
- README/CLAUDE: document HASHVIEW_TEST_LOCAL and the env overrides.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 10:17:49 -04:00
Justin BollingerandClaude Opus 4.8 c07bab1a2b fix(hashview): degrade to direct hashfile-ID entry when listing API absent
The hashfile-listing route (/v1/hashfiles/hash_type/<type>) only exists
on Hashview builds from 2026-06-08+ (v0.8.3-dev). On `main` and older
servers it 404s, which surfaced as "Could not list hashfiles" and a dead
end. The download flow is now version-adaptive:

- get_all_customer_hashfiles stops sweeping after the first 404 (the
  listing endpoint is absent) instead of probing every common type.
- The menu treats listing as best-effort: when no listing is available
  it prints a clear note and accepts a hashfile ID typed directly (read
  from the web UI), with no list-membership check. The chosen file's
  type is resolved via GET /v1/getHashType/<id> and downloaded via
  GET /v1/hashfiles/<id> -- both present on all server versions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 17:56:48 -04:00
Justin BollingerandClaude Opus 4.8 347e3529d5 feat(hashview): display a customer's hashfiles instead of asking for type
Downloading previously required knowing/typing the hash type because
Hashview only lists hashfiles per type. The download flow now sweeps
common hashcat modes (HashviewAPI.get_all_customer_hashfiles) and shows
all of the customer's uploaded hashfiles to pick from, deduped by id.
A manual hash-type prompt remains as a fallback only when nothing is
found among the common set (uncommon modes). The chosen file's real
hash type still drives the download.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 17:44:48 -04:00
Justin BollingerandClaude Opus 4.8 ab4700e636 fix(hashview): prompt for hash type when session type is unset
The download-hashes flow scoped the customer hashfile listing to
hcatHashType, but that is None when the Hashview menu is entered
without a hashfile loaded this session -> "No hashfiles of type None
found". Since Hashview only lists hashfiles per type, prompt for a
hashcat hash-type when none is set (Q cancels back to the menu) and
use it for the listing. Downstream selection still derives the real
type from the chosen hashfile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 17:40:36 -04:00
Justin BollingerandClaude Opus 4.8 90653b856f fix(hashview): correct remaining job/hashfile API routes
Continues the v0.8.3-dev API alignment beyond the hashfile-listing 404:

- download_left_hashes: "left" hashes are GET /v1/hashfiles/<id>
  (returns uncracked ciphertexts), not the nonexistent /<id>/left.
- delete_job: DELETE /v1/jobs/<id>, not GET /v1/jobs/delete/<id>.
- start_job: POST /v1/jobs/start/<id>, not GET (route is POST-only).
- stop_job: Hashview has no stop route; raise NotImplementedError
  pointing at delete_job rather than calling a phantom endpoint.
- found-hash bulk export: no such route exists (only single-hash
  POST /v1/search); the best-effort merge is documented and degrades
  gracefully on the expected 404.

Adds offline tests asserting start_job POSTs, delete_job uses DELETE,
and stop_job raises. Documents the release in README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:59:40 -04:00
Justin BollingerandClaude Opus 4.7 23ef425aef docs: add v2.10.5 version history entry
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 12:02:17 -04:00
Justin BollingerandClaude Opus 4.7 5fcd589cbc docs: add v2.10.4 version history entry
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 11:44:06 -04:00
Justin BollingerandClaude Opus 4.7 32ca52af77 docs: add v2.10.3 version history entry
Covers the auto-upgrade-loop fix shipping in this patch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 16:31:22 -04:00
Justin BollingerandClaude Opus 4.7 19abb7b479 docs: add v2.10.2 version history entry
Covers the two fingerprint-attack bugfixes shipping in this patch:
the empty-.expanded guard and the LC_ALL=C sort locale fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 15:09:05 -04:00
Justin Bollinger 5fc54f4574 docs: add v2.10.1 version history entry 2026-05-05 19:45:14 -04:00
Justin BollingerandClaude Opus 4.7 202f5480e1 build(deps): make simple-term-menu a default dependency
Move simple-term-menu from the [tui] optional extra into the main
dependencies list so arrow-key menu navigation works out of the box.
Users can still opt into the plain numbered menu with
HATE_CRACK_PLAIN_MENU=1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 14:37:08 -04:00
Justin BollingerandClaude Sonnet 4.6 c037242037 docs(readme): correct version history to v2.9.3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 20:41:45 -04:00
Justin BollingerandClaude Sonnet 4.6 a2a79a72b4 docs(readme): consolidate torrent changes under v2.10.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 20:38:51 -04:00
Justin BollingerandClaude Sonnet 4.6 598bfd97e5 fix(api): store torrent files in /tmp/hate_crack/ not /tmp/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 20:28:22 -04:00
Justin BollingerandClaude Sonnet 4.6 0d8089ea17 fix(api): increase watch-dir polling timeout from 10s to 30s
Transmission's watch dir scanner runs every ~10s, so a 10s deadline
could expire before the first scan completes. 30s gives 2-3 scan
cycles of headroom.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 20:27:33 -04:00
Justin BollingerandClaude Sonnet 4.6 7e8641bc3b docs(readme): add v2.9.3 version history entry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 20:08:55 -04:00
Justin BollingerandClaude Sonnet 4.6 56b2f99145 fix(api): add missing return in info_file after exhausted loop
Prevent implicit None return when no data row matches the expected
transmission-remote --info-files format. Also clarify README macOS
install note.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 17:31:31 -04:00
Justin BollingerandClaude Sonnet 4.6 dc62af105a fix(docs): use correct brew formula transmission-cli, clarify both deps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 16:12:53 -04:00
Justin BollingerandClaude Sonnet 4.6 cca2ff0065 chore: replace transmission-cli with transmission-daemon in CI/install
Delete wordlists/kill_transmission.sh (replaced by Python extraction).
Update Makefile, Dockerfile.test, lima config, README, TESTING.md, and
test_dependencies.py to reference transmission-daemon/transmission-remote
instead of transmission-cli.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 00:46:51 -04:00
Justin BollingerandClaude Sonnet 4.6 61fb8309d2 docs: document Notifications submenu (option 82) in README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 19:28:08 -04:00
Justin Bollinger d0bfb015a6 docs: update README for v2.5.0 changes 2026-03-20 11:15:29 -04:00
Justin Bollinger 95d0eb229a feat: add rule file tools submenu (key 81) with cleanup and optimize
Resolves merge conflict with origin/main (keys 19-22 and 80 from main
kept, rule tools submenu added at key 81).
2026-03-19 16:03:40 -04:00
Justin Bollinger 4b5091ef89 feat: add wordlist tools submenu (key 80) with 7 hashcat-utils filters
Resolves merge conflict with origin/main (keys 19-22 from main kept,
wordlist tools submenu added at key 80).

Fixes test isolation bug in test_random_rules_attack.py where
load_cli_module() nuked hate_crack.attacks from sys.modules, breaking
__globals__ references in wordlist_tools_submenu for downstream tests.
Also corrects wrong menu key assertion (21 not 20) for generate_rules_crack.
2026-03-19 16:00:09 -04:00
Justin Bollinger a31497649f feat: add combipow passphrase attack at menu key 22
Resolves merge conflict with origin/main (keys 19-21 used by ngram,
permute, random-rules). Combipow takes key 22.

- gzip support: decompress .gz wordlists to a temp file before passing
  path to combipow.bin (which requires a filename argument)
- UI line-counting uses gzip.open for .gz files
- Update tests to reference key 22 instead of 21
2026-03-19 15:50:25 -04:00
Justin Bollinger 63e7286fcb merge: resolve conflicts with main - random rules moves to key 21 2026-03-19 15:42:11 -04:00
Justin Bollinger 92a835c6d8 merge: resolve conflicts with main - permute moves to key 20, ngram stays at 19 2026-03-19 15:33:48 -04:00
Justin Bollinger 399cd06fdb docs: add Wordlist Tools submenu to README 2026-03-19 12:17:48 -04:00
Justin Bollinger 2d77d8e582 feat: add combipow passphrase attack (#88)
Add menu option 21 (Combipow Passphrase Attack) using combipow.bin from
hashcat-utils. Generates all unique non-empty subset combinations from a
short wordlist and pipes them into hashcat stdin.

- hcatCombipow(hash_type, hash_file, wordlist, use_space_sep) in main.py
- combipow_crack handler in attacks.py validates file, enforces 63-line
  limit, prompts for space separator, then delegates to hcatCombipow
- Wired into get_main_menu_items() and get_main_menu_options() in both
  main.py and hate_crack.py
- 12 tests covering menu presence, handler delegation, line-count
  enforcement, file validation, and subprocess flag construction
2026-03-19 12:17:26 -04:00
Justin Bollinger 69e6fb9cb3 feat: add combinator3 and combinatorX attacks to combinator submenu
Extends the combinator submenu (option 6) with two new attacks using
hashcat-utils binaries that were already compiled but unused.

- hcatCombinator3: 3-way wordlist combination via combinator3.bin piped
  to hashcat stdin
- hcatCombinatorX: 2-8 wordlist combination via combinatorX.bin with
  optional --sepFill separator, piped to hashcat stdin
- combinator3_crack handler: prompts for 3 comma-separated wordlist paths
- combinatorX_crack handler: prompts for 2-8 paths plus optional separator
- combinator_submenu updated with options 5 and 6

Closes #84, closes #85
2026-03-19 12:16:04 -04:00
Justin Bollinger 7664afda55 feat: add wordlist tools submenu (len, req-include, req-exclude, cutb, rli, rli2, splitlen, gate) (#90, #91, #92, #94)
Add Wordlist Tools submenu (key 80) with 7 preprocessing utilities backed by hashcat-utils binaries:

- Filter by length (len.bin) - #90
- Require/exclude character classes (req-include.bin, req-exclude.bin) - #90
- Extract substring (cutb.bin) - #90
- Remove matching lines (rli.bin, rli2.bin) - #91
- Split by length (splitlen.bin) - #92
- Shard wordlist (gate.bin) - #94

Three-layer pattern:
- main.py: low-level wrappers (wordlist_filter_len, wordlist_filter_req_include,
  wordlist_filter_req_exclude, wordlist_cutb, wordlist_splitlen, wordlist_subtract,
  wordlist_subtract_single, wordlist_gate) return bool for testability
- attacks.py: UI handlers with input validation and the wordlist_tools_submenu dispatcher
- hate_crack.py + main.py: menu item "80" wired in both get_main_menu_items and
  get_main_menu_options

Move interactive_menu import to attacks.py module level (was local import in
combinator_submenu) to support patching in tests.
2026-03-19 12:15:43 -04:00
Justin Bollinger e41134eb1a feat: add permutation attack using permute.bin (closes #86)
Adds Permutation Attack (menu option 19) that generates all character
permutations of each word in a targeted wordlist and pipes them to
hashcat via permute.bin from hashcat-utils.

- hcatPermute() in main.py: pipes permute.bin < wordlist | hashcat
- permute_crack() in attacks.py: prompts for single wordlist file with
  factorial-growth warning, tab-autocomplete support
- Menu option 19 wired in both main.py and hate_crack.py
- hcatPermuteCount tracking alongside other count globals
- Tests: test_permute_attack.py (handler behavior) and
  test_permute_wrapper.py (subprocess wiring)
- README: added entry in menu listing and attack descriptions
2026-03-19 12:14:05 -04:00
Justin Bollinger dfe9e28e70 feat: add random rules attack using generate-rules.bin (#87)
- Add hcatGenerateRules() in main.py: runs generate-rules.bin to
  produce N random rules, writes them to a temp file, runs hashcat
  with -r against a chosen wordlist, cleans up on exit
- Add generate_rules_crack() handler in attacks.py with count
  prompt (default 65536), wordlist picker with tab-completion,
  input validation, and abort on invalid input
- Add dispatcher generate_rules_crack() in main.py and key "20"
  in both main.py and hate_crack.py get_main_menu_options()
- Add ("20", "Random Rules Attack") to get_main_menu_items()
- Add tests: test_random_rules_attack.py (menu presence, handler
  wiring), test_random_rules_wrapper.py (subprocess behavior,
  cleanup, count passing, count tracking)
- Add key "20" to MENU_OPTION_TEST_CASES in test_ui_menu_options.py
- Update README: add option 20 to menu listing, add attack
  description, add version history entry
2026-03-19 12:13:38 -04:00
Justin Bollinger 9611565471 feat: add rule file management tools using cleanup-rules.bin and rules_optimize.bin (closes #93)
Adds Rule File Tools submenu (menu option 81) with three operations:
- Clean: removes invalid/duplicate rules via cleanup-rules.bin
- Optimize: consolidates redundant operations via rules_optimize.bin
- Clean and optimize: both in sequence with temp file handling

Wired through the standard three-layer pattern: main.py utility
functions + dispatcher, attacks.py handlers + submenu, root
hate_crack.py menu registration.
2026-03-19 12:12:12 -04:00
Justin Bollinger 02ce2092ec docs: add ad-hoc mask and markov brute force attack documentation
- Update menu listing to show combinator submenu and new attacks (17, 18)
- Remove keys 10/11/12 from main menu (consolidated into submenu)
- Add detailed descriptions for Combinator Attacks submenu, Ad-hoc Mask Attack, and Markov Brute Force Attack
- Document Markov training source selection and table persistence
- Update version history with new feature details
2026-03-18 19:02:35 -04:00
Justin Bollinger fda38d3498 docs: update README with OMEN fix and issues #80, #81, #82 2026-03-17 15:07:02 -04:00
Justin Bollinger a1b81ec01d fix: replace uv tool install with bash shim for reliable config resolution
Config and assets were not found when running hate_crack from outside the
repo directory. The shim uses `uv run --directory` to always execute from
the repo root, and _candidate_roots() now includes _repo_root and
_package_path as fallback search locations.
2026-03-17 12:45:19 -04:00
Justin Bollinger 83491ea17d docs: update README with recent bug fixes in version history 2026-03-16 14:33:43 -04:00
Justin Bollinger e0a79d7c7b refactor: remove vendor-assets wheel build flow, use editable install
- Remove vendor-assets and clean-vendor Makefile targets
- Lima VM test and Dockerfile.test now use make install (editable)
- Remove hate_crack/hashcat-utils from submodules-pre expander generation
- Update README to reflect no-vendoring install
2026-03-16 11:50:32 -04:00