diff --git a/hashin.py b/hashin.py
index a43390e..427079f 100755
--- a/hashin.py
+++ b/hashin.py
@@ -773,6 +773,23 @@ def main():
     parser = get_parser()
     args = parser.parse_args()
 
+    if (
+        args.update_all
+        and args.packages
+        and len(args.packages) == 1
+        and os.path.isfile(args.packages[0])
+        and args.packages[0].endswith(".txt")
+    ):
+        # It's totally common to make the mistake of using the `--update-all` flag
+        # and specifying the requirements file as the first argument. E.g.
+        #
+        #     $ hashin --update-all --interactive myproject/reqs.txt
+        #
+        # The user intention is clear any non-keyed flags get interpreted as a
+        # list of "packages". Let's fix that for the user.
+        args.requirements_file = args.packages[0]
+        args.packages = []
+
     if args.update_all:
         if args.packages:
             print(

Be kinder if the package is a requirements file
So many times I've typed something like this:

```bash
▶ hashin --dry-run -u requirements/default.txt
Can not combine the --update-all option with a list of packages.
```
when I meant to type `hashin --dry-run -u -r requirements/default.txt`

It reminds me of how `pip` deals with `pip install requirements.txt` and thinks `requirements.txt` is a package name on PyPI.
diff --git a/tests/test_cli.py b/tests/test_cli.py
index e494a33..8c60ba0 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -182,6 +182,36 @@ def test_packages_and_update_all(capsys, mock_get_parser):
     )
 
 
