diff --git a/AUTHORS b/AUTHORS
index 0817aa1..c4d08fc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,4 @@
 Nicholas H.Tollervey (ntoll@ntoll.org)
 Matt Wheeler (m@funkyhat.org)
 Tom Viner (uflash@viner.tv)
+Tom Gurion (nagasaki45@gmail.com)
diff --git a/README.rst b/README.rst
index 0451d63..610092f 100644
--- a/README.rst
+++ b/README.rst
@@ -57,6 +57,15 @@ the path to the Python script in as the first argument to the command::
     $ uflash my_script.py
     Flashing Python to: /media/ntoll/MICROBIT/micropython.hex
 
+You can let uflash watch for changes of your script. It will be flashed
+automatically every time you save it::
+
+    $ uflash -w my_script.py
+
+or::
+
+    $ uflash --watch my_script.py
+
 At this point uflash will try to automatically detect the path to the device.
 However, if you have several devices plugged in and/or know what the path on
 the filesystem to the BBC micro:bit already is, you can specify this as a
@@ -124,4 +133,3 @@ with development. Typing ``make`` on its own will list the options thus::
     make package - create a deployable package for the project.
     make publish - publish the project to PyPI.
     make docs - run sphinx to create project documentation.
-
diff --git a/uflash.py b/uflash.py
index 3082398..1bcb02d 100644
--- a/uflash.py
+++ b/uflash.py
@@ -12,6 +12,7 @@ import os
 import struct
 import sys
 from subprocess import check_output
+import time
 
 #: The magic start address in flash memory for a Python script.
 _SCRIPT_ADDR = 0x3e000
@@ -291,6 +292,27 @@ def extract(path_to_hex, output_path=None):
             print(python_script)
 
 
+def watch_file(path, func, *args, **kwargs):
+    """
+    Watch a file for changes by polling its last modification time. Call the
+    provided function with *args and **kwargs upon modification.
+    """
+    if not path:
+        raise ValueError('Please specify a file to watch')
+    print('Watching "{}" for changes'.format(path))
+    last_modification_time = os.path.getmtime(path)
+    try:
+        while True:
+            time.sleep(1)
+            new_modification_time = os.path.getmtime(path)
+            if new_modification_time == last_modification_time:
+                continue
+            func(*args, **kwargs)
+            last_modification_time = new_modification_time
+    except KeyboardInterrupt:
+        pass
+
+
 def main(argv=None):
     """
     Entry point for the command line tool 'uflash'.
@@ -316,10 +338,18 @@ def main(argv=None):
                             action='store_true',
                             help=("Extract python source from a hex file"
                                   " instead of creating the hex file."), )
+        parser.add_argument('-w', '--watch',
+                            action='store_true',
+                            help='Watch the source file for changes.')
         args = parser.parse_args(argv)
 
         if args.extract:
             extract(args.source, args.target)
+        elif args.watch:
+            watch_file(args.source, flash,
+                       path_to_python=args.source,
+                       paths_to_microbits=args.target,
+                       path_to_runtime=args.runtime)
         else:
             flash(path_to_python=args.source, paths_to_microbits=args.target,
                   path_to_runtime=args.runtime)

Add command line flag to watch the script for changes and re-flash
I'm currently doing it with `inotifywait`, but I think that it might be usefull as part of uflash itself, with additional command line flag.

```bash
while inotifywait -e modify my_script.py; do
    uflash my_script.py
done
```

(BTW, :+1: for the guidelines for contribution!)
diff --git a/tests/test_uflash.py b/tests/test_uflash.py
index 6794b06..0428b4e 100644
--- a/tests/test_uflash.py
+++ b/tests/test_uflash.py
@@ -7,6 +7,8 @@ import os
 import os.path
 import sys
 import tempfile
+import time
+import threading
 
 import pytest
 import uflash
@@ -461,6 +463,19 @@ def test_main_named_args():
                                            path_to_runtime='baz.hex')
 
 
+def test_main_watch_flag():
+    """
+    The watch flag cause a call the correct function.
+    """
+    with mock.patch('uflash.watch_file') as mock_watch_file:
+        uflash.main(argv=['-w'])
+        mock_watch_file.assert_called_once_with(None,
+                                                uflash.flash,
+                                                path_to_python=None,
+                                                paths_to_microbits=[],
+                                                path_to_runtime=None)
+
+
 def test_extract_command():
     """
     Test the command-line script extract feature
@@ -515,3 +530,44 @@ def test_extract_command_no_source():
     """
     with pytest.raises(TypeError):
         uflash.extract(None, None)
+
+
+def test_watch_no_source():
+    """
+    If there is no source file the watch command should complain.
+    """
+    with pytest.raises(ValueError):
+        uflash.watch_file(None, lambda: "should never be called!")
+
+
+@mock.patch('uflash.time')
+@mock.patch('uflash.os')
+def test_watch_file(mock_os, mock_time):
+    """
+    Make sure that the callback is called each time the file changes.
+    """
+    # Our function will throw KeyboardInterrupt when called for the 2nd time,
+    # ending the watching gracefully.This will help in testing the
+    # watch_file function.
+    call_count = [0]
+
+    def func():
+        call_count[0] = call_count[0] + 1
+        if call_count[0] == 2:
+            raise KeyboardInterrupt()
+
+    # Instead of modifying any file, let's change the return value of
+    # os.path.getmtime. Start with initial value of 0.
+    mock_os.path.getmtime.return_value = 0
+
+    t = threading.Thread(target=uflash.watch_file,
+                         args=('path/to/file', func))
+    t.start()
+    time.sleep(0.01)
+    mock_os.path.getmtime.return_value = 1  # Simulate file change
+    time.sleep(0.01)
+    assert t.is_alive()
+    assert call_count[0] == 1
+    mock_os.path.getmtime.return_value = 2  # Simulate file change
+    t.join()
+    assert call_count[0] == 2

pip install -e .
parse_log_pytest
requirements.txt
pytest
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
alabaster==0.7.16
babel==2.17.0
certifi==2025.1.31
charset-normalizer==3.4.1
coverage==7.8.0
docutils==0.21.2
exceptiongroup==1.2.2
idna==3.10
imagesize==1.4.1
importlib_metadata==8.6.1
iniconfig==2.1.0
Jinja2==3.1.6
MarkupSafe==3.0.2
packaging==24.2
pep8==1.7.1
pluggy==1.5.0
pyflakes==3.3.1
Pygments==2.19.1
pytest==8.3.5
pytest-cov==6.0.0
requests==2.32.3
snowballstemmer==2.2.0
Sphinx==7.4.7
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
tomli==2.2.1
-e git+https://github.com/ntoll/uflash.git@fe26fe8ea0b7943674cb8165e6939cba3ef0dc88#egg=uflash
urllib3==2.3.0
zipp==3.21.0

name: uflash
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:
      - alabaster==0.7.16
      - babel==2.17.0
      - certifi==2025.1.31
      - charset-normalizer==3.4.1
      - coverage==7.8.0
      - docutils==0.21.2
      - exceptiongroup==1.2.2
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - jinja2==3.1.6
      - markupsafe==3.0.2
      - packaging==24.2
      - pep8==1.7.1
      - pluggy==1.5.0
      - pyflakes==3.3.1
      - pygments==2.19.1
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - requests==2.32.3
      - snowballstemmer==2.2.0
      - sphinx==7.4.7
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - tomli==2.2.1
      - urllib3==2.3.0
      - zipp==3.21.0
prefix: /opt/conda/envs/uflash

tests/test_uflash.py::test_main_watch_flag tests/test_uflash.py::test_watch_no_source tests/test_uflash.py::test_watch_file
tests/test_uflash.py::test_get_version tests/test_uflash.py::test_hexlify tests/test_uflash.py::test_unhexlify tests/test_uflash.py::test_hexlify_empty_script tests/test_uflash.py::test_embed_hex tests/test_uflash.py::test_embed_no_python tests/test_uflash.py::test_embed_no_runtime tests/test_uflash.py::test_extract tests/test_uflash.py::test_extract_not_valid_hex tests/test_uflash.py::test_extract_no_python tests/test_uflash.py::test_find_microbit_posix_exists tests/test_uflash.py::test_find_microbit_posix_missing tests/test_uflash.py::test_find_microbit_nt_exists tests/test_uflash.py::test_find_microbit_nt_missing tests/test_uflash.py::test_find_microbit_unknown_os tests/test_uflash.py::test_save_hex tests/test_uflash.py::test_save_hex_no_hex tests/test_uflash.py::test_save_hex_path_not_to_hex_file tests/test_uflash.py::test_flash_no_args tests/test_uflash.py::test_flash_has_python_no_path_to_microbit tests/test_uflash.py::test_flash_with_path_to_multiple_microbits tests/test_uflash.py::test_flash_with_path_to_microbit tests/test_uflash.py::test_flash_with_path_to_runtime tests/test_uflash.py::test_flash_cannot_find_microbit tests/test_uflash.py::test_flash_wrong_python tests/test_uflash.py::test_main_no_args tests/test_uflash.py::test_main_first_arg_python tests/test_uflash.py::test_main_first_arg_help tests/test_uflash.py::test_main_first_arg_not_python tests/test_uflash.py::test_main_two_args tests/test_uflash.py::test_main_multiple_microbits tests/test_uflash.py::test_main_runtime tests/test_uflash.py::test_main_named_args tests/test_uflash.py::test_extract_command tests/test_uflash.py::test_extract_paths tests/test_uflash.py::test_extract_command_source_only tests/test_uflash.py::test_extract_command_no_source
README.rst uflash.py AUTHORS
README.rst uflash.py AUTHORS