diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..379270c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Edward Betts <edward@4angle.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a4857ad
--- /dev/null
+++ b/README.md
@@ -0,0 +1,103 @@
+# Flight History Backup and Display Scripts
+
+## Introduction
+
+These Python scripts allow you to automate the process of downloading and
+displaying your flight history from OpenFlights. You can use the backup script
+to regularly download a CSV backup of your flight data, and the display script
+to list your past and future flights. This README will guide you through
+setting up and using these scripts.
+
+## Prerequisites
+
+Before you begin, make sure you have the following requirements installed:
+
+- Python 3.x
+- [Playwright](https://playwright.dev/) for web automation (used by the backup
+  script)
+
+## Installation
+
+1. Clone or download this repository to your local machine.
+
+   ```bash
+   git clone https://git.4angle.com/edward/flights.git
+   ```
+
+2. Install the required Python modules for the scripts.
+
+   ```bash
+   pip install playwright
+   ```
+
+3. Create a configuration file for your OpenFlights account. You can use the
+   provided sample config file as a template (`config`). Update the `username`
+   and `password` fields with your OpenFlights login credentials.
+
+   ```ini
+   [backup]
+   backup_dir=/path/to/backup/directory
+   username=YourOpenFlightsUsername
+   password=YourOpenFlightsPassword
+
+   [history]
+   days=120
+   ```
+
+## Usage
+
+### Backup Script (`run_backup`)
+
+The backup script automates the process of downloading a CSV backup of your
+flight history from OpenFlights. You can schedule this script to run
+periodically, such as daily using cron.
+
+1. Open your terminal and navigate to the directory where you cloned or
+   downloaded the scripts.
+
+2. Run the backup script:
+
+   ```bash
+   python run_backup.py
+   ```
+
+   This script will launch a headless browser, log in to your OpenFlights
+   account, and download the CSV backup to the specified directory in your
+   configuration file.
+
+3. You can schedule this script to run daily using cron or any other scheduling
+   tool. For example, to run it every day at 2 AM, add the following line to
+   your crontab:
+
+   ```bash
+   0 2 * * * /usr/bin/python3 /path/to/openflights-scripts/run_backup
+   ```
+
+### Display Script (`flights`)
+
+The display script reads the downloaded CSV backup and displays a list of your
+past and future flights within a specified date range.
+
+1. Open your terminal and navigate to the directory where you cloned or
+   downloaded the scripts.
+
+2. Run the display script:
+
+   ```bash
+   python flights
+   ```
+
+   This script will read the most recent CSV backup file in the specified
+   directory, filter flights based on the configured date range, and display the
+   results.
+
+## Customization
+
+You can customize the scripts further by modifying the configuration file
+(`config`) or the scripts themselves. For example, you can adjust the number of
+days to look back for past flights or customize the display format.
+
+## License
+
+This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
+for details.
diff --git a/show b/flights
similarity index 84%
rename from show
rename to flights
index 6d20bc8..202528c 100755
--- a/show
+++ b/flights
@@ -1,13 +1,24 @@
 #!/usr/bin/python3
 
+import configparser
 import csv
 import os
 from datetime import datetime, timedelta
 from typing import Callable
 
-backup_loc = os.path.expanduser("~/backup/openflights")
+config_file_path = os.path.expanduser(
+    os.path.join(os.getenv("XDG_CONFIG_HOME", "~/.config"), "OpenFlights", "config")
+)
+
+config = configparser.ConfigParser()
+
+config.read(os.path.expanduser(config_file_path))
+
+backup_dir = os.path.expanduser(config.get("backup", "backup_dir"))
+days = int(config.get("history", "days"))
+
 now = datetime.now()
-since_date = now - timedelta(days=365 * 5)
+since_date = now - timedelta(days=days)
 
 airlines = {
     "British Airways": "BA",
@@ -90,7 +101,7 @@ def show_flights(flights: Flights) -> None:
 
 
 if __name__ == "__main__":
-    filename = get_most_recent(backup_loc, lambda f: f.endswith(".csv"))
+    filename = get_most_recent(backup_dir, lambda f: f.endswith(".csv"))
     assert filename
     flights = read_flights(filename)
     show_flights(flights)
diff --git a/run_backup b/run_backup
new file mode 100755
index 0000000..77eb39d
--- /dev/null
+++ b/run_backup
@@ -0,0 +1,44 @@
+#!/usr/bin/python3
+"""Download CSV of flights from OpenFlights."""
+
+import configparser
+import os.path
+
+from playwright.sync_api import Playwright, sync_playwright
+
+config_file_path = os.path.expanduser(
+    os.path.join(os.getenv("XDG_CONFIG_HOME", "~/.config"), "OpenFlights", "config")
+)
+
+config = configparser.ConfigParser()
+
+config.read(os.path.expanduser(config_file_path))
+
+backup_dir = os.path.expanduser(config.get("backup", "backup_dir"))
+username = config.get("backup", "username")
+password = config.get("backup", "password")
+
+
+def run(playwright: Playwright) -> None:
+    """Run backup."""
+    browser = playwright.chromium.launch(headless=True)
+    context = browser.new_context()
+    page = context.new_page()
+    page.goto("https://openflights.org/")
+    page.locator('input[name="name"]').fill(username)
+    page.locator('input[name="pw"]').fill(password)
+    page.get_by_role("button", name="Log in").click()
+    page.get_by_role("button", name="Settings").click()
+    with page.expect_download() as download_info:
+        page.get_by_role("button", name="Backup to CSV").click()
+    download = download_info.value
+    download.save_as(os.path.join(backup_dir, download.suggested_filename))
+    page.close()
+
+    context.storage_state(path="auth.json")
+    context.close()
+    browser.close()
+
+
+with sync_playwright() as playwright:
+    run(playwright)