Skip to main content

Advent of Code helper for Python: fetch and cache inputs, submit answers, and pull private leaderboards.

Project description

elf: Advent of Code helper for Python

elf logo

A fast, modern Advent of Code CLI with caching, guardrails, leaderboards, and a lightweight Python API.

Works on macOS, Linux, and Windows. Most networked commands require an AoC session cookie (AOC_SESSION).

Why I Built This

Advent of Code has become one of my favorite Christmas traditions. I am never the fastest solver, and some puzzles definitely keep me humble, but the challenges always spark new ideas and mark the start of the holiday season for me.

Thank you to Eric Wastl, the creator of Advent of Code. His work brings an incredible community together every December and inspires people around the world to learn, explore new ideas, and enjoy the fun of programming puzzles.

After refining a small helper tool I have used personally for the past few years, I decided to turn it into a package others can benefit from as well. I originally built an early version for my own workflows in my personal AoC repo.

If Advent of Code is part of your December ritual too, I hope this little elf makes the journey smoother, more fun, and a bit more magical.

Highlights

  • Fetch inputs instantly with automatic caching
  • Submit answers safely with smart guardrails (duplicate, low, high, locked, cooldown)
  • Explore private leaderboards as tables, JSON, or Pydantic models
  • View your status calendar (table, JSON, or model)
  • Inspect your guess history with timestamps and per-part details
  • Open any AoC page (puzzle, input, or website) straight from the CLI
  • Use elf as a CLI tool or a full Python API

Installation

Using uv (recommended)

Install as a tool

uv tool install elf

Inside a project

uv add elf

Using pip

pip install elf

Requirements

  • Python 3.11 or newer
  • An Advent of Code account
  • AOC_SESSION cookie set in your environment for most commands

Configure your AoC Session

Most features in elf require your Advent of Code session cookie so the CLI can access your personal puzzle inputs and progress.

To get it:

  1. Log in to https://adventofcode.com using GitHub, Google, or Reddit.
  2. Open your browser’s developer tools.
    • Chrome: View → Developer → Developer Tools
    • Firefox: Tools → Browser Tools → Web Developer Tools
  3. Go to the Application (Chrome) or Storage (Firefox) tab.
  4. Look for Cookies for the domain adventofcode.com.
  5. Find the cookie named session.
  6. Copy the value (a long hex string).
  7. Set it as an environment variable:
export AOC_SESSION="your-session-token"

On Windows you can persist the cookie with PowerShell:

$env:AOC_SESSION = "your-session-token"
setx AOC_SESSION "your-session-token"

Or via CMD:

setx AOC_SESSION "your-session-token"

Most commands require this. You can also pass it via --session in the CLI or session= in the API.

Quick Start

export AOC_SESSION="your-session-token"

elf input        # fetch today's input
elf answer 2025 1 1 123 # submit answer for part 1
elf status       # view progress
elf leaderboard 2025 123456 --view-key ABCDEF

CLI Documentation

elf --help

Usage: elf [OPTIONS] COMMAND [ARGS]...

Advent of Code CLI

Options:
  --version, -V
  --debug
  --install-completion
  --show-completion
  --help

Commands:
  input        Fetch the input for a given year/day
  answer       Submit an answer
  leaderboard  Fetch/display a private leaderboard
  guesses      Show cached guesses
  status       Show yearly star status
  open         Open puzzle/input/website
  cache        Show cache information

Enable detailed tracebacks with --debug or ELF_DEBUG=1 when troubleshooting.


Commands

elf input

Fetch puzzle input with caching. Requires a session cookie.

Usage: elf input [YEAR] [DAY]

Options:
  --session TEXT   AOC session cookie (env: AOC_SESSION)

Defaults:

  • year: current year
  • day: current day in December, otherwise 1 (Dec 1)
  • Caches to ~/.cache/elf/<year>/<day>/input.txt (or platform equivalent)

elf answer

Submit an answer with safety guardrails. Requires a session cookie. Guardrails use your local guess cache to short-circuit duplicate answers and infer too-high/too-low for integer guesses.

Usage: elf answer YEAR DAY PART ANSWER

Options:
  --session TEXT  AOC session cookie

Behaviors:

  • Year and day are required to avoid accidental submissions.
  • Detects locked puzzles (future days or future years) and shows unlock timestamp.
  • Identifies too high / too low / duplicate guesses from local cache
  • Caches cooldown responses locally for ~60 seconds to avoid hammering the site
  • Writes to guess cache automatically (per part)

Exit codes:

  • 0 when the answer is correct or already completed on AoC
  • 2 when AoC rate-limits you (cooldown/WAIT)
  • 1 for incorrect/too-high/too-low/unknown guesses

Duplicate guesses reuse cached submissions, so the exit code follows the cached result: e.g., a cached correct/completed guess still exits 0, while cached incorrect/high/low responses return 1.

Example errors:

❄️ Puzzle YYYY‑MM‑DD not unlocked yet
1234 is not correct.
You submitted an answer recently. Please wait...
12345 is correct. Star awarded.

elf guesses

Display local guess history (per part). Requires a cached guesses.csv from previous submissions. Displays all guesses for both parts automatically.

Usage: elf guesses [YEAR] [DAY]

Example table:

Time (UTC)      Guess  Status
2025‑12‑05 ...  959    too_low
2025‑12‑05 ...  6951   correct

elf leaderboard

Fetch private leaderboards. Provide a view key for read-only access or a session cookie for authenticated access. A view key is the read-only share token you can generate on your AoC leaderboard page.

