Astra banner

Astra

3 devlogs
6h 25m 39s

Astra is a CLI tool that fetches NASA Astronomy Picture of the Day and renders it right in your terminal. Set it as a terminal greeter and start every day with a photo about space.

This project uses AI

Used github copilot for code completion, claude and minimax for debugging

Demo Repository

Loading README...

ash

v0.2.2

Removed the API key setup prompt entirely. Now it just uses NASA’s built-in DEMO_KEY by default since it was a hassle for some users to grab an API key for themselves. If someone hits the rate limit (50 requests/day), it tells them how to set their own key.

Also added –version flag so users can check which version they have installed. Bumped the API timeout to handle slow connections better. Made some error messages better and added date validation for the date command so invalid dates get caught immediately instead of hitting the API.

Attachment
0
ash

Shipped this project!

Hours: 5.88
Cookies: 🍪 150
Multiplier: 25.56 cookies/hr

I built Astra, a CLI tool that fetches NASA’s Astronomy Picture of the Day and renders it directly in your terminal. Full-color inline images, not ASCII art.
The hardest part was definitely the image rendering. I tried using an existing library but it didn’t support SIXEL, so I ended up writing my own encoder from scratch. I had to figure out escape sequences, query the terminal for cell dimensions and background color, and deal with platform differences between Windows and Linux. Then I had to build a second renderer when I discovered Ghostty uses the Kitty protocol instead of SIXEL. Performance was another headache, the first version took over a minute to render because of all the loopty loops but numpy brought that down to a few seconds.
It also has a search command that lets you search through all APOD titles ever published since 1995, image caching so repeat views are instant, and you can save any APOD you like as HD images. My favorite feature is the terminal greeter, you can set it up so a new space photo greets you every morning when you open your terminal.My favorite feature is the terminal greeter, you can set it up so a new space photo greets you every morning when you open your terminal.
Published on PyPI: pip install astra-apod and it works anywhere (i hope)

ash

v0.2.0

I added image caching so downloaded APOD images are stored and reused for 14 days before expiring. This makes repeat views of the same APOD instant and saves bandwidth.

I also added astra search. Since NASA’s APOD API has no search endpoint, I went with scraping their archive index page which was a HTML file listing every APOD since 1995, about 11,000 entries. Parsed it with a regex and cached it locally with a 24 hour expiry so its fast on repeat searches. Results show up to 10 matches newest first, and you can pick a number to view that APOD directly.

Attachment
0
ash

v0.1.0

Started out by setting up the project structure and got the astra command working globally. Then I hooked up the NASA APOD API pretty easily.

The first real challenge was getting images to actually render in the terminal. I tried using the term-image library but the latest version on pypi didn’t have a sixel renderer, so I ended up building my own from scratch. Centering the image was tricky too, ANSI cursor positioning doesn’t work with SIXEL, so I had to create a full width canvas in pillow and paste the image centered on it.

Performance was a big problem early on. The pure python SIXEL encoder was taking 30-80 seconds. So I brought in numpy.

Added a terminal greeter feature so you can have today’s APOD show up automatically when you open your shell.

Found a timezone bug where the once per day check was comparing NASA’s publication date against local time, so it was showing the APOD on every terminal open. Fixed it by tracking when the greeter last ran instead.

Tested on my Linux machine with ghostty and discovered it doesn’t support SIXEL and it uses the Kitty protocol instead. So I built a third renderer. Kitty was actually way simpler than SIXEL.
Published to PyPI as astra-apod.

Attachment
0