--- /dev/null
+#!/bin/bash
+
+usage() {
+ cat <<EOF
+usage: aoc [options] <DAY>...
+
+Options:
+ --run run the solution for the given <DAY> (default)
+ --test run the tests for the given <DAY>
+ --input retrieve the input file for the given <DAY> (default)
+ --html retrieve the writeup for a given <DAY>
+ --help print this help and exit
+EOF
+}
+
+read_cookie() {
+ [ ! -f .cookie ] && echo "Missing .cookie file" && exit 1
+ COOKIE=$(cat .cookie)
+ [ -z "$COOKIE" ] && echo "Cookie file is empty" && exit 1
+}
+
+get_input() {
+ [ -f input/$DAY.txt ] && return
+ read_cookie
+ curl -o input/$DAY.txt \
+ -H "Cookie: session=$COOKIE" \
+ "https://adventofcode.com/2025/day/$(printf "%d" ${DAY/day/})/input"
+}
+
+get_html() {
+ read_cookie
+ curl -o html/$DAY.html \
+ -H "Cookie: session=$COOKIE" \
+ "https://adventofcode.com/2025/day/$(printf "%d" ${DAY/day/})"
+}
+
+do_test() {
+ cargo test $DAY::tests
+}
+
+do_run() {
+ cargo run --release $DAY input/$DAY.txt
+}
+
+COOKIE=""
+
+DAY=""
+DO_RUN=1
+DO_TEST=0
+DO_INPUT=1
+DO_HTML=0
+
+while [ $# -ge 1 ]; do
+ case $1 in
+ "--run") DO_RUN=1; DO_TEST=0 ;;
+ "--test") DO_RUN=0; DO_TEST=1; DO_INPUT=0 ;;
+ "--input") DO_INPUT=1; DO_RUN=0 ;;
+ "--html") DO_HTML=1; DO_RUN=0 ;;
+ "--help"|"-h") usage && exit 0 ;;
+ -*) echo "Unknown or missing option: $1" && usage && exit 1 ;;
+ *) break ;;
+ esac
+ shift
+done
+
+while [ $# -ge 1 ]; do
+ DAY=$1
+ echo "day: $DAY"
+ [ $DO_HTML -eq 1 ] && get_html
+ [ $DO_INPUT -eq 1 ] && get_input
+ [ $DO_RUN -eq 1 ] && do_run
+ [ $DO_TEST -eq 1 ] && do_test
+ shift
+done