10 interesting stories served every morning and every evening.
Hi! I’m Eric Wastl. I make Advent of Code. I hope you like it! I also make lots of other things. I’m on Bluesky, Mastodon, and GitHub.
Advent of Code is an Advent calendar of small programming puzzles for a variety of skill levels that can be solved in any programming language you like. People use them as interview prep, company training, university coursework, practice problems, a speed contest, or to challenge each other.
You don’t need a computer science background to participate - just a little programming knowledge and some problem solving skills will get you pretty far. Nor do you need a fancy computer; every problem has a solution that completes in at most 15 seconds on ten-year-old hardware.
If you’d like to support Advent of Code, you can do so indirectly by helping to [Share] it with others or directly via AoC++.
If you get stuck, try your solution against the examples given in the puzzle; you should get the same answers. If not, re-read the description. Did you misunderstand something? Is your program doing something you don’t expect? After the examples work, if your answer still isn’t correct, build some test cases for which you can verify the answer by hand and see if those work with your program. Make sure you have the entire puzzle input. If you’re still stuck, maybe ask a friend for help, or come back to the puzzle later. You can also ask for hints in the subreddit.
Is there an easy way to select entire code blocks? You should be able to triple-click code blocks to select them. You’ll need JavaScript enabled.
#!/usr/bin/env perl
use warnings;
use strict;
print “You can test it out by ”;
print “triple-clicking this code.\n”;
How does authentication work? Advent of Code uses OAuth to confirm your identity through other services. When you log in, you only ever give your credentials to that service - never to Advent of Code. Then, the service you use tells the Advent of Code servers that you’re really you. In general, this reveals no information about you beyond what is already public; here are examples from Reddit and GitHub. Advent of Code will remember your unique ID, names, URL, and image from the service you use to authenticate.
Why was this puzzle so easy / hard? The difficulty and subject matter varies throughout each event. Very generally, the puzzles get more difficult over time, but your specific skillset will make each puzzle significantly easier or harder for you than someone else. Making puzzles is tricky.
Why do the puzzles unlock at midnight EST/UTC-5? Because that’s when I can consistently be available to make sure everything is working. I also have a family, a day job, and even need sleep occasionally. If you can’t participate at midnight, that’s not a problem; if you want to race, many people use private leaderboards to compete with people in their area.
I find the text on the site hard to read. Is there a high contrast mode? There is a high contrast alternate stylesheet. Firefox supports these by default (View -> Page Style -> High Contrast).
I have a puzzle idea! Can I send it to you? Please don’t. Because of legal issues like copyright and attribution, I don’t accept puzzle ideas, and I won’t even read your email if it looks like one just in case I use parts of it by accident.
Did I find a bug with a puzzle? Once a puzzle has been out for even an hour, many people have already solved it; after that point, bugs are very unlikely. Start by asking on the subreddit.
Should I try to get a fast solution time? Maybe. Solving puzzles is hard enough on its own, but trying for a fast time also requires many additional skills and a lot of practice; speed-solves often look nothing like code that would pass a code review. If that sounds interesting, go for it! However, you should do Advent of Code in a way that is useful to you, and so it is completely fine to choose an approach that meets your goals and ignore speed entirely.
Why did the number of days per event change? It takes a ton of my free time every year to run Advent of Code, and building the puzzles accounts for the majority of that time. After keeping a consistent schedule for ten years(!), I needed a change. The puzzles still start on December 1st so that the day numbers make sense (Day 1 = Dec 1), and puzzles come out every day (ending mid-December).
What happened to the global leaderboard? The global leaderboard was one of the largest sources of stress for me, for the infrastructure, and for many users. People took things too seriously, going way outside the spirit of the contest; some people even resorted to things like DDoS attacks. Many people incorrectly concluded that they were somehow worse programmers because their own times didn’t compare. What started as a fun feature in 2015 became an ever-growing problem, and so, after ten years of Advent of Code, I removed the global leaderboard. (However, I’ve made it so you can share a read-only view of your private leaderboard. Please don’t use this feature or data to create a “new” global leaderboard.)
While trying to get a fast time on a private leaderboard, may I use AI / watch streamers / check the solution threads / ask a friend for help / etc? If you are a member of any private leaderboards, you should ask the people that run them what their expectations are of their members. If you don’t agree with those expectations, you should find a new private leaderboard or start your own! Private leaderboards might have rules like maximum runtime, allowed programming language, what time you can first open the puzzle, what tools you can use, or whether you have to wear a silly hat while working.
Should I use AI to solve Advent of Code puzzles? No. If you send a friend to the gym on your behalf, would you expect to get stronger? Advent of Code puzzles are designed to be interesting for humans to solve - no consideration is made for whether AI can or cannot solve a puzzle. If you want practice prompting an AI, there are almost certainly better exercises elsewhere designed with that in mind.
Can I copy/redistribute part of Advent of Code? Please don’t. Advent of Code is free to use, not free to copy. If you’re posting a code repository somewhere, please don’t include parts of Advent of Code like the puzzle text or your inputs. If you’re making a website, please don’t make it look like Advent of Code or name it something similar.
...
Read the original on adventofcode.com »
For those unfamiliar, Zigtools was founded to support the Zig community, especially newcomers, by creating editor tooling such as ZLS, providing building blocks for language servers written in Zig with lsp-kit, working on tools like the Zigtools Playground, and contributing to Zig editor extensions like vscode-zig.
A couple weeks ago, a Zig resource called Zigbook was released with a bold claim of “zero AI” and an original “project-based” structure.
Unfortunately, even a cursory look at the nonsense chapter structure, book content, examples, generic website, or post-backlash issue-disabled repo reveals that the book is wholly LLM slop and the project itself is structured like some sort of sycophantic psy-op, with botted accounts and fake reactions.
We’re leaving out all direct links to Zigbook to not give them any more SEO traction.
We thought that the broad community backlash would be the end of the project, but Zigbook persevered, releasing just last week a brand new feature, a “high-voltage beta” Zig playground.
As we at Zigtools have our own Zig playground (repo, website), our interest was immediately piqued. The form and functionality looked pretty similar and Zigbook even integrated (in a non-functional manner) ZLS into their playground to provide all the fancy editor bells-and-whistles, like code completions and goto definition.
Knowing Zigbook’s history of deception, we immediately investigated the WASM blobs. Unfortunately, the WASM blobs are byte-for-byte identical to ours. This cannot be a coincidence given the two blobs (zig.wasm, a lightly modified version of the Zig compiler, and zls.wasm, ZLS with a modified entry point for WASI) are entirely custom-made for the Zigtools Playground.
We archived the WASM files for your convenience, courtesy of the great Internet Archive:
We proceeded to look at the JavaScript code, which we quickly determined was similarly copied, but with LLM distortions, likely to prevent the code from being completely identical. Still, certain sections were copied one-to-one, like the JavaScript worker data-passing structure and logging (original ZLS playground code, plagiarized Zigbook code).
The following code from both files is identical:
try {
// @ts-ignore
const exitCode = wasi.start(instance);
postMessage({
stderr: `\n\n–-\nexit with exit code ${exitCode}\n–-\n`,
} catch (err) {
postMessage({ stderr: `${err}` });
postMessage({
done: true,
onmessage = (event) => {
if (event.data.run) {
run(event.data.run);
The \n\n–-\nexit with exit code ${exitCode}\n–-\n is perhaps the most obviously copied string.
Funnily enough, despite copying many parts of our code, Zigbook didn’t copy the most important part of the ZLS integration code, the JavaScript ZLS API designed to work with the ZLS WASM binary’s API. That JavaScript code is absolutely required to interact with the ZLS binary which they did plagiarize. Zigbook either avoided copying that JavaScript code because they knew it would be too glaringly obvious, because they fundamentally do not understand how the Zigtools Playground works, or because they plan to copy more of our code.
To be clear, copying our code and WASM blobs is entirely permissible given that the playground and Zig are MIT licensed. Unfortunately, Zigbook has not complied with the terms of the MIT license at all, and seemingly claims the code and blobs as their own without correctly reproducing the license.
We sent Zigbook a neutral PR correcting the license violations, but they quickly closed it and deleted the description, seemingly to hide their misdeeds.
The original description (also available in the “edits” dropdown of the original PR comment) is reproduced below:
We (@zigtools) noticed you were using code from the Zigtools Playground, including byte-by-byte copies of our WASM blobs and excerpts of our JavaScript source code. This is a violation of the MIT license that the Zigtools Playground is licensed under alongside a violation of the Zig MIT license (for the zig.wasm blob).The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
We’ve fixed this by adding the licenses in question to your repository. As your repository does not include a direct link to the *.wasm dependencies, we’ve added a license disclaimer on the playground page as well that mentions the licenses.
Zigbook’s aforementioned bad behavior and their continued violation of our license and unwillingness to fix the violation motivated us to write this blog post.
It’s sad that our first blog post is about the plagiarism of our coolest subproject. We challenged ourselves by creating a WASM-based client-side playground to enable offline usage, code privacy, and no server costs.
This incident has motivated us to invest more time into our playground and has generated a couple of ideas:
* We’d like to enable multifile support to allow more complex Zig projects to be run in the browser
* We’d like to collaborate with fellow Ziguanas to integrate the playground into their excellent Zig tutorials, books, and blogpostsA perfect example usecase would be enabling folks to hop into Ziglings online with the playgroundThe Zig website itself would be a great target as well!
* A perfect example usecase would be enabling folks to hop into Ziglings online with the playground
* The Zig website itself would be a great target as well!
* We’d like to support stack traces using DWARF debug info which is not yet emitted by the self-hosted Zig compiler
As Zig community members, we advise all other members of the Zig community to steer clear of Zigbook.
If you’re looking to learn Zig, we strongly recommend looking at the excellent official Zig learn page which contains excellent resources from the previously mentioned Ziglings to Karl Seguin’s Learning Zig.
We’re also using this opportunity to mention that we’re fundraising to keep ZLS sustainable for our only full-time maintainer, Techatrix. We’d be thrilled if you’d be willing to give just $5 a month. You can check out our OpenCollective or GitHub Sponsors.
...
Read the original on zigtools.org »
- Programming
- Windows
On its own, the title of this post is just a true piece of trivia, verifiable with the built-in subst tool (among other methods).
Here’s an example creating the drive +:\ as an alias for a directory at C:\foo:
subst +: C:\foo
The +:\ drive then works as normal (at least in cmd.exe, this will be discussed more later):
> cd /D +:\
+:\> tree .
Folder PATH listing
Volume serial number is 00000001 12AB:23BC
└───bar
However, understanding why it’s true elucidates a lot about how Windows works under the hood, and turns up a few curious behaviors.
The paths that most people are familiar with are Win32 namespace paths, e.g. something like C:\foo which is a drive-absolute Win32 path. However, the high-level APIs that take Win32 paths like CreateFileW ultimately will convert a path like C:\foo into a NT namespace path before calling into a lower level API within ntdll.dll like NtCreateFile.
This can be confirmed with NtTrace, where a call to CreateFileW with C:\foo ultimately leads to a call of NtCreateFile with \??\C:\foo:
NtCreateFile( FileHandle=0x40c07ff640 [0xb8], DesiredAccess=SYNCHRONIZE|GENERIC_READ|0x80, ObjectAttributes=“\??\C:\foo”, IoStatusBlock=0x40c07ff648 [0/1], AllocationSize=null, FileAttributes=0, ShareAccess=7, CreateDisposition=1, CreateOptions=0x4000, EaBuffer=null, EaLength=0 ) => 0
NtClose( Handle=0xb8 ) => 0
That \??\C:\foo is a NT namespace path, which is what NtCreateFile expects. To understand this path, though, we need to talk about the Object Manager, which is responsible for handling NT paths.
The Object Manager is responsible for keeping track of named objects, which we can explore using the WinObj tool. The \?? part of the \??\C:\foo path is actually a special virtual folder within the Object Manager that combines the \GLOBAL?? folder and a per-user DosDevices folder together.
For me, the object C: is within \GLOBAL??, and is actually a symbolic link to \Device\HarddiskVolume4:
So, \??\C:\foo ultimately resolves to \Device\HarddiskVolume4\foo, and then it’s up to the actual device to deal with the foo part of the path.
The important thing here, though, is that \??\C:\foo is just one way of referring to the device path \Device\HarddiskVolume4\foo. For example, volumes will also get a named object created using their GUID with the format Volume{18123456-abcd-efab-cdef-1234abcdabcd} that is also a symlink to something like \Device\HarddiskVolume4, so a path like \??\Volume{18123456-abcd-efab-cdef-1234abcdabcd}\foo is effectively equivalent to \??\C:\foo.
All this is to say that there’s nothing innately special about the named object C:; the Object Manager treats it just like any other symbolic link and resolves it accordingly.
How I see it, drive letters are essentially just a convention borne out of the conversion of a Win32 path into a NT path. In particular, that would be down to the implementation of RtlDosPathNameToNtPathName_U.
In other words, since RtlDosPathNameToNtPathName_U converts C:\foo to \??\C:\foo, then an object named C: will behave like a drive letter. To give an example of what I mean by that: in an alternate universe, RtlDosPathNameToNtPathName_U could convert the path FOO:\bar to \??\FOO:\bar and then FOO: could behave like a drive letter.
So, getting back to the title, how does RtlDosPathNameToNtPathName_U treat something like +:\foo? Well, exactly the same as C:\foo:
> paths.exe C:\foo
path type: .DriveAbsolute
nt path: \??\C:\foo
> paths.exe +:\foo
path type: .DriveAbsolute
nt path: \??\+:\foo
Therefore, if an object with the name +: is within the virtual folder \??, we can expect the Win32 path +:\ to behave like any other drive-absolute path, which is exactly what we see.
This section only focuses on a few things that were relevant to what I was working on. I encourage others to investigate the implications of this further if they feel so inclined.
Drives with a drive-letter other than A-Z do not appear in File Explorer, and cannot be navigated to in File Explorer.
For the “do not appear” part, my guess as to what’s happening is that explorer.exe is walking \?? and looking specifically for objects named A: through Z:. For the “cannot be navigated to” part, that’s a bit more mysterious, but my guess is that explorer.exe has a lot of special logic around handling paths typed into the location bar, and part of that restricts drive letters to A-Z (i.e. it’s short-circuiting before it ever tries to actually open the path).
PowerShell seems to reject non-A-Z drives as well:
PS C:\> cd +:\
cd : Cannot find drive. A drive with the name ‘+’ does not exist.
At line:1 char:1
+ cd +:\
+ CategoryInfo : ObjectNotFound: (+:String) [Set-Location], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
Drive letters don’t have to be within the ASCII range at all; they can also be non-ASCII characters.
> subst €: C:\foo
> cd /D €:\
€:\> tree .
Folder PATH listing
Volume serial number is 000000DE 12AB:23BC
└───bar
Non-ASCII drive letters are even case-insensitive like A-Z are:
> subst Λ: C:\foo
> cd /D λ:\
λ:\> tree .
Folder PATH listing
Volume serial number is 000000DE 12AB:23BC
λ:\
└───bar
However, drive-letters cannot be arbitrary Unicode graphemes or even arbitrary code points; they are restricted to a single WTF-16 code unit (a u16, so U+FFFF). The tool that we’ve been using so far (subst.exe) errors with Invalid parameter if you try to use a drive letter with a code point larger than U+FFFF, but you can get around that by going through the MountPointManager directly:
However, having the symlink in place doesn’t solve anything on its own:
> cd /D 𤭢:\
The filename, directory name, or volume label syntax is incorrect.
This is because there’s no way to get the drive-absolute Win32 path 𤭢:\ to end up as the relevant NT path. As mentioned earlier, the behavior of RtlDosPathNameToNtPathName_U is what matters, and we can verify that it will not convert a drive-absolute path with a drive letter bigger than U+FFFF to the relevant NT path:
C:\foo> paths.exe 𤭢:\foo
path type: .Relative
nt path: \??\C:\foo\𤭢:\foo
It’s very common for path-related functions to be written without the use of system-specific APIs, which means that there’s high potential for a mismatch between how RtlDosPathNameToNtPathName_U treats a file path and how something like a particular implementation of path.isAbsolute treats a file path.
As a random example, Rust only considers paths with A-Z drive letters as absolute:
use std::path::Path;
fn main() {
println!(“C:\\ {}”, Path::new(“C:\\foo”).is_absolute());
println!(“+:\\ {}”, Path::new(“+:\\foo”).is_absolute());
println!(“€:\\ {}”, Path::new(“€:\\foo”).is_absolute());
> rustc test.rs
> test.exe
C:\ true
+:\ false
€:\ false
Whether or not this represents a problem worth fixing is left as an exercise for the reader (I genuinely don’t know if it is a problem), but there’s a second wrinkle (hinted at previously) involving text encoding that can make something like an isAbsolute implementation return different results for the same path. This wrinkle is the reason I looked into this whole thing in the first place, as when I was doing some work on Zig’s path-related functions recently I realized that looking at path[0], path[1], and path[2] for a pattern like C:\ will look at different parts of the path depending on the encoding. That is, for something like €:\ (which is made up of the code points ):
* Encoded as WTF-16 where U+20AC can be encoded as the single u16 code unit 0x20AC, that’d mean path[0] will be 0x20AC, path[1] will be 0x3A (:), and path[2] will be 0x5C (\), which looks like a drive-absolute path
* Encoded as WTF-8 where U+20AC is encoded as three u8 code units (0xE2 0x82 0xAC), that’d mean path[0] will be 0xE2, path[1] will be 0x82, and path[2] will be 0xAC, meaning it will look nothing like a drive-absolute path
So, to write an implementation that treats paths the same regardless of encoding, some decision has to be made:
* If strict compatibility with RtlDetermineDosPathNameType_U/RtlDosPathNameToNtPathName_U is desired, decode the first code point and check for when dealing with WTF-8 (this is the option I went with for the Zig standard library, but I’m not super happy about it)
* If you want to be able to always check path[0]/path[1]/path[2] and don’t care about non-ASCII drive letters, check for path[0] regardless of encoding
* If you don’t care about anything other than the standard A-Z drive letters, then check for that explicitly (this is what Rust does)
Something bizarre that I found with this whole thing is that the kernel32.dll API SetVolumeMountPointW has it’s own unique quirk when dealing with non-ASCII drive letters. Specifically, this code (attempting to create the drive €:\) will succeed:
const std = @import(“std”);
const windows = std.os.windows;
const L = std.unicode.wtf8ToWtf16LeStringLiteral;
extern “kernel32” fn SetVolumeMountPointW(
VolumeMountPoint: windows.LPCWSTR,
VolumeName: windows.LPCWSTR,
) callconv(.winapi) windows.BOOL;
pub fn main() !void {
const volume_name = L(“\\\\?\\Volume{18123456-abcd-efab-cdef-1234abcdabcd}\");
const mount_point = L(“€:\");
if (SetVolumeMountPointW(mount_point, volume_name) == 0) {
const err = windows.GetLastError();
std.debug.print(“{any}\n”, .{err});
return error.Failed;
However, when we look at the Object Manager, the €: symlink won’t exist… but ¬: will:
...
Read the original on www.ryanliptak.com »
AI is being done wrong.
It’s being pushed down our throats. It’s in our search bars, our operating systems, and even our creative tools, whether we asked for it or not. It feels less like an upgrade and more like a force-feeding.
It doesn’t need to be this way. Technology can be adopted slowly. Organically. One piece at a time.
Right now, the frantic pace of deployment isn’t about utility; it’s about liquidity. It’s being shoved down our throats because some billionaires need to make some more billions before they die.
We don’t owe them anything.
It is time to do AI the right way. The honeymoon phase of the hype cycle is over. We now know the limitations. We see the hallucinations. We see the errors. Let’s pick the things which work and slowly integrate it into our lives. We don’t need to do it this quarter just because some startup has to do an earnings call. We will do it if it helps us.
And let’s be clear: We don’t need AGI (Artificial General Intelligence). We don’t need a digital god. We just need software that works.
If the current models don’t work? No problem. Let the researchers go back to the lab and do their jobs. We will continue doing ours. We might even generate more data for them in the process—but this time, we do it correctly. We will work with the creators, writers, and artists, instead of ripping off their life’s work to feed the model.
I hear the complaints from the tech giants already: “But we bought too many GPUs! We spent billions on infrastructure! They have to be put to work!”
I will use what creates value for me. I will not buy anything that is of no use to me.
There are plenty of legitimate use cases for AI and enough places to make money without force-feeding the market. But I will not allow AI to be pushed down my throat just to justify your bad investment.
...
Read the original on gpt3experiments.substack.com »
Norway’s $2 trillion wealth fund said on Sunday it would vote for a shareholder proposal at the upcoming Microsoft annual general meeting requiring for a report on the risks of operating in countries with significant human rights concerns.
Microsoft management had recommended shareholders voted against the motion.
The fund also said it would vote against the re-appointment of CEO Satya Nadella as chair of the board, as well as against his pay package.
The fund owned a 1.35% stake worth $50 billion in the company as of June 30, according to fund data, making it the fund’s second-largest equity holding overall, after Nvidia.
It is Microsoft’s eighth-largest shareholder, according to LSEG data.
Investors in the U. S. tech company will decide whether to ratify the proposed motions at the AGM on Dec. 5.
...
Read the original on www.cnbc.com »
Note: this post is also applicable to AGENTS.md, the open-source equivalent of CLAUDE.md for agents and harnesses like OpenCode, Zed, Cursor and Codex.
LLMs are stateless functions. Their weights are frozen by the time they’re used for inference, so they don’t learn over time. The only thing that the model knows about your codebase is the tokens you put into it.
Similarly, coding agent harnesses such as Claude Code usually require you to manage agents’ memory explicitly. CLAUDE.md (or AGENTS.md) is the only file that by default goes into every single conversation you have with the agent.
This has three important implications:
Coding agents know absolutely nothing about your codebase at the beginning of each session.
The agent must be told anything that’s important to know about your codebase each time you start a session.
CLAUDE.md is the preferred way of doing this.
Since Claude doesn’t know anything about your codebase at the beginning of each session, you should use CLAUDE.md to onboard Claude into your codebase. At a high level, this means it should cover:
WHAT: tell Claude about the tech, your stack, the project structure. Give Claude a map of the codebase. This is especially important in monorepos! Tell Claude what the apps are, what the shared packages are, and what everything is for so that it knows where to look for things
WHY: tell Claude the purpose of the project and what everything is doing in the repository. What are the purpose and function of the different parts of the project?
HOW: tell Claude how it should work on the project. For example, do you use bun instead of node? You want to include all the information it needs to actually do meaningful work on the project. How can Claude verify Claude’s changes? How can it run tests, typechecks, and compilation steps?
But the way you do this is important! Don’t try to stuff every command Claude could possibly need to run in your CLAUDE.md file - you will get sub-optimal results.
Regardless of which model you’re using, you may notice that Claude frequently ignores your CLAUDE.md file’s contents.
You can investigate this yourself by putting a logging proxy between the claude code CLI and the Anthropic API using ANTHROPIC_BASE_URL. Claude code injects the following system reminder with your CLAUDE.md file in the user message to the agent:
IMPORTANT: this context may or may not be relevant to your tasks.
You should not respond to this context unless it is highly relevant to your task.
As a result, Claude will ignore the contents of your CLAUDE.md if it decides that it is not relevant to its current task. The more information you have in the file that’s not universally applicable to the tasks you have it working on, the more likely it is that Claude will ignore your instructions in the file.
Why did Anthropic add this? It’s hard to say for sure, but we can speculate a bit. Most CLAUDE.md files we come across include a bunch of instructions in the file that aren’t broadly applicable. Many users treat the file as a way to add “hotfixes” to behavior they didn’t like by appending lots of instructions that weren’t necessarily broadly applicable.
We can only assume that the Claude Code team found that by telling Claude to ignore the bad instructions, the harness actually produced better results.
The following section provides a number of recommendations on how to write a good CLAUDE.md file following context engineering best practices.
Your mileage may vary. Not all of these rules are necessarily optimal for every setup. Like anything else, feel free to break the rules once…
you understand when & why it’s okay to break them
you have a good reason to do so
### Less (instructions) is more
It can be tempting to try and stuff every single command that claude could possibly need to run, as well as your code standards and style guidelines into CLAUDE.md. We recommend against this.
Though the topic hasn’t been investigated in an incredibly rigorous manner, some research has been done which indicates the following:
Frontier thinking LLMs can follow ~ 150-200 instructions with reasonable consistency. Smaller models can attend to fewer instructions than larger models, and non-thinking models can attend to fewer instructions than thinking models.
Smaller models get MUCH worse, MUCH more quickly. Specifically, smaller models tend to exhibit an expotential decay in instruction-following performance as the number of instructions increase, whereas larger frontier thinking models exhibit a linear decay (see below). For this reason, we recommend against using smaller models for multi-step tasks or complicated implementation plans.
LLMs bias towards instructions that are on the peripheries of the prompt: at the very beginning (the Claude Code system message and CLAUDE.md), and at the very end (the most-recent user messages)
As instruction count increases, instruction-following quality decreases uniformly. This means that as you give the LLM more instructions, it doesn’t simply ignore the newer (“further down in the file”) instructions - it begins to ignore all of them uniformly
Our analysis of the Claude Code harness indicates that Claude Code’s system prompt contains ~50 individual instructions. Depending on the model you’re using, that’s nearly a third of the instructions your agent can reliably follow already - and that’s before rules, plugins, skills, or user messages.
This implies that your CLAUDE.md file should contain as few instructions as possible - ideally only ones which are universally applicable to your task.
All else being equal, an LLM will perform better on a task when its’ context window is full of focused, relevant context including examples, related files, tool calls, and tool results compared to when its context window has a lot of irrelevant context.
Since CLAUDE.md goes into every single session, you should ensure that its contents are as universally applicable as possible.
For example, avoid including instructions about (for example) how to structure a new database schema - this won’t matter and will distract the model when you’re working on something else that’s unrelated!
Length-wise, the less is more principle applies as well. While Anthropic does not have an official recommendation on how long your CLAUDE.md file should be, general consensus is that < 300 lines is best, and shorter is even better.
At HumanLayer, our root CLAUDE.md file is less than sixty lines.
Writing a concise CLAUDE.md file that covers everything you want Claude to know can be challenging, especially in larger projects.
To address this, we can leverage the principle of Progressive Disclosure to ensure that claude only sees task- or project-specific instructions when it needs them.
Instead of including all your different instructions about building your project, running tests, code conventions, or other important context in your CLAUDE.md file, we recommend keeping task-specific instructions in separate markdown files with self-descriptive names somewhere in your project.
agent_docs/
|- building_the_project.md
|- running_tests.md
|- code_conventions.md
|- service_architecture.md
|- database_schema.md
|- service_communication_patterns.md
Then, in your CLAUDE.md file, you can include a list of these files with a brief description of each, and instruct Claude to decide which (if any) are relevant and to read them before it starts working. Or, ask Claude to present you with the files it wants to read for aproval first before reading them.
Prefer pointers to copies. Don’t include code snippets in these files if possible - they will become out-of-date quickly. Instead, include file:line references to point Claude to the authoritative context.
Conceptually, this is very similar to how Claude Skills are intended to work, although skills are more focused on tool use than instructions.
### Claude is (not) an expensive linter
One of the most common things that we see people put in their CLAUDE.md file is code style guidelines. Never send an LLM to do a linter’s job. LLMs are comparably expensive and incredibly slow compared to traditional linters and formatters. We think you should always use deterministic tools whenever you can.
Code style guidelines will inevitably add a bunch of instructions and mostly-irrelevant code snippets into your context window, degrading your LLM’s performance and instruction-following and eating up your context window.
LLMs are in-context learners! If your code follows a certain set of style guidelines or patterns, you should find that armed with a few searches of your codebase (or a good research document!) your agent should tend to follow existing code patterns and conventions without being told to.
If you feel very stronly about this, you might even consider setting up a Claude Code Stop hook that runs your formatter & linter and presents errors to Claude for it to fix. Don’t make Claude find the formatting issues itself.
Bonus points: use a linter that can automatically fix issues (we like Biome), and carefully tune your rules about what can safely be auto-fixed for maximum (safe) coverage.
You could also create a Slash Command that includes your code guidelines and which points claude at the changes in version control, or at your git status, or similar. This way, you can handle implementation and formatting separately. You will see better results with both as a result.
### Don’t use /init or auto-generate your CLAUDE.md
Both Claude Code and other harnesses with OpenCode come with ways to auto-generate your CLAUDE.md file (or AGENTS.md).
Because CLAUDE.md goes into every single session with Claude code, it is one of the highest leverage points of the harness - for better or for worse, depending on how you use it.
A bad line of code is a bad line of code. A bad line of an implementation plan has the potential to create a lot of bad lines of code. A bad line of a research that misunderstands how the system works has the potential to result in a lot of bad lines in the plan, and therefore a lot more bad lines of code as a result.
But the CLAUDE.md file affects every single phase of your workflow and every single artifact produced by it. As a result, we think you should spend some time thinking very carefully about every single line that goes into it:
CLAUDE.md is for onboarding Claude into your codebase. It should define your project’s WHY, WHAT, and HOW.
Less (instructions) is more. While you shouldn’t omit necessary instructions, you should include as few instructions as reasonably possible in the file.
Keep the contents of your CLAUDE.md concise and universally applicable.
Use Progressive Disclosure - don’t tell Claude all the information you could possibly want it to know. Rather, tell it how to find important information so that it can find and use it, but only when it needs to to avoid bloating your context window or instruction count.
Claude is not a linter. Use linters and code formatters, and use other features like Hooks and Slash Commands as necessary.
CLAUDE.md is the highest leverage point of the harness, so avoid auto-generating it. You should carefully craft its contents for best results.
...
Read the original on www.humanlayer.dev »
I would like to migrate the Dillo project away from
GitHub
into a new home which is more friendly to be used with Dillo and solves some of its problems. This page summarizes the current situation with GitHub and why I decided to move away from it into a self-hosted server with multiple mirrors in other forges.
Before we dive into the details, I would like to briefly mention what happened with the old site. The original Dillo website was at dillo.org, which also had the source code of Dillo in a mercurial repository at hg.dillo.org. But it also included the mail server used to reach the developers, a bug tracker and archives for the mailing list. However, in 2022
the domain was lost and someone else decided to buy it to put a similar site but plaged with AI generated ads. The original developers are no longer active, but luckily I had a copy of the mercurial repository and with some help I was able to recover a lot of material from the original server (some parts are still missing to this day).
I want to avoid this situation as much as possible, so we cannot rely on a single site that can go down and the whole project become lost. Initially, I uploaded the Dillo source and website to git repositories on GitHub, but I no longer think this is a good idea.
GitHub has been useful to store all repositories of the Dillo project, as well as to run the CI workflows for platforms in which I don’t have a machine available (like Windows, Mac OS or some BSDs).
However, it has several problems that make it less suitable to develop Dillo anymore. The most annoying problem is that the frontend barely works without JavaScript, so we cannot open issues, pull requests, source code or CI logs in Dillo itself, despite them being mostly plain HTML, which I don’t think is acceptable. In the past, it used to gracefully degrade without enforcing JavaScript, but now it doesn’t. Additionally, the page is very resource hungry, which I don’t think is needed to render mostly static text.
Another big problem is that it is a single point of failure. I don’t mean that GitHub is stored in a single machine, but it is controlled by a single entity which can unilateraly ban our repository or account and we would lose the ability to notify in that URL what happened. This can cause data loss if we don’t have a local copy of all the data.
On the usability side, the platform has become more and more slow over time, which is affecting the development process. It also requires you to have a fast Internet connection at all times, which is not the case for me sometimes. Additionally, GitHub seems to encourage a “push model” in which you are notified when a new event occurs in your project(s), but I don’t want to work with that model. Instead, I prefer it to work as a “pull model”, so I only get updates when I specifically look for them. This model would also allow me to easily work offline. Unfortunately, I see that the same push model has been copied to alternative forges.
On the social side, I feel that it doesn’t have the right tools to moderate users, specially for projects where the ratio of non-technical users to developers is high. This is specially problematic when active issues with developer notes begin to be filled with comments from users that have never contributed to the project and usually do more harm than good. This situation ends up causing burnout in developers.
Lastly, GitHub seem to follow the current trend of over-focusing on LLMs and generative AI, which are destroying the open web (or what remains of it) among
other
problems. It has a direct impact on us because sites protect themseves with a JavaScript wall (or worse, browser fingerprinting) to prevent aggresive LLM crawler bots from overloading the site, but they also leave Dillo users out. So I would prefer not to encourage this trend. Despite my intentions, moving Dillo away won’t change much their capability to train their model with our code, but at least I won’t be actively helping.
After researching the available options, it seems that none of the current forges would allow us to have a redundant system that can prevent the forge from becoming a single point of failure and solve the rest of the problems with GitHub. Therefore, I decided to self-host Dillo myself, move all important data to git repositories and keep them synchronized in multiple git mirrors.
I decided to buy the dillo-browser.org domain name and setup a very small VPS. Initially, I was very skeptical that it would be able to survive on today’s web, but it seems to be doing an acceptable job at handling it (mostly AI bot traffic masquerading as users). The Dillo website is available here:
I researched which git frontends may suit our needs, and I discovered that most options are very complicated to self-host and require a lot of server resources and JavaScript on the frontend. I ended up testing cgit, which is written in C and it seems to be very lightweight both on RAM and CPU usage. Furthermore, the web frontend doesn’t require JS, so I can use it from Dillo (I modified cgit CSS slightly to work well on Dillo). It is available on this URL:
Regarding the bug tracker, I also took a look at the available options. They are all too complicated for what I would like to have and they seem to centralize the data into a database that can get lost. This is precisely the case that happened with the old dillo bug tracker and we are still unable to recover the original bug entries.
To avoid this problem, I created my own bug tracker software,
buggy, which is a very simple C tool that parses plain Markdown files and creates a single HTML page for each bug. All bugs are stored in a
git repository
and a git hook regenerates the bug pages and the index on each new commit. As it is simply plain text, I can edit the bugs locally and only push them to the remote when I have Internet back, so it works nice offline. Also, as the output is just an static HTML site, I don’t need to worry about having any vulnerabilities in my code, as it will only run at build time. You can see it live here, with the exported issues from GitHub:
The mailing list archives are stored by three independent external services, but I might include a copy with our own archives in the future.
As all the important data is now stored in git repositories, we can mirror them in any forge, without having to rely on their custom storage format for the issues or other data. If a forge goes down (or goes rogue) we can simply switch to another site with low switching cost. To this end, I have created git mirrors in Codeberg and Sourcehut that are synced with our git server:
However, we still have a single point of failure: the DNS entry of the dillo-browser.org domain. If we lose the DNS entry (like with dillo.org) it would cause a problem as all services will be unreachable. We could recover from such situation by relying on alternative ways to reach users, by the mailing list, fediverse or IRC, as well as updating the mirrors to reflect the current situation. It is not ideal, but I don’t think it would cause a catastrophic data loss (like it happened before) as all the data is now stored in git and replicated across independent locations.
In order for this page to have some authority, the HTML file is signed with my GPG key
(32E65EC501A1B6FDF8190D293EE6BA977EB2A253), which is the same that I use to sign the last releases of Dillo and is also listed in my GitHub user. The signature is available here and is linked to the page with the tag using the rel=signature
relation. You can find more information and how to verify the signature in the
Dillo RFC-006.
Using OpenPGP signatures is robust against losing the DNS entry, as the authority is not given by the TLS certificate chain but by the trust in the OpenPGP signature, so we could move the site elsewhere and still claim that is owned by us. Additionally, as we can store the signatures inside all git mirrors, they are also resilient against data loss.
Keep in mind that the migration process requires several moving parts and it will take a while for it to stabilize (switching costs). The GitHub
repositories won’t be removed at any point in time and they will continue to
be updated until we finish the migration. When the migration process is completed, I will mark the Dillo repositories as archived and properly comunicate it in our site. It is important that we don’t remove any commit or tarball release to avoid breaking downstream builds that still rely on the GitHub URL.
Lastly, I’m glad that we can have our own fully independent and self-hosted site with relatively low expenses and very little energy cost (which is good for the environment, but probably not even noticeable at large scale). With the current DNS and server costs and our current donations I consider that it is likely that we can continue covering the expenses for at least the next 3 years in the worst case scenario. If you are interested in keeping us afloat, you can help via Liberapay.
...
Read the original on dillo-browser.org »
CachyOS is designed to deliver lightning-fast speeds and stability, ensuring a smooth and enjoyable computing experience every time you use it. Whether you’re a seasoned Linux user or just starting out, CachyOS is the ideal choice for those looking for a powerful, customizable and blazingly fast operating system.
Blazingly Fast & Customizable
Linux distribution CachyOS is designed to deliver lightning-fast speeds and stability, ensuring a smooth and enjoyable computing experience every time you use it. Whether you’re a seasoned Linux user or just starting out, CachyOS is the ideal choice for those looking for a powerful, customizable and blazingly fast operating system.
Download
Learn more
CachyOS is designed to deliver lightning-fast speeds and stability, ensuring a smooth and enjoyable computing experience every time you use it. Whether you’re a seasoned Linux user or just starting out, CachyOS is the ideal choice for those looking for a powerful, customizable and blazingly fast operating system.
Blazingly Fast & Customizable
Linux distribution CachyOS is designed to deliver lightning-fast speeds and stability, ensuring a smooth and enjoyable computing experience every time you use it. Whether you’re a seasoned Linux user or just starting out, CachyOS is the ideal choice for those looking for a powerful, customizable and blazingly fast operating system.
Download
Learn more
Experience Cutting-Edge Linux Performance with CachyOS - A distribution built on Arch Linux, CachyOS features the optimized linux-cachyos kernel utilizing the advanced BORE Scheduler for unparalleled performance.
CachyOS does compile packages with the x86-64-v3, x86-64-v4 and Zen4 instruction set and LTO to provide a higher performance. Core packages also get PGO or BOLT optimization. CachyOS offers a variety of popular Desktop Environments, Wayland Compositors and X11 Window Managers including KDE Plasma, GNOME, XFCE, i3, Wayfire, LXQt, Openbox, Cinnamon, COSMIC, UKUI, LXDE, Mate, Budgie, Qtile, Hyprland, Sway and Niri. Select your preferred environment during the online installation process. CachyOS offers a choice of two installers to fit your needs: a user-friendly GUI version based on Calamares, and a CLI-based option for those who prefer a streamlined, non-graphical installation experience. Power Up Your Computing with Robust Kernel Support CachyOS utilizes the BORE Scheduler for better interactivity, and offers a variety of scheduler options including EEVDF, sched-ext, ECHO, and RT. All kernels are compiled with optimized x86-64-v3, x86-64-v4, Zen4 instructions and LTO to be optimized for your CPU.
...
Read the original on cachyos.org »
This note is to be removed before publishing as an RFC.¶
Discussion of this draft takes place on the HTTP working group mailing list (ietf-http-wg@w3.org), which is archived at https://lists.w3.org/Archives/Public/ietf-http-wg/.¶
Working Group information can be found at https://httpwg.org/; source code and issues list for this draft can be found at https://github.com/httpwg/http-extensions/labels/query-method.¶
The changes in this draft are summarized in Appendix C.14.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as “work in progress.“¶
This Internet-Draft will expire on 22 May 2026.¶
Copyright (c) 2025 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust’s Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
This specification defines the HTTP QUERY request method as a means of making a safe, idempotent request (Section 9.2 of [HTTP]) that encloses a representation describing how the request is to be processed by the target resource.¶
However, when the data conveyed is too voluminous to be encoded in the request’s URI, this pattern becomes problematic:¶
* often size limits are not known ahead of time because a request can pass through many uncoordinated
systems (but note that recommends senders and recipients to support at least 8000 octets),¶
* expressing certain kinds of data in the target URI is inefficient because of the overhead of encoding that data into a valid URI,¶
* request URIs are more likely to be logged than request content, and may also turn up in bookmarks,¶
* encoding queries directly into the request URI effectively casts every possible combination of query inputs as distinct
resources.¶
As an alternative to using GET, many implementations make use of the HTTP POST method to perform queries, as illustrated in the example below. In this case, the input to the query operation is passed as the request content as opposed to using the request URI’s query component.¶
A typical use of HTTP POST for requesting a query is:¶
In this variation, however, it is not readily apparent — absent specific knowledge of the resource and server to which the request is being sent — that a safe, idempotent query is being performed.¶
The QUERY method provides a solution that spans the gap between the use of GET and POST, with the example above being expressed as:¶
As with POST, the input to the query operation is passed as the content of the request rather than as part of the request URI. Unlike POST, however, the method is explicitly safe and idempotent, allowing functions like caching and automatic retries to operate.¶
Recognizing the design principle that any important resource ought to be identified by a URI, this specification describes how a server can assign URIs to both the query itself or a specific query result, for later use in a GET request.¶
The QUERY method is used to initiate a server-side query. Unlike the GET method, which requests a representation of the resource identified by the target URI (as defined by Section 7.1 of [HTTP]), the QUERY method is used to ask the target resource to perform a query operation within the scope of that target resource.¶
The content of the request and its media type define the query. The origin server determines the scope of the operation based on the target resource.¶
Servers MUST fail the request if the Content-Type request field ([HTTP], Section 8.3) is missing or is inconsistent with the request content.¶
As for all HTTP methods, the target URI’s query part takes part in identifying the resource being queried. Whether and how it directly affects the result of the query is specific to the resource and out of scope for this specification.¶
QUERY requests are safe with regard to the target resource ([HTTP], Section 9.2.1) — that is, the client does not request or expect any change to the state of the target resource. This does not prevent the server from creating additional HTTP resources through which additional information can be retrieved (see Sections 2.3
and 2.4).¶
Furthermore, QUERY requests are idempotent ([HTTP], Section 9.2.2) — they can be retried or repeated when needed, for instance after a connection failure.¶
As per Section 15.3 of [HTTP], a 2xx (Successful) response code signals that the request was successfully received, understood, and accepted.¶
In particular, a 200 (OK) response indicates that the query was successfully processed and the results of that processing are enclosed as the response content.¶
The “Accept-Query” response header field can be used by a resource to directly signal support for the QUERY method while identifying the specific query format media type(s) that may be used.¶
Accept-Query contains a list of media ranges (Section 12.5.1 of [HTTP]) using “Structured Fields” syntax ([STRUCTURED-FIELDS]). Media ranges are represented by a List Structured Header Field of either Tokens or Strings, containing the media range value without parameters.¶
Media type parameters, if any, are mapped to Structured Field Parameters of type String or Token. The choice of Token vs. String is semantically insignificant. That is, recipients MAY convert Tokens to Strings, but MUST NOT process them differently based on the received type.¶
Media types do not exactly map to Tokens, for instance they allow a leading digit. In cases like these, the String format needs to be used.¶
The only supported uses of wildcards are “*/*”, which matches any type, or “xxxx/*”, which matches any subtype of the indicated type.¶
The order of types listed in the field value is not significant.¶
The value of the Accept-Query field applies to every URI on the server that shares the same path; in other words, the query component is ignored. If requests to the same resource return different Accept-Query values, the most recently received fresh value (per Section 4.2 of [HTTP-CACHING]) is used.¶
Although the syntax for this field appears to be similar to other fields, such as “Accept” (Section 12.5.1 of [HTTP]), it is a Structured Field and thus MUST be processed as specified in Section 4 of [STRUCTURED-FIELDS].¶
The QUERY method is subject to the same general security considerations as all HTTP methods as described in [HTTP].¶
It can be used as an alternative to passing request information in the URI (e.g., in the query component). This is preferred in some cases, as the URI is more likely to be logged or otherwise processed by intermediaries than the request content. In other cases, where the query contains sensitive information, the potential for logging of the URI might motivate the use of QUERY over GET.¶
If a server creates a temporary resource to represent the results of a QUERY request (e.g., for use in the Location or Content-Location field), assigns a URI to that resource, and the request contains sensitive information that cannot be logged, then that URI SHOULD be chosen such that it does not include any sensitive portions of the original request content.¶
Caches that normalize QUERY content incorrectly or in ways that are significantly different from how the resource processes the content can return an incorrect response if normalization results in a false positive.¶
A QUERY request from user agents implementing CORS (Cross-Origin Resource Sharing) will require a “preflight” request, as QUERY does not belong to the set of CORS-safelisted methods (see “Methods” in [FETCH]).¶
The examples below are for illustrative purposes only; if one needs to send queries that are actually this short, it is likely better to use GET.¶
The media type used in most examples is “application/x-www-form-urlencoded” (as used in POST requests from browser user clients, defined in “application/x-www-form-urlencoded” in [URL]). The Content-Length fields have been omitted for brevity.¶
The HTTP Method Registry (http://www.iana.org/assignments/http-methods) already contains three other methods with the properties “safe” and “idempotent”: “PROPFIND” ([RFC4918]), REPORT” ([RFC3253]), and “SEARCH” ([RFC5323]).¶
It would have been possible to re-use any of these, updating it in a way that it matches what this specification defines as the new method “QUERY”. Indeed, the early stages of this specification used “SEARCH”.¶
The method name “QUERY” ultimately was chosen because:¶
* The alternatives use a generic media type for the request content (“application/xml”); the
semantics of the request depends solely on the request content.¶
* Furthermore, they all originate from the WebDAV activity, about which many have mixed feelings.¶
* “QUERY” captures the relation with the URI’s query component well.¶
This section is to be removed before publishing as an RFC.¶
We thank all members of the HTTP Working Group for ideas, reviews, and feedback.¶
The following individuals deserve special recognition: Carsten Bormann, Mark Nottingham, Martin Thomson, Michael Thornburgh, Roberto Polli, Roy Fielding, and Will Hawkins.¶
Ashok Malhotra participated in early discussions leading to this specification:¶
Discussion on the this HTTP method was reopened by Asbjørn Ulsberg during the HTTP Workshop in 2019:¶
...
Read the original on www.ietf.org »
To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".
10HN is also available as an iOS App
If you visit 10HN only rarely, check out the the best articles from the past week.
If you like 10HN please leave feedback and share
Visit pancik.com for more.