You are browsing as a guest. Sign up (or log in) to start making projects!

xerneas

@xerneas

Joined June 2nd, 2026

  • 12Devlogs
  • 6Projects
  • 1Ships
  • 15Votes
Open comments for this post

50m 16s logged

the window moves now.

you can grab welcome.exe by its title bar and fling it around the desktop, hit the little red dot to close it, and click xerneasOS up top to summon it back. it’s a real window now. it even has a title bar.

spent a while wrestling with the drag math turns out you have to keep track of the cursor’s offset from the window when the drag starts. otherwise the window instantly teleports so its corner snaps to your mouse. not exactly the intended user experience.

also did some housekeeping: ripped all the CSS into style.css and the JavaScript into script.js so my HTML isn’t one giant cursed wall of inline styles anymore. windows are now a reusable .window component, so making future apps should be way easier.oh, and there’s a live clock in the top bar that updates every second. new Date() my beloved.

the cat remains. the cat is eternal.

next time: a real wallpaper, maybe an actual second app, and slowly making this feel less like “one draggable window about a cat” and more like an operating system (that’s still about a cat)

0

Loading discussion…

0
2
Open comments for this post

2h 1m 10s logged

Live Hackfetch

New milestone today: hackfetch can now stay open and update itself while you code.

The goal was simple: run hackfetch once, leave it in the corner of your terminal, and watch the numbers move in real time as you work.

hackfetch -watch

Your today-hours tick up. Your top project changes when you switch repos. Your streak rolls over at midnight. All without running the command a second time.

The static render was already in place from the regular one-shot fetch. The new part was redrawing without scrolling.

That sounds simple. It is not.

In a terminal, every time you print something, it appends to the bottom of the screen. By default, refreshing the fetch would just print a second copy of itself underneath the first, then a third, then a fourth. Within a minute you’d have a wall of identical fetches scrolling away into the past.

The trick is ANSI escape codes. There’s a sequence that means “move the cursor up N lines” and one that means “clear the rest of the screen from here down.” Together they let you erase the previous fetch and redraw a new one in the same spot. Same screen, fresh data, no scroll.

Why every 30 seconds? Two reasons:

Hackatime aggregates heartbeats in 1-minute buckets internally, so polling faster than that doesn’t tell you anything new 30 seconds is fast enough to feel “live” without hammering the API for no reason

Ctrl+C to quit. Resizing the terminal doesn’t break it. Pair it with a gradient color scheme and the whole thing turns into a tiny dashboard for your coding session:

hackfetch -watch sunset

1

Loading discussion…

0
8
Open comments for this post

1h 2m 31s logged

The Problem and My Idea

The problem. Brain-to-image datasets are huge and growing, and the only way we compress them today is generic lossy compression that optimizes how the waveform looks. That throws away the part that actually matters: what the person saw. And there’s no way to search the data. A lab with decades of recordings can’t ask “find the trials where the subject saw a face.”

My idea: embeddings. Instead of storing the raw signal, store an embedding: a short vector that captures the meaning of the data, not its pixels.

The clearest example is faces. Face recognition already works this way. A face gets turned into a vector (a few hundred numbers), and identity lives in the geometry of that space: the same person’s faces land close together, different people land far apart. You never store the photo. You store the embedding, and that tiny vector is enough to recognize, match, or search the face.

Where I want to take it. My idea is that the same trick should work for the “what you saw” signal in a brain recording. If I can map an EEG epoch into a latent space that captures meaning (the kind of space face and image models already live in), then I could:

  • Store it tiny. Keep the compact embedding instead of the full signal.
  • Search it by meaning. Type a word, find the matching recordings, because text and these embeddings can share a space.
  • Compress against meaning, so what survives is what the data is for, not the loudest part of the waveform.

This is the direction I want to take it: treat embeddings as the storage format, the way we already do for faces, and apply it to the brain.

0

Loading discussion…

0
4
Open comments for this post

23m 30s logged

Hackfetch Installs Itself Anywhere

Hackfetch crossed another milestone today: you no longer need Go installed to use it. Or Homebrew. Or anything, really.

The goal was simple: one command, any Linux, any Mac, no prerequisites.

curl -fsSL https://raw.githubusercontent.com/xerneas3318/hackfetch/main/install.sh | sh

Run that on Ubuntu, Fedora, Alpine, Arch, openSUSE, whatever you have, and a few seconds later hackfetch is on your PATH.

Getting the basic installer working was the easy part. Detect your OS, detect your CPU architecture, grab the matching binary from GitHub Releases, drop it in /usr/local/bin. Standard installer stuff.

The harder problem was the script itself failing on some Linuxes.

I’d written the first version in Bash, with set -euo pipefail at the top and $'\033[1m' style escape sequences sprinkled through. Worked great on my Mac. Worked great on Ubuntu. Then I checked which shell Alpine Linux ships by default. Not Bash. The whole script would die on line one for anyone on a minimal container.

So I rewrote it in POSIX sh, which is the one shell every Unix system actually has. No Bash-isms, no fancy quoting, no pipefail. Smaller, dumber, way more portable.

Speaking Seven Package Managers

The next problem: the script needs curl and tar to do its job. If you don’t have them, normally you’d just be stuck.

Instead, the installer now detects your system’s package manager and installs the missing prereqs for you:

  • apt (Debian, Ubuntu)
  • dnf (Fedora, RHEL)
  • yum (CentOS, older RHEL)
  • pacman (Arch)
  • zypper (openSUSE)
  • apk (Alpine)
  • brew (macOS)

They all do the same thing. They all use different words for it. The installer knows all seven.

One line. Any Linux. No prereqs.

0

Loading discussion…

0
6
Open comments for this post

11h 7m 7s logged

Tiny Shakespeare (decoder-only transformer)

Dataset:

  • Tiny Shakespeare, ~1.1M characters
  • vocab 65

Architecture: GPT-style decoder

  • token embedding + learned position embedding (embd=384)
  • 6 transformer blocks, each:
    • multi-head causal self-attention (8 heads, head_size=48)
    • feed-forward (Linear → ReLU → Linear)
    • pre-LayerNorm + residual connections on both sublayers
  • final LayerNorm → linear to vocab
  • block_size=64, dropout=0.2

Training:

  • AdamW, lr=1e-4
  • ExponentialLR, gamma=0.99995
  • batch size 1024
  • 5000 iters
  • CUDA + torch.compile

Results:

  • train loss = 1.26
  • val loss = 1.52

Why it worked:

  • Attention replaces flattening. Instead of mashing all 64 embeddings into one vector, each position attends to the relevant earlier positions directly. Sequence structure is preserved instead of thrown away — the exact failure mode of mlp3.
  • The receptive field is the full block (64 chars) and every position can use all of it, not just a fixed local window.
  • Residual connections + pre-LayerNorm let 6 blocks stack and actually train.
  • Position embeddings give the model order information that a bag-of-embeddings MLP never had.

Against the mlp3 goals:

  • Goal was dev loss < 1.7 → hit 1.52.
  • Goal was “generate actual words and sentences” → it now produces speaker tags, line breaks, and mostly real English words in Shakespearean cadence. It learned the SPEAKER:\n dialogue form like mlp3 did, but this time it fills the dialogue with coherent structure instead of gibberish.

The train/dev gap:

  • 1.26 vs 1.52→ much tighter than mlp3’s 1.12/2.02. Dropout 0.2 + a context long enough to actually be useful means it’s learning real patterns, not memorizing short-range ones.

Notes / loose ends:

  • LR never decays much → gamma=0.99995 over 5000 steps only drops lr from 1e-4 to ~7.8e-5, so the schedule is nearly flat. Loss was still falling at step 5000; more iters or a higher/decaying lr would likely push val below 1.5.

Next:

  • Decay the LR properly (or warmup + cosine) and train longer to close in on ~1.4.
  • Scale block_size for longer context now that attention makes it affordable.
  • Develop gpt-2 (the old sucky model from 2019)
0

Loading discussion…

0
3
Open comments for this post

47m 3s logged

today i learned the difference between margin and padding. profound stuff. life-changing, really.

anyway none of that matters because i put a picture of my friend’s cat on my website and now it’s the best site ever made.

just started webOS development! things i poked at:

  • styled everything neon teal because i just can
  • google fonts (VT323 my beloved)
  • object-fit: cover so the cat doesn’t get crunched into a horror image
  • border-radius so the cat has rounded corners now. very important. mission critical some might say

next time: probably a wallpaper, a window, maybe a clock. or more cats. undecided.

0

Loading discussion…

0
5
Open comments for this post

19m 10s logged

Hackfetch Meets Orpheus!

If you’ve been around Hack Club for more than five minutes, you know Orpheus. The little dinosaur shows up everywhere: stickers,
websites, T-shirts, hackathon merch.

Until today, he wasn’t in hackfetch. That’s been bugging me since v1.0.

The goal was simple: give Orpheus a spot in the logo lineup, the same way flag, bot, and rocket already have one.

hackfetch orpheus

Drawing him was the harder part.

Every logo in hackfetch has to fit inside a fixed width of 33 characters, otherwise the system info column next to it gets pushed off the screen. 33 characters is not a lot of room to draw a recognizable dinosaur, especially one with personality.

I tried him head-on first. It didn’t work. Round dinosaur faces in ASCII end up looking like blobs because you don’t have curves, only corners.

So I redrew him in profile. The result:

  • a snout sticking out to one side
  • one big eye (◉) that catches the light
  • a HACK CLUB body underneath
  • two tiny stubby legs at the bottom

Nine lines tall. No wasted rows.

He plays especially well with the gradient color schemes:

hackfetch orpheus -color forest
hackfetch orpheus -color sunset

Forest makes him look like he’s wandering through tall grass. Sunset gives him a “main character in the closing shot” vibe.

The mascot finally has a seat at the terminal.

Long overdue!

Also if any better artists want to have a crack at it, I’m super open to that, and I can credit you in my repo as a collaborator! THNX!

1

Loading discussion…

0
9
Open comments for this post

4h 44m 56s logged

Hackfetch Can Finally Fetch

Hackfetch crossed a pretty big milestone today: it actually fetches things.

The goal is simple: build a Neofetch-style dashboard for Hack Club.

Run a single command and get a snapshot of your machine alongside your Hack Club activity.

hackfetch

and instantly see information like:

  • OS
  • Hostname
  • Username
  • Shell
  • Terminal
  • Editor
  • Hackatime
  • stats

Getting the system information was the easy part. Go makes it straightforward to grab things like the current user, hostname, operating system, and environment variables.

The harder problem was rendering everything cleanly beside an ASCII logo.

Each logo has different dimensions and line lengths, so I ended up building a small layout engine that calculates the width of every logo row and pads it dynamically before printing the corresponding information. Without that, the text column slowly drifts into the logo and the entire fetch screen looks broken.

Hooking into Hackatime

The more interesting work was integrating with the Hackatime API.Hackfetch reads your API key from:

~/.wakatime.cfg

authenticates with Hackatime, and pulls fresh coding statistics every time you run the command.Right now it can display:

Today’s coding time
Weekly coding time
Current streak
Top project
Most-used language

No browser.

No dashboard.

Just a terminal command.

1

Loading discussion…

0
13
Open comments for this post

27m 3s logged

In honor of pride month, I have added a pride color scheme to my custom hackfetch. It is currently installable via brew. On macs, simply run:

brew install xerneas3318/tap/hackfetch

Currently working on better support for more operating systems. Follow and like to stay updated!

2

Loading discussion…

0
229
Open comments for this post

5h 6m 35s logged

Introducing hackfetch a tiny terminal fetch tool for hackatime. Run hackfetch and get your hours today, weekly total, streak, top project, and top language right in your terminal.

5 logos. 8 color schemes. mix and match:
hackfetch stardance rainbow

How it works: hackfetch reads your hackatime key from ~/.wakatime.cfg, fetches your Hackatime summaries and heartbeats, then renders your stats directly in the terminal.

0

Loading discussion…

0
34
Ship Pending review

Claude Harness that is light enough and not extra enough for daily use. After messing around with openclaw I saw that the costs and features were simply too extra. This is a great life planner that can be run simply even with lower end models like claude haiku.

  • 1 devlog
  • 1h
Try project → See source code →
Open comments for this post

58m 46s logged

What it is
A markdown-only second-brain that Claude Code reads at every session start and edits as you talk to it. Everything lives as plain .md files in a fixed directory tree- no database, no proprietary format.

Two repos, one system

  • brain-template: the harness itself. CLAUDE.md (the session-start instructions Claude reads), a templates/ folder, and a directory skeleton (daily/, backlog/, goals/, notes/, projects/, routines/, memory/, archive/). Drop your real notes in, edit memory/context.md, and Claude becomes a proactive planner.
  • ClaudePlanner: the phone + sync layer on top of the harness. iOS app (SwiftUI) for Today/Browse views with tap-to-toggle, drag reorder, talk-to-Claude with on-device speech. A Node sync-daemon does bidirectional brain/ ↔ Firestore sync. A Fastify relay exposes the Claude Agent SDK with Firebase auth + MCP tools (list_today, read_file, add_task, check_task).

Flow

  1. You write/edit a task in daily/today.md (or tell Claude on phone, or check a box).
  2. sync-daemon mirrors the change to Firestore.
  3. iOS app live-listens and updates instantly.
  4. Closing the loop: when Claude (on phone or terminal) edits files via the relay, sync-daemon writes them back to disk.

Full iOS and server support will be shown soon

0

Loading discussion…

0
22
Open comments for this post

3h 45m 24s logged

makemore — devlog

mlp2-gpu: names MLP

Dataset: Karpathy’s names.txt (32k names, vocab 27)

Architecture:
embed=10 -> flatten -> linear(200) -> tanh -> linear(27)

Training:

  • AdamW, lr=1e-3
  • 200 epochs
  • MPS

Result:
dev loss = 2.20

Samples:
bhuza
fremah
mykeslanna
talee

The model worked because names are short and mostly depend on local character patterns.

mlp3: Tiny Shakespeare (without a guide and with single hidden layer)

Dataset:

  • 1.1M characters
  • vocab 65

Architecture:
embed=32, hidden=400, block_size=16

Training:

  • batch size 8192
  • 600 epochs
  • CUDA

Results:
train loss = 1.12
dev loss = 2.02

Samples:

LERCUTIF:
MARCAPUL:
HENRY:

Why it failed:

  • 16 characters of context is too short for prose.
  • Flattening embeddings throws away sequence structure.
  • The model learned the easiest pattern: SPEAKER:\n dialogue.
  • Large train/dev gap suggests overfitting to short-range patterns.

The model was not too small. It was the wrong architecture.

Next:

WaveNet-style hierarchical MLP from the next lecture.

Instead of flattening all embeddings at once, combine them in stages to preserve locality and expand the receptive field.

Goal:

  • dev loss < 1.7 on Tiny Shakespeare
  • generate actual words and sentences

After that: transformers.

0

Loading discussion…

0
4

Followers

Loading…