+def test_packages_and_update_all_with_requirements_file(
+    capsys, mock_get_parser, tmpfile
+):
+    with tmpfile() as filename:
+        with open(filename, "w") as f:
+            f.write("")
+
+        def mock_parse_args(*a, **k):
+            return argparse.Namespace(
+                packages=[filename],  # Note!
+                algorithm="sha256",
+                python_version="3.8",
+                verbose=False,
+                include_prereleases=False,
+                dry_run=False,
+                update_all=True,
+                interactive=False,
+                synchronous=False,
+                index_url="anything",
+            )
+
+        mock_get_parser().parse_args.side_effect = mock_parse_args
+
+        error = hashin.main()
+        assert error == 0
+        # Because the requirements file is empty, the update-all command
+        # won't find anything to query the internet about so we don't
+        # need to mock murlopen in this test.
+
+
 def test_no_packages_and_not_update_all(capsys, mock_get_parser):
     def mock_parse_args(*a, **k):
         return argparse.Namespace(

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest mock
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
backports.tarfile==1.2.0
cachetools==5.5.2
certifi==2025.1.31
cffi==1.17.1
chardet==5.2.0
charset-normalizer==3.4.1
colorama==0.4.6
cryptography==44.0.2
distlib==0.3.9
docutils==0.21.2
exceptiongroup==1.2.2
filelock==3.18.0
-e git+https://github.com/peterbe/hashin.git@23840376aaf09746264a99545526fe4bbec93e17#egg=hashin
id==1.5.0
idna==3.10
importlib_metadata==8.6.1
iniconfig==2.1.0
jaraco.classes==3.4.0
jaraco.context==6.0.1
jaraco.functools==4.1.0
jeepney==0.9.0
keyring==25.6.0
markdown-it-py==3.0.0
mdurl==0.1.2
mock==5.2.0
more-itertools==10.6.0
nh3==0.2.21
packaging==24.2
pip-api==0.0.34
platformdirs==4.3.7
pluggy==1.5.0
pycparser==2.22
Pygments==2.19.1
pyproject-api==1.9.0
pytest==8.3.5
readme_renderer==44.0
requests==2.32.3
requests-toolbelt==1.0.0
rfc3986==2.0.0
rich==14.0.0
SecretStorage==3.3.3
tomli==2.2.1
tox==4.25.0
twine==6.1.0
typing_extensions==4.13.0
urllib3==2.3.0
virtualenv==20.29.3
zipp==3.21.0

name: hashin
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - backports-tarfile==1.2.0
      - cachetools==5.5.2
      - certifi==2025.1.31
      - cffi==1.17.1
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - colorama==0.4.6
      - cryptography==44.0.2
      - distlib==0.3.9
      - docutils==0.21.2
      - exceptiongroup==1.2.2
      - filelock==3.18.0
      - id==1.5.0
      - idna==3.10
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - jaraco-classes==3.4.0
      - jaraco-context==6.0.1
      - jaraco-functools==4.1.0
      - jeepney==0.9.0
      - keyring==25.6.0
      - markdown-it-py==3.0.0
      - mdurl==0.1.2
      - mock==5.2.0
      - more-itertools==10.6.0
      - nh3==0.2.21
      - packaging==24.2
      - pip-api==0.0.34
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pycparser==2.22
      - pygments==2.19.1
      - pyproject-api==1.9.0
      - pytest==8.3.5
      - readme-renderer==44.0
      - requests==2.32.3
      - requests-toolbelt==1.0.0
      - rfc3986==2.0.0
      - rich==14.0.0
      - secretstorage==3.3.3
      - tomli==2.2.1
      - tox==4.25.0
      - twine==6.1.0
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - virtualenv==20.29.3
      - zipp==3.21.0
prefix: /opt/conda/envs/hashin

tests/test_cli.py::test_packages_and_update_all_with_requirements_file
tests/test_cli.py::test_get_latest_version_simple tests/test_cli.py::test_get_latest_version_only_pre_release tests/test_cli.py::test_get_latest_version_non_pre_release_leading_zeros tests/test_cli.py::test_get_hashes_error tests/test_cli.py::test_non_200_ok_download tests/test_cli.py::test_main_packageerrors_stderr tests/test_cli.py::test_packages_and_update_all tests/test_cli.py::test_no_packages_and_not_update_all tests/test_cli.py::test_interactive_not_update_all tests/test_cli.py::test_main_version tests/test_cli.py::test_amend_requirements_content_new tests/test_cli.py::test_amend_requirements_different_old_name tests/test_cli.py::test_amend_requirements_content_multiple_merge tests/test_cli.py::test_amend_requirements_content_replacement tests/test_cli.py::test_amend_requirements_content_actually_not_replacement tests/test_cli.py::test_amend_requirements_content_replacement_addition tests/test_cli.py::test_amend_requirements_content_replacement_single_to_multi tests/test_cli.py::test_amend_requirements_content_replacement_2 tests/test_cli.py::test_amend_requirements_content_replacement_amongst_others tests/test_cli.py::test_amend_requirements_content_replacement_amongst_others_2 tests/test_cli.py::test_amend_requirements_content_new_similar_name tests/test_cli.py::test_run tests/test_cli.py::test_canonical_list_of_hashes tests/test_cli.py::test_run_atomic_not_write_with_error_on_last_package tests/test_cli.py::test_run_interactive tests/test_cli.py::test_run_interactive_quit_and_accept_all tests/test_cli.py::test_run_interactive_case_redirect tests/test_cli.py::test_run_without_specific_version tests/test_cli.py::test_run_with_alternate_index_url tests/test_cli.py::test_run_contained_names tests/test_cli.py::test_run_case_insensitive tests/test_cli.py::test_run_update_all tests/test_cli.py::test_run_comments_with_package_spec_patterns tests/test_cli.py::test_run_dry tests/test_cli.py::test_run_dry_multiple_packages tests/test_cli.py::test_run_pep_0496 tests/test_cli.py::test_filter_releases tests/test_cli.py::test_release_url_metadata_python tests/test_cli.py::test_expand_python_version tests/test_cli.py::test_get_package_hashes tests/test_cli.py::test_get_package_hashes_from_alternate_index_url tests/test_cli.py::test_get_package_hashes_package_not_found tests/test_cli.py::test_get_package_hashes_unknown_algorithm tests/test_cli.py::test_get_package_hashes_without_version tests/test_cli.py::test_with_extras_syntax tests/test_cli.py::test_extras_syntax_edit tests/test_cli.py::test_add_extra_extras_syntax_edit tests/test_cli.py::test_change_extra_extras_syntax_edit tests/test_cli.py::test_remove_extra_extras_syntax_edit tests/test_cli.py::test_interactive_upgrade_request tests/test_cli.py::test_interactive_upgrade_request_repeat_question tests/test_cli.py::test_interactive_upgrade_request_help tests/test_cli.py::test_interactive_upgrade_request_force_yes
hashin.py
hashin.py