Usage: elf leaderboard YEAR BOARD_ID

Options:
  --view-key TEXT
  --session TEXT
  --format table|json|model

Supports:

  • table: pretty Rich table
  • json: raw JSON
  • model: structured Pydantic model

elf status

View your Advent of Code star calendar. Requires a session cookie.

Usage: elf status [YEAR]

Options:
  --session TEXT
  --format table|json|model

Defaults:

  • year: current year if omitted

Prints stars for each day.

elf open

Opens puzzle pages in your browser.

Usage: elf open [YEAR] [DAY]

Options:
  --kind puzzle|input|website

elf cache

Display cache directory information.

Usage: elf cache

Shows:

  • Cache root directory (platform-aware)
  • Number of cached files
  • Reminder to delete the directory manually to clear cache

Caching Behavior

  • Default cache dir: macOS/Linux ~/.cache/elf, Windows %LOCALAPPDATA%\elf
  • Override location with ELF_CACHE_DIR (respects XDG_CACHE_HOME on Linux)
  • Inputs stored under: <cache>/<year>/<day>/input.txt
  • Guess history stored as <cache>/<year>/<day>/guesses.csv
  • Duplicate/high/low guesses are short‑circuited locally when possible
  • Cooldown responses are cached locally for ~60 seconds to avoid hammering AoC
  • Guardrails rely on your local guess history only (new machines/cleared cache = fresh)
  • Delete the cache directory to clear everything

Concurrency note

The library reuses a process-global httpx.Client to keep CLI calls fast. For heavy multi-threaded usage, create separate elf.aoc_client.AOCClient instances per thread to avoid sharing the global session.


Library Usage

from elf import (
    get_puzzle_input,
    submit_puzzle_answer,
    get_private_leaderboard,
    get_user_status,
    OutputFormat,
)

# AOC_SESSION is used automatically if not passed explicitly
input_text = get_puzzle_input(2023, 5)

result = submit_puzzle_answer(2023, 5, 1, "12345")
print(result.is_correct, result.message)

leaderboard = get_private_leaderboard(
    2023, session=None, board_id=123456, view_key=None, fmt=OutputFormat.MODEL
)

status = get_user_status(2023, fmt=OutputFormat.TABLE)
print(status)

Puzzle Helpers

elf.helpers includes some small utilities you can use in your own AoC solutions:

from elf.helpers import parse_input, read_test_input, timer

Leaderboard Example

 elf leaderboard 2025 3913340
              Advent of Code 2025  Private Leaderboard
┏━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Rank  Name            Stars  Local Score  Last Star (UTC)     ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│    1  User A             45          900  2025-12-26 00:53:17 │
│    2  User B             45          855  2025-12-26 00:53:56 │
│    3  User C             36          622  2025-12-26 03:29:21 │
└──────┴────────────────┴───────┴─────────────┴─────────────────────┘

JSON format:

elf leaderboard 2025 3982840 --format json

Model format (Pydantic):

lb = get_private_leaderboard(2025, board_id=3982840, fmt=OutputFormat.MODEL)
members = sorted(lb.members.values(), key=lambda m: (-m.local_score, -m.stars))
print(members[0].name, members[0].stars)

Status Example

 elf status 2023
Advent of Code
  2023  cak
(AoC++) [34]
┏━━━━━┳━━━━━━━┓
┃ Day  Stars ┃
┡━━━━━╇━━━━━━━┩
│   1   ★★   │
│   2   ★★   │
│   3   ★★   │
│   4   ★☆   │
│   5   ★☆   │
│   6   ★★   │
│   7   ★★   │
│   8   ★☆   │
│   9   ☆☆   │
│  10   ☆☆   │
│  ..   ..   │
│  25   ☆☆   │
└─────┴───────┘

JSON format:

elf status 2023 --format json

Model format:

status = get_user_status(2023, fmt=OutputFormat.MODEL)
print(status.days[0].day, status.days[0].stars)

Development / Testing

Install the dev dependencies (currently just pytest) with:

pip install -e ".[dev]"

Run the test suite via:

uv run pytest

Alternatively, you can still run:

python -m pytest

Special Thanks

This project exists thanks to the generosity and creativity of others.

Thanks to Solos for donating the elf PyPI name.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

elf-1.0.0.tar.gz (36.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

elf-1.0.0-py3-none-any.whl (32.5 kB view details)

Uploaded Python 3

File details

Details for the file elf-1.0.0.tar.gz.

File metadata

  • Download URL: elf-1.0.0.tar.gz
  • Upload date:
  • Size: 36.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.5

File hashes

Hashes for elf-1.0.0.tar.gz
Algorithm Hash digest
SHA256 c10a9df11dd605f486b4b1be20787d15a0ebc6b4d4c43d5afa6f793551dc47be
MD5 88e98ef3c48b1dc0b706f923ff46f292
BLAKE2b-256 d3122510e16bd3be03234caecb3d054398aecfcc91dc1e32a9a3cb863827fd06

See more details on using hashes here.

File details

Details for the file elf-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: elf-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 32.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.5

File hashes

Hashes for elf-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5b63ca9571012596787b942e863bf2495f33404b2d5f3ac32c7cef8bec831519
MD5 cac1e7ab39c9fb29c428a7e808b488af
BLAKE2b-256 1f05289546d4d547a783663a4c251df3cf34d9b07c1bf4174de02638cf678e1e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page