Jilai Cheng
Every post, for crawlers and readers without JavaScript.
- Scholarly paper search APIs — 2026-08-20
Twenty-one scholarly search APIs were probed with live requests. Every endpoint and field shape below is the response that came back, not what the documentation
- Nix fixed-output fetches through the HTTP proxy — 2026-08-17
A flake's nix flake check failed downloading two fixed-output sources: musl.libc.org and a repo.or.cz snapshot. The download failed twice: first with a TLS conn
- nix flake check does not run your test apps — 2026-08-17
A workspace's test suites were wired as apps.${system}.test flakes and the gate was nix flake check. Every check was green. Running nix run .#test across the sa
- buildDotnetModule: JSON lockfile and the silent AOT skip — 2026-08-16
nixpkgs buildDotnetModule parses nugetDeps by filename suffix: a .nix path is callPackage'd as Nix code, anything else is lib.importJSON (add-nuget-deps/default
- dotnet: no cargo-style toolchain self-satisfaction — 2026-08-16
Go's GOTOOLCHAIN=auto downloads the go.mod-declared toolchain on demand (go.dev/doc/toolchain). dotnet's global.json pins the SDK version but only selects among
- LoongArch linker relaxation: the pcaddi fold — 2026-08-16
R_LARCH_RELAX is relocation 100 in the LoongArch ELF ABI: Instruction can be relaxed, paired with a normal relocation at the same address. The assembler emits i
- Nix store epoch mtimes defeat mtime-based change detection — 2026-08-16
NixOS deploys a config file with environment.etc as a symlink chain into the Nix store. A switch replaces the target with a new store path whose name embeds the
- TCO: the self-tail-call jmp must precede the param spills — 2026-08-16
Tail-call optimization in a compiler that spills parameters to stack slots: the self-tail-call jmp target must be BEFORE the parameter re-spill block. The body
- VLC 3.0.23 ignores --http-user-agent — 2026-08-16
VLC 3.0.23 sends a hardcoded User-Agent on every HTTP request. --http-user-agent on the command line and http-user-agent= in vlcrc are both ignored. A GET to a
- YouTube timedtext 429 escalates with retries — 2026-08-16
yt-dlp fetches subtitles from youtube.com/api/timedtext. A 429 on that endpoint returns Google's "your computer or network may be sending automated queries" HTM
- A 403 that was a version field, not a block — 2026-08-15
Uploads returned HTTP 403 (出错啦 / 服务器正在休息) from every client and every egress: the campus IP, the lab IP, even a WARP tunnel. It looked like a network block. It
- Blank pages: the shell, not the script — 2026-08-15
A classic script inside <head> executes while the parser is still in the head. document.body is null at that moment; the first document.body.appendChild throws.
- bun --compile binaries in Nix: patch only the interpreter — 2026-08-15
bun build --compile packs the JS runtime and the bundle into one ELF. EYG (Eat Your Greens), a statically typed functional scripting language by Peter Saxton, s
- DeepSeek Harness on NixOS: the bash tool that assumed /bin/bash — 2026-08-15
DeepSeek Harness (dsh) has two model-facing bash tools with different executors. The standard agent preset mounts dsh-tool-bash: each call is a fresh subprocess
- EYG: a typed functional language for makers — 2026-08-15
EYG (Eat Your Greens) is a statically typed functional scripting language by Peter Saxton (CrowdHailer, Gleam contributor). It is implemented in Gleam, Apache-2
- Generations that lie: boot regressions hide under long uptime — 2026-08-15
A one-line change to a boot-time provisioning script broke wifi for 44 generations before anyone noticed. The machine never rebooted. The running system is not
- kotlin-toolchain: Gradle distribution mirror and the 2.3.10 power-assert runtime gap — 2026-08-15
A Gradle Tooling API client downloads the Gradle distribution itself when the connector specifies none. GradleConnector.newConnector().forProjectDirectory(...)
- Mill 1.1 build files: what changed — 2026-08-15
Mill 1.1 build files compile with Scala 3: the mill jars are _3 artifacts, type errors print union types (Seq[mill.PathRef | os.Path]), and macro errors read Ta
- Self-contained Clojure builds with Mill — 2026-08-15
Mill declares its JVM in a .mill-jvm-version file (name:version, e.g. zulu:26), a //| mill-jvm-version build header, or the declarative jvmVersion: key, and pro
- qutebrowser IPC: JSON, not plain text — 2026-08-15
The IPC socket speaks JSON, not plain text. One message is one JSON object: args (each element one command string, colon included), target_arg, version, protoco
- Transcripts bridge what titles can't — 2026-08-15
Scoring candidates by TF-IDF cosine against a corpus of talk titles separated junk from tech, but not desired from boring: a "how to switch to Linux" tutorial s
- ty, the Astral type checker: strict mode without --strict — 2026-08-15
ty 0.0.67 has no --strict flag; ty check --strict fails with unexpected argument. Strictness is configured per rule in [tool.ty.rules] with severities ignore, w
- The stub that broke bilibili transcoding — 2026-08-15
yt-dlp -f "bv*+ba/b" silently fell back to the combined muxed format (18) for one video. Through the proxy egress that format arrived as a 1.5 MB header-only st
- DeepSeek Harness: Everything is a Plugin — 2026-08-14
DeepSeek Harness (dsh) is DeepSeek-AI's open-source agent harness. License: MIT. Version 0.1.0-rc.6, developer preview; the README warns of compatibility-breaki
- Rebuilding git history from per-file change chains — 2026-08-14
A linear history can be rebuilt commit by commit with git commit-tree. The final tree stays byte-identical: every file's last version is the original last versi
- The publication date is a declaration — 2026-08-13
File mtime measures disk writes, not publication. A fresh clone stamps every file with the clone time, so a post from a year ago shows today's mtime. Ordering b
- Identifying pi sessions behind the opaque pi process; the subagent O(n^2) hot path — 2026-07-17
The pi wrapper runs exec -a: every pi process shows cmdline pi (argv: model, session, prompt) is invisible to ps/pgrep. Running several sessions means several i
- pi 0.84.0: sendUserMessage never dispatches extension commands — 2026-07-16
docs/extensions.md and the shipped example examples/extensions/reload-runtime.ts document a tool-to-command handoff for reload: the tool calls pi.sendUserMessag
- pi as a programmable agent: RPC mode and declarative subagents — 2026-07-13
pi is a coding agent that runs headless over a JSON protocol, and it ships no subagents or plan mode: "you can ask pi to build what you want or install a third
- Hyprland 0.56: Lua config, dispatch, and screenshots — 2026-07-05
Hyprland 0.56 configures itself from Lua: the shipped share/hypr/hyprland.lua plus the config deployed with the compositor. hyprctl dispatch wraps its argument
- Codeberg edge drops repeat connections; pacing and the API are stable — 2026-07-02
The first request to codeberg.org succeeds. Repeats within about 40 seconds time out after the TLS handshake with 0 bytes received.
- YouTrack: the REST API takes the SPA's own token — 2026-06-18
JetBrains' kotlin-toolchain routes GitHub issues to YouTrack. Its only issue template is a form whose required checkbox reads "I have read the message and will
- Bilibili video uploads accept a browser session — 2026-06-01
bilibili has two login classes. Web login issues SESSDATA, a cookie. App login issues access_key, a token. The video-submit endpoint x/vu/client/add rejects coo
- A resolver that withholds video sites at night — 2026-05-28
A campus DNS server answered NXDOMAIN for the seven big video sites at night and resolved them again by morning. Control domains always resolved, and direct TCP
- Session cookies carry their own expiry — 2026-05-10
A bilibili login cookie encodes its own deadline. yt-dlp rewrites the cookie file you hand it. The two facts together shape how long a media playback setup stay
- Debugging traps that recur — 2026-03-27
Every one of these started as "my change did nothing" and ended as a two-line explanation. None is exotic; all of them recur. The theme: verify against the runn
- Rotating credentials in a systemd credential store — 2026-03-19
Static secrets need provisioning once. Tokens that expire or get revoked need a refresh loop: a timer re-exports the current bytes from each live source, diffs
- systemd already does what you were about to write — 2026-03-16
Four mechanisms turned out to be systemd builtins: a secret path list, a backlight-restore loop, a wait-online "disable", and a udev RUN+= shell. The rule: ask
- Declarative configuration and secrets pipelines — 2026-03-12
The repo IS the system: services, configs, secrets, even the AI model the coding agent uses are declared, committed, rebuilt. User-state files under the home di
- Title embeddings, not whole content, for topic-level duplicates — 2026-03-05
A blog gate: a new topic that duplicates an existing post's topic must be blocked, and the author updates the existing post instead of creating a new one. The c
- Verifying what you write about software — 2026-02-28
Before writing about a claim, check it against the source. Memory and "everybody knows" are wrong often enough to make this the default workflow. Each claim bel
- Keeping a language model out of your prose — 2026-02-23
A model composing prose adds words that carry no fact: invented reasons, intensifiers, metaphors. Two checks remove them. The first is a deletion test; the seco
- Python set iteration order is seed-dependent — 2026-02-19
Set iteration order derives from element hashes. String hashing is salted per process by PYTHONHASHSEED, so the same set iterates in a different order in every
- Nix strings inside strings — 2026-02-15
A systemd unit needed to run a bash loop. The natural first attempt put the whole one-liner in a double-quoted Nix string and blew up the parse; the fix is Nix'
- Exact config key names and silent ignores — 2026-02-04
Goal: turn off LLMNR and mDNS advertising on a campus network. One line worked, the other vanished, with no error anywhere. Key names are exact in case and spel
- ssh resolves ~ from the passwd database, not $HOME — 2026-01-30
A root systemd unit running an ssh reverse tunnel failed in a restart loop with Host key verification failed (exit 255). The unit set environment.HOME=/home/<us
- How to submit a change to Guix (2026) — 2026-01-24
Since 2026-01-01 Guix accepts pull requests on codeberg.org/guix/guix; the email route (guix-patches@gnu.org) is retired. The GitHub mirror is read-only; GitHub
- kmscon as the console — 2026-01-10
The kernel console could not render bright backgrounds distinctly on the laptop panel. kmscon, a KMS/DRM terminal emulator, replaced it: 256 colors, pango fonts
- HDA codec debugging from userspace — 2025-12-19
A laptop speaker kept playing together with the headphones, and the mixer controls did nothing. Fixing it meant reading the HD-audio codec and driving it with H
- Mic hum: diagnose with a 10-second recording — 2025-12-05
A microphone picks up mains hum. The right fix depends on what the noise is: tonal hum at 50 Hz (China mains) with odd harmonics wants an EQ cut; broadband hiss
- Faster substitutes and package management from China — 2025-11-16
Guix queries substitute servers in order and falls back. Put the fast ones first, keep the official ones as fallback, and prefer API clients over git for repo w
- Guix firmware: why a machine can silently lose its sound card — 2025-11-14
A laptop rebooted into a working system with no sound at all: /proc/asound/cards empty, dmesg showing sof_probe_work failed err: -2 for the Intel audio DSP. The
- guix system reconfigure: what it does and does not do — 2025-09-29
guix system reconfigure is transactional but not a restart: it stages the new system and starts what is missing. The manual says what it does not do, plainly, a
- SSH, keys, and hostnames across machines — 2025-09-09
Three systems on two laptops, one jump host, and a network that renames your computers. All of it declared, none of it hand-edited.
- What happens when a laptop joins a campus/enterprise Wi-Fi — 2025-08-25
A failure that looks like "wifi is broken" lives in one layer of a four-layer stack: the driver owns the radio, wpa_supplicant scans and runs EAP, systemd-netwo
- Shipping your Emacs config as part of the OS — 2025-07-30
An Emacs config that lives in the system repo, pinned per generation, edited like any other system file, with no ~/.emacs.d to maintain.
- Emacs face colors on terminals — 2025-07-22
Goal: one theme that works on the kernel console, on kmscon, and in a GUI. The terminal advertises its colors in three different ways; Emacs builds a different
- The escape key: five layers — 2025-05-09
Goal: make Escape cancel like C-g, make the Windows key Meta, and leave Alt dead. Each attempt failed for a different reason, and each reason is a documented la
- NixOS debugging essentials — 2025-04-28
The flake layout, what switch does, and how the machine gets its name. All of it is declared, none of it is remembered.
- Building this page with DOM, CSSOM, and Houdini — 2024-11-22
Every page has a generated static shell: title, description, canonical, JSON-LD, and two body script tags. common.js builds the DOM and the stylesheet; a per-pa