diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9bbe07a..270239d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
 
 ## [Unreleased]
 
+### Added
+
+- Next-action can now read multiple todo.txt files to select the next action from. For example: `next-action --file todo.txt --file big-project-todo.txt`. Closes #35.
+
 ### Changed
 
 - Ignore tasks that have a start date in the future. Closes #34.
diff --git a/README.md b/README.md
index 3dfda58..4bc5ef1 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,7 @@ $ next-action
 
 The next action is determined using priority. Creation date is considered after priority, with older tasks getting precedence over newer tasks.
 
-Completed tasks (<del>`x This is a completed task`</del>) and tasks with a creation date in the future (`9999-01-01 Start preparing for five-digit years`) are not considered when determining the next action.
+Completed tasks (~~`x This is a completed task`~~) and tasks with a creation date in the future (`9999-01-01 Start preparing for five-digit years`) are not considered when determining the next action.
 
 ### Limit next actions
 
diff --git a/next_action/arguments.py b/next_action/arguments.py
index ec87cb1..adc90f4 100644
--- a/next_action/arguments.py
+++ b/next_action/arguments.py
@@ -48,7 +48,9 @@ def parse_arguments() -> argparse.Namespace:
     parser = argparse.ArgumentParser(description="Show the next action in your todo.txt",
                                      formatter_class=argparse.ArgumentDefaultsHelpFormatter)
     parser.add_argument("--version", action="version", version="%(prog)s {0}".format(next_action.__version__))
-    parser.add_argument("-f", "--file", help="filename of the todo.txt file to read", type=str, default="todo.txt")
+    default_filenames = ["todo.txt"]
+    parser.add_argument("-f", "--file", help="todo.txt file to read; argument can be repeated", type=str,
+                        action="append", dest="filenames", metavar="FILE", default=default_filenames)
     group = parser.add_mutually_exclusive_group()
     group.add_argument("-n", "--number", metavar="N", help="number of next actions to show", type=int, default=1)
     group.add_argument("-a", "--all", help="show all next actions", action="store_true")
@@ -57,6 +59,14 @@ def parse_arguments() -> argparse.Namespace:
     parser.add_argument("projects", metavar="+PROJECT", help="show the next action for the specified projects",
                         nargs="*", type=str, default=None, action=ContextProjectAction)
     namespace = parser.parse_args()
+    # Work around the issue that the "append" action doesn't overwrite defaults.
+    # See https://bugs.python.org/issue16399.
+    if default_filenames != namespace.filenames:
+        for default_filename in default_filenames:
+            namespace.filenames.remove(default_filename)
+    # Remove duplicate filenames while maintaining order.
+    namespace.filenames = list(dict.fromkeys(namespace.filenames))
+    # If the user wants to see all next actions, set the number to something big.
     if namespace.all:
         namespace.number = sys.maxsize
     return namespace
diff --git a/next_action/cli.py b/next_action/cli.py
index 93a7d57..e0c7f41 100644
--- a/next_action/cli.py
+++ b/next_action/cli.py
@@ -10,17 +10,18 @@ def next_action() -> None:
 
         Basic recipe:
         1) parse command-line arguments,
-        2) read todo.txt file,
+        2) read todo.txt file(s),
         3) determine the next action(s) and display them.
     """
     arguments = parse_arguments()
-    filename: str = arguments.file
-    try:
-        todotxt_file = open(filename, "r")
-    except FileNotFoundError:
-        print("Can't find {0}".format(filename))
-        return
-    with todotxt_file:
-        tasks = [Task(line.strip()) for line in todotxt_file.readlines() if line.strip()]
+    tasks = []
+    for filename in arguments.filenames:
+        try:
+            todotxt_file = open(filename, "r")
+        except FileNotFoundError:
+            print("Can't find {0}".format(filename))
+            return
+        with todotxt_file:
+            tasks.extend([Task(line.strip()) for line in todotxt_file.readlines() if line.strip()])
     actions = next_actions(tasks, set(arguments.contexts), set(arguments.projects))
     print("\n".join(action.text for action in actions[:arguments.number]) if actions else "Nothing to do!")

Allow for repeating --file
Show which file the next action was selected from somehow, e.g.:

```console
$ next-action --file work.txt home.txt
(A) Fix leaking roof [home.txt]
```
diff --git a/tests/unittests/test_arguments.py b/tests/unittests/test_arguments.py
index 6fa5f60..ac314cd 100644
--- a/tests/unittests/test_arguments.py
+++ b/tests/unittests/test_arguments.py
@@ -17,17 +17,32 @@ class ArgumentParserTest(unittest.TestCase):
     @patch.object(sys, "argv", ["next-action"])
     def test_default_filename(self):
         """ Test that the argument parser has a default filename. """
-        self.assertEqual("todo.txt", parse_arguments().file)
+        self.assertEqual(["todo.txt"], parse_arguments().filenames)
 
     @patch.object(sys, "argv", ["next-action", "-f", "my_todo.txt"])
     def test_filename_argument(self):
         """ Test that the argument parser accepts a filename. """
-        self.assertEqual("my_todo.txt", parse_arguments().file)
+        self.assertEqual(["my_todo.txt"], parse_arguments().filenames)
 
     @patch.object(sys, "argv", ["next-action", "--file", "my_other_todo.txt"])
     def test_long_filename_argument(self):
         """ Test that the argument parser accepts a filename. """
-        self.assertEqual("my_other_todo.txt", parse_arguments().file)
+        self.assertEqual(["my_other_todo.txt"], parse_arguments().filenames)
+
+    @patch.object(sys, "argv", ["next-action", "-f", "todo.txt"])
+    def test_add_default_filename(self):
+        """ Test that adding the default filename doesn't get it included twice. """
+        self.assertEqual(["todo.txt"], parse_arguments().filenames)
+
+    @patch.object(sys, "argv", ["next-action", "-f", "todo.txt", "-f", "other.txt"])
+    def test_default_and_non_default(self):
+        """ Test that adding the default filename and another filename gets both included. """
+        self.assertEqual(["todo.txt", "other.txt"], parse_arguments().filenames)
+
+    @patch.object(sys, "argv", ["next-action", "-f", "other.txt", "-f", "other.txt"])
+    def test__add_filename_twice(self):
+        """ Test that adding the same filename twice includes it only once. """
+        self.assertEqual(["other.txt"], parse_arguments().filenames)
 
     @patch.object(sys, "argv", ["next-action"])
     def test_no_context(self):
diff --git a/tests/unittests/test_cli.py b/tests/unittests/test_cli.py
index 1b80920..7c7d92a 100644
--- a/tests/unittests/test_cli.py
+++ b/tests/unittests/test_cli.py
@@ -71,7 +71,7 @@ positional arguments:
 optional arguments:
   -h, --help            show this help message and exit
   --version             show program's version number and exit
-  -f FILE, --file FILE  filename of the todo.txt file to read (default: todo.txt)
+  -f FILE, --file FILE  todo.txt file to read; argument can be repeated (default: ['todo.txt'])
   -n N, --number N      number of next actions to show (default: 1)
   -a, --all             show all next actions (default: False)
 """),

pip install -e .
parse_log_pytest
pytest
pytest
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
-e git+https://github.com/fniessink/next-action.git@4f4f97d3a24dba7b534e09cc514805f18a03d9c4#egg=next_action
packaging @ file:///croot/packaging_1734472117206/work
pluggy @ file:///croot/pluggy_1733169602837/work
pytest @ file:///croot/pytest_1738938843180/work
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work

name: next-action
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
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_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
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=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
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
prefix: /opt/conda/envs/next-action

tests/unittests/test_arguments.py::ArgumentParserTest::test__add_filename_twice tests/unittests/test_arguments.py::ArgumentParserTest::test_add_default_filename tests/unittests/test_arguments.py::ArgumentParserTest::test_default_and_non_default tests/unittests/test_arguments.py::ArgumentParserTest::test_default_filename tests/unittests/test_arguments.py::ArgumentParserTest::test_filename_argument tests/unittests/test_arguments.py::ArgumentParserTest::test_long_filename_argument
tests/unittests/test_arguments.py::ArgumentParserTest::test_all_and_number tests/unittests/test_arguments.py::ArgumentParserTest::test_empty_context tests/unittests/test_arguments.py::ArgumentParserTest::test_empty_project tests/unittests/test_arguments.py::ArgumentParserTest::test_faulty_number tests/unittests/test_arguments.py::ArgumentParserTest::test_faulty_option tests/unittests/test_cli.py::CLITest::test_help
tests/unittests/test_arguments.py::ArgumentParserTest::test_all_actions tests/unittests/test_arguments.py::ArgumentParserTest::test_contexts_and_projects tests/unittests/test_arguments.py::ArgumentParserTest::test_default_number tests/unittests/test_arguments.py::ArgumentParserTest::test_multiple_contexts tests/unittests/test_arguments.py::ArgumentParserTest::test_multiple_projects tests/unittests/test_arguments.py::ArgumentParserTest::test_no_context tests/unittests/test_arguments.py::ArgumentParserTest::test_number tests/unittests/test_arguments.py::ArgumentParserTest::test_one_context tests/unittests/test_arguments.py::ArgumentParserTest::test_one_project tests/unittests/test_cli.py::CLITest::test_context tests/unittests/test_cli.py::CLITest::test_empty_task_file tests/unittests/test_cli.py::CLITest::test_ignore_empty_lines tests/unittests/test_cli.py::CLITest::test_missing_file tests/unittests/test_cli.py::CLITest::test_number tests/unittests/test_cli.py::CLITest::test_one_task tests/unittests/test_cli.py::CLITest::test_project tests/unittests/test_cli.py::CLITest::test_version
next_action/cli.py README.md next_action/arguments.py CHANGELOG.md
next_action/cli.py README.md next_action/arguments.py CHANGELOG.md