10 Days, 46 Releases, and Four AI Subscriptions: AhdCode v1.0.0

When I wrote the first AhdCode post, I explained how the project had started. I talked about how, while joking around about something, I somehow ended up starting to write my own programming language, the first design decisions I made, and the structure that emerged within just a few days.

Only about ten days have passed since then.

Looking back now, I realize that even when I wrote that first post, I had no idea just how early I still was in the story.

Because AhdCode's first ten days ended up involving a few dangerous questions, thousands of answers, more tokens than I eventually stopped trying to count, four different AI subscriptions, two ChatGPT conversations that are almost completely full, and finally 46 releases (AHD translation: published versions of the project).

And today, what I have in front of me is:

AhdCode v1.0.0

And when I put the goals I had on the very first night next to the system that actually works today, the surprising part is not simply how quickly the version number moved.

A significant portion of the things I originally talked about as:

“Could we maybe make this possible someday?”

are now genuinely part of the language.

A small note: Naturally, this post contains quite a lot of software and programming-language terminology. To avoid drowning the article in technical detail, I have left short “AHD translations” in parentheses where I thought they would help. They are not meant to be perfect dictionary definitions; they only need to quickly explain what I mean in that particular sentence.

It All Started with a Few Dangerous Questions

When I went back and looked at the actual conversation history, I realized that things had developed even faster than I remembered.

August 27, 9:15 PM.

The question I asked was roughly:

“Are there really a million people in the world who know enough software development to write a programming language from scratch without AI?”

Under normal circumstances, that is the kind of question people discuss for a while, throw around a few opinions about, and then move on from.

I did not move on.

9:23 PM.

Eight minutes later:

“If we created a language called AhdCode, how long would that project take?”

Then the night moved on through questions like whether we should use C or Go, how the compiler (AHD translation: the part that turns source code into something executable) should work, what the web side should look like, and whether AhdCode should produce native executables (AHD translation: programs the operating system can run directly).

One of the first ideas was to translate AhdCode source code into C and leave the rest to existing tools such as clang or gcc. That way, we would not have to deal from day one with directly producing machine code, register allocation (AHD translation: deciding which values get to use the processor's limited registers), different processor architectures, or an optimizer (AHD translation: the layer that tries to make generated code more efficient).

But my actual goal was not a small toy for experimenting with compiler theory.

What I wanted was closer to this:

I wanted to run my own language from the terminal; I wanted it to be able to start its own local server (AHD translation: a web server running on my own computer), connect to MySQL, work together with HTML, CSS, and JavaScript, and perhaps one day handle some of the jobs PHP handles, but in its own way.

That goal would have made the runtime burden on the C side unnecessarily large.

That was how Go entered the picture.

AhdCode source code would first pass through a Lexer (AHD translation: the layer that splits code into meaningful pieces) and a Parser (AHD translation: the layer that figures out how those pieces form structures according to the rules of the language). An AST would be created (AHD translation: an abstract tree-shaped representation of the code), semantic checks would be performed (AHD translation: checking whether the code makes sense even if it is grammatically valid), the result would then be translated into Go code, and finally a native executable would be produced.

Thanks to Go's garbage collection (AHD translation: automatically cleaning up memory that is no longer being used), built-in string and map structures, HTTP stack, concurrency support (AHD translation: allowing multiple pieces of work to progress together), JSON tools, and broad ecosystem, it seemed much more sensible to spend my energy on AhdCode itself.

That became one of the most important architectural decisions of the night.

August 28, 2:49 AM.

Roughly five hours earlier, I had merely been wondering how many people in the world could theoretically write a programming language.

Now I was saying:

“I want to build my own language called AhdCode. I wrote a prompt (AHD translation: the detailed instructions I give to an AI) and a spec (AHD translation: the technical document defining how the language is supposed to behave). Can you review them?”

There is one small point I should emphasize here.

Those five hours were not simply spent asking questions and waiting for answers. I answered the questions that came back, compared options, made decisions, clarified requirements, and gradually shaped what kind of language AhdCode was going to be.

So the transition was not merely from:

“Could this even be done?”

to:

“Here is the spec.”

Those five hours were also the period in which the language started developing its first real personality.

Do I want semicolons?

What should functions look like?

Should declaring a variable and changing its value later be clearly separated?

If a function receives the wrong type of data, should that error be caught by the compiler?

How should modules be named and imported?

What should happen if an alias (AHD translation: a shorter name assigned to a long module name) conflicts with another name?

Should the error system merely tell the user, “wrong,” or should it explain where the problem is and why it is wrong?

Which Go behaviors should never leak into AhdCode?

I had already started answering many of these questions before there was even a compiler.

What came after that took slightly longer.

Thousands of answers, an unknown number of tokens, hundreds of design decisions, and increasingly strange questions...

“If the short name of one module conflicts with another module, which one wins?”

“Should this error be caught at compile time, or should we allow it to survive until runtime?”

“If someone wrote this in an older version, will the new behavior break their code?”

“What happens if another module is using the same file at the same time?”

“Will Path behave the same way on Windows?”

“LaTeX is done, but if we add TikZ too, could we draw decorative certificate borders?”

I would especially like to point out that the last question was not part of the compiler plan on the first night.

The Biggest Problem Once It Works: Wanting More

At the beginning, I deliberately wanted to keep the target small.

A few basic data types.

Functions.

Conditions.

Loops.

Lists.

Modules.

And a working compiler.

At first, even classes seemed unnecessary. There were no generics (AHD translation: a system that lets the same structure safely work with different data types). No reflection (AHD translation: allowing a running program to inspect its own structure). No operator overloading (AHD translation: defining special behavior for operators such as + or -). No large framework systems (AHD translation: prebuilt structures for organizing an application around a particular architecture).

In short, the philosophy of the initial plan was:

“Let us not reinvent Java.”

This was a perfectly sensible approach.

For approximately a few hours.

Because the moment you see the first working code, another extremely dangerous question appears:

“So what else could we do with this?”

For me, the first serious answer came from a very natural place:

LaTeX.

Since I am a mathematician, the idea that AhdCode could do more than simply print things to the screen and could directly produce mathematical and academic documents caught my attention very early.

So one of the first major expansions of the standard library happened on the LaTeX side.

But once LaTeX existed, producing documents was no longer enough. Processing the data that would go into those documents also became important.

That was how Data arrived.

Then, naturally, came CSV (AHD translation: a common format for storing table-like data in simple text files).

If we could read data, the next question did not take long:

“What if we visualize it?”

And that produced Plot.

Once Plot expanded the data and mathematics side, I returned to LaTeX. The original LaTeX support, which only handled basic document generation, no longer seemed sufficient, so that module began expanding as well.

In other words, the standard library did not grow as a flat list like:

Module 1
Module 2
Module 3
Module 4

It looked more like:

LaTeX
   ↓
Data
   ↓
CSV
   ↓
Plot
   ↓
Expanding LaTeX
   ↓
Regex
   ↓
Word
   ↓
XML
   ↓
Excel
   ↓
...

It became a chain of needs that kept creating one another.

Regex (AHD translation: regular expressions used for finding and matching patterns in text) opened new possibilities in text and data processing.

Once Word support arrived, AhdCode could generate not only mathematical documents but also more general-purpose documents.

XML (AHD translation: a text-based format that structures data using tags) brought another category of data formats into the system.

Excel then connected the data-processing and document-generation sides again.

After that, File, Path, Environment, SQLite, MySQL, PDF, Archive, and other tools continued to build on top of the same structure.

At one point, I realized that before I had even fully moved into the web side, many foundational tools I had originally thought I would deal with much later were already finished.

What I liked even more was that these had not arrived as disconnected features.

Something added in one release would prepare the foundation for another module several releases later. Data made CSV useful; CSV made Plot meaningful; Plot created a reason to expand LaTeX again; and as document and data tools developed, modules such as Word, XML, and Excel joined the chain naturally.

So the standard library was not simply gaining more modules. The relationships between those modules were becoming increasingly meaningful.

The releases started fitting on top of one another.

I think this is one of the things I am most proud of in AhdCode so far.

Developing quickly may be easy.

Developing quickly without destroying the previous twenty releases is harder.

The Most Dangerous Questions Usually Look Small

AhdCode's development was not shaped only by large features.

The issues that took the most time were often questions only a few words long.

For example:

“Can the list inside a Constant be modified?”

At first glance, that sounds like a small question.

But its answer defines the language's approach to immutable data (AHD translation: data that cannot be changed after it is created).

If you protect only the variable itself but allow the list inside it to change, you get one behavior. If you require immutability all the way down into the internal structure, you have moved toward a different language philosophy.

When I decided that the second approach was more consistent, I was not merely deciding the behavior of a single keyword. I was deciding what “constant” would actually mean in AhdCode.

Another example:

“What is null going to do here?”

Again, only a few words.

But the answer affects everything from the type system (AHD translation: the rules governing which kinds of data are allowed where) to runtime behavior.

Can a value genuinely be empty?

Can a value that might be empty be assigned somewhere that cannot accept an empty value?

If the compiler can see the problem in advance, why wait until the program is running?

A seemingly tiny decision about null suddenly puts control flow, type safety, and error messages at the same table.

Then another question appears:

“If we change this behavior, what happens to AhdCode files people already wrote?”

At that point, the issue stops being only about adding a new feature and turns into backward compatibility.

During this process, I came to understand much more clearly that a programming language is far more than its syntax (AHD translation: the writing and structural rules of the language).

A feature may look good on its own.

But if it conflicts with the rest of the language, looking good is not enough.

Getting the happy path working (AHD translation: the normal scenario in which everything is used as intended) is usually easy.

What interested me more was the side that I eventually started calling, among ourselves, the destroyer path (AHD translation: deliberately attacking the system with absurd and extreme edge cases).

A normal user writes:

write("Hello AhdCode")

After a while, I was walking around asking:

“What happens if I add null to a string?”

“What happens if I put a Unicode character and a null byte in the same place?”

“What if I give this an unclosed HTML tag?”

“What if I try to modify a collection while iterating over that same collection?”

“What if I try to carry data of the wrong type through several functions while making it look valid?”

And when something broke, my first reaction was often:

“Good. Apparently there is still something here we need to talk about.”

Because in a project like this, an error does not always mean merely a bug that needs to be fixed.

Sometimes the error reveals a design question that the language has not answered yet.

A Small Problem with the Original Estimates

Looking back at the time estimates we made on the first night is quite entertaining now.

The rough plan looked something like this:

Within one week:

“Look, our own language works.”

A demo we could point to.

Within two to four weeks, something usable for small real projects.

Within one or two months, a usable AhdCode 0.1 with documentation and a set of tools.

Technically, that estimate was perfectly reasonable.

The only variable we failed to account for was me.

Roughly ten days later, the project had seen 46 releases and reached AhdCode v1.0.0.

So from now on, when estimating timelines for AhdCode, we may need to add one more variable to the usual software-development equations:

“Will the developer become curious about something new at 2:00 AM?”

Unfortunately, the value of that variable has so far remained permanently true (AHD translation: yes, unfortunately he became curious again).

We may also need another variable:

“Will he leave whatever he became curious about until morning?”

I am not particularly optimistic about the current value of that one either.

46 Releases: More of a Survival Strategy Than a Speed Record

I also do not want the phrase “46 releases in 10 days” to be misunderstood.

That number is not there to show how quickly I can write code.

A significant portion of the code was generated by AI models anyway.

The 46 releases were also a way of moving forward without collapsing the project.

We added a feature.

We tested it.

We checked the old behavior.

We updated the documentation.

Then we froze that version.

This meant that when the next feature arrived, we did not merely have some vague codebase about which we could say, “I think it worked yesterday.” We had a known version and knew exactly where we stood.

As the project grew, my biggest fear stopped being that I would fail to add a new feature. It became accidentally breaking behavior that had already been working correctly.

In the first days, the basic question was:

“Does the compiler accept this?”

A few days later, the question became:

“The compiler accepts this, but should it actually accept it?”

The fact that a piece of code could compile was no longer enough to count as success.

Does it represent the correct behavior?

Is it consistent with previous versions?

If it fails, does it fail in the right place?

Does it prepare the ground for the next feature, or does it create a new burden that we will have to carry later?

I think this was one of the most important shifts in the entire programming-language development process.

Four AIs, Two Nearly Full Chats, and an Unknown Number of Tokens

I emphasized this in the first AhdCode article as well:

I am not claiming that I sat down and wrote every line of AhdCode by myself.

By the end of the ten-day period, that reality had become even more obvious.

At different points, I used different AI models.

One model was better at implementation (AHD translation: turning a design into actual working code).

Another was better at reviewing long files and identifying architectural problems.

Another could be more useful for generating edge cases that tests should catch.

Sometimes I had one model review code written by another.

Sometimes I distrusted the conclusion both of them had reached and asked a third:

“They both say this, but I am still not satisfied. Criticize it too.”

Eventually, the number of AI subscriptions I was actively using for AhdCode reached four.

On the ChatGPT side, two separate conversations dedicated almost entirely to AhdCode ended up nearly full.

For a while, I kept track of how many tokens I had used.

Then, for the sake of my mental well-being, I decided to stop counting.

In 2026, assigning four different AIs to review one another's code while developing your own programming language may sound slightly absurd.

Surprisingly, it works.

In fact, sometimes the most useful outcome was not the models agreeing with one another, but disagreeing.

When I was presented with two different approaches, I had to think about why I was choosing one of them.

I also learned something important about AI-assisted software development through this process.

The fact that an AI can write very good code does not remove your responsibility to know what you want.

If anything, as the project gets larger, the burden of decision-making increases.

On day one:

“Do this.”

may be enough.

By day ten, you need answers to questions like these:

  • Does this feature fit AhdCode's existing design philosophy?
  • Which earlier decision does it affect?
  • Does it break backward compatibility?
  • Are we creating a second API (AHD translation: the interface through which different pieces of software communicate) that does the same job?
  • Does this feature belong in this part of the standard library?
  • What error will users see when they use it incorrectly?
  • Does that error message actually help them?
  • Is there platform-specific behavior we have not tested?
  • Is this feature genuinely necessary?
  • Or are we adding it simply because we can?

I think that last question has become increasingly important.

Because in the AI era, being able to build something is becoming cheaper and cheaper.

The fact that a feature can be implemented in a few hours is no longer, by itself, a sufficient reason to add it.

Deciding what not to build is still expensive.

At Some Point, the Language Wasn't Enough, So I Started Building the Tools Too

On the first night, my mind was focused mainly on the language itself.

Lexer.

Parser.

Type system.

Compiler.

Native executable.

But once you actually start using a programming language, having a compiler alone is not enough.

While writing code, you want your editor to understand you.

You want the file to be recompiled the moment you save it.

You want to fix the formatting of your code with a single command.

Sometimes you do not even want to create a file just to test something small.

That was the point where the project stopped being merely the AhdCode language and began turning into the AhdCode toolchain.

Language Server

One of the most important additions was LSP, the Language Server Protocol (AHD translation: a standard that allows an editor to communicate with a programming language's analysis tools).

In simpler AHD terms: the background language service that allows the editor to genuinely understand AhdCode.

Today:

ahdcode lsp

starts AhdCode's own language server.

And this is not merely a tiny system that draws a red underline and says:

“There might be an error here.”

It has Diagnostics (showing code errors and warnings in the editor).

Hover (showing type and symbol information when you place the pointer over something).

Completion (automatic code-completion suggestions).

Go to Definition (jumping directly to where a symbol was defined).

Document Symbols (listing Functions, Classes, and similar structures in a file).

Signature Help (showing the expected parameters while calling a Function).

Find References (finding where a selected symbol is used).

Rename (safely renaming the actual symbol rather than blindly replacing matching text).

Semantic highlighting (coloring code according to meaning rather than merely according to words).

Inlay hints (small type or parameter hints shown directly inside editor lines).

Quick fixes and code actions (ready-to-apply editor operations for certain problems).

Auto import (automatically adding the required module for a symbol being used).

Document formatting (bringing the open file into AhdCode's standard formatting style).

Workspace symbol search (searching Functions, Classes, and other definitions throughout the project).

Folding and selection ranges (collapsing code blocks and progressively selecting meaningful code structures).

More importantly, none of this is powered by a second, separately invented interpretation of AhdCode created just for the editor.

The LSP does not invent its own parser or its own type system.

Whatever lexer, parser, and semantic analysis system the compiler uses, the language server gets its information from that same real frontend (AHD translation: the compiler side responsible for reading and understanding source code).

In other words, I tried to avoid creating two parallel universes where the compiler says:

“This is wrong.”

while the editor says:

“I think it might be fine.”

One detail I particularly like is that even unsaved editor content can be analyzed.

The VS Code extension uses the same ahdcode lsp server.

So something I wrote in earlier drafts:

“A Language Server could be developed.”

is no longer accurate.

Of course, more features can be added later.

But the LSP surface I originally defined for everyday use is already complete.

Formatter

The same applies to the formatter (AHD translation: the tool that automatically puts source code into the language's standard style).

ahdcode format program.ahd

can transform source code into one canonical form (AHD translation: the form officially considered standard by the language).

The formatter is not simply a text tool randomly adjusting spaces.

It is AST-aware (AHD translation: it understands the structure of the code instead of treating it as plain text).

It knows the structure of the program.

It preserves comments.

It preserves string escapes such as \n.

It does not break interpolation (AHD translation: inserting variables or expressions directly into strings).

It leaves multiline string contents untouched.

It does not attempt to half-format invalid source code.

And repeatedly formatting the same source does not continue changing the result.

format(format(source)) == format(source)

When I started writing a programming language, I did not expect a formatter to become important this early.

But once you start seeing your own language across hundreds of files, the question:

“What is the official appearance of this language?”

becomes just as real as the syntax itself.

REPL

Then there is the REPL.

In AHD terms: an interactive environment where you can type AhdCode directly into the terminal and immediately see the result without creating a file.

Simply running:

ahdcode

opens a persistent AhdCode session (AHD translation: a session that remembers earlier definitions).

For example:

ahd> x := 5
ahd> x = x + 1
ahd> x
6

works as expected.

I did not write a separate toy interpreter for this either.

The normal lexer, parser, semantic checker, and AhdCode's lower representation layers are shared with ordinary file compilation.

Variables can survive throughout the session.

Functions and Classes can survive.

Objects such as List and Pair preserve their identities.

Modules can be used.

File operations work.

Even an SQLite database can remain open inside the interactive session.

In short, at some point the project moved from:

“I can compile my own language.”

to:

“I also have a significant portion of the tools I need to actually use my language every day.”

What Happened to the Web Goal from the First Night?

I want to return separately to the web goals we discussed on that first night.

In my earlier description, they can sound as though they are still future milestones waiting somewhere ahead of me.

In reality, the situation is largely the opposite.

One of the goals in my head on the night of August 27 was:

“I want something I can use on the web like PHP. I do not want to have to open MAMP. It should start its own local server, connect to MySQL, and let me use HTML, CSS, and JavaScript inside the project.”

That night, I saw this as one of the major milestones I might eventually reach.

Today, AhdCode can run:

ahdcode init web

to create an initial web-project structure.

And it is not limited to one empty template.

Empty.

Basic.

Admin.

MVC.

CRUD.

Different starter structures can be selected.

In AHD terms: instead of manually creating files one by one in an empty directory, AhdCode builds a web-application skeleton you can immediately start working from.

Then:

ahdcode dev app.ahd

starts the application in development mode.

This command compiles the source, runs it, and watches the relevant file graph.

When the code changes, it rebuilds the application.

If the new build succeeds, it replaces the running application with the new version.

If the new build is broken, it does not kill the last working application.

So a syntax error does not suddenly make the working application disappear from the browser.

Development continues after the next successful save.

This sounds like a small detail, but once you actually use it, it becomes extremely valuable.

Even local development names entered the picture.

For example, a local identity based on the application's domain can be created:

ahdakademi.test

Here, local identity simply means a local domain name assigned to that project on my own computer.

Once the initial permission has been granted, AhdCode can manage these local names within its own development workflow.

So the thing I imagined on the first night:

“I want to write a file in my own language, run it from the terminal, and open it in a browser.”

is no longer a goal.

It is a working feature.

I Was Hesitant to Call It a Framework; the Documentation Was Braver Than I Was

For a while, while discussing the web side, I deliberately thought:

“Let me not call this a framework.”

Because my goal was not to build some enormous Laravel, Django, or similar system.

I simply wanted to be able to write real server-side web applications comfortably in AhdCode.

But as the project expanded, all of these pieces came together:

HTTP.

HTML.

Cookies (AHD translation: small pieces of identity or state information stored by the browser).

Server-side sessions (AHD translation: keeping session data on the server instead of giving the data itself to the user).

Forms (receiving and processing data submitted through web forms).

Validation (checking whether incoming data satisfies defined rules).

CSRF protection (AHD translation: protecting users against forged form requests being sent on their behalf without their knowledge).

Flash messages (AHD translation: messages such as “Registration completed successfully” that appear once on the next page and then disappear).

Routes (AHD translation: determining which Function responds to which web address).

Route groups (grouping similar web routes under shared rules).

Guards (AHD translation: gates that decide whether a request is allowed to reach a particular page).

Layouts (shared page structures reused across multiple pages).

Components (small reusable interface pieces).

Static assets (files served directly, such as CSS, JavaScript, images, and fonts).

Web starters (templates that create ready-made starting structures for new projects).

And today the AhdCode documentation explicitly describes this structure as a first-party Web framework (AHD translation: AhdCode's own official web framework shipped together with the language).

What matters to me is still not its size.

The web layer follows AhdCode's general philosophy as well.

For example, pages, layouts, and components do not have to be written in some mysterious template language (AHD translation: a second special syntax you would need to learn just to generate HTML). They can be written as ordinary AhdCode Functions.

The HTML layer puts safe text generation at its center.

Native executables can be produced without requiring the framework source code to remain present separately at runtime.

In other words, I did not want a structure where:

“I am using AhdCode, but secretly I am also learning another template language and another runtime.”

I wanted the web side to resemble the rest of the language as much as possible.

Databases: From SQLite to MySQL, Then to Its Own Tool

On the first night, I explicitly kept saying MySQL.

But the database side did not stop there.

First came a typed SQLite bridge.

Then came MySQL support capable of connecting to real MySQL servers.

Queries use parameter binding (AHD translation: values are sent as safe parameters instead of directly gluing user data into SQL text).

Transaction support is available (AHD translation: multiple database operations can succeed together as a single unit or be rolled back together).

The required MySQL driver (AHD translation: the library that lets the program communicate with MySQL) is shipped with the package so that an AhdCode program using MySQL does not need to search the internet for a driver during the build process.

In other words, the goal of offline builds is preserved here as well.

Then at some point I arrived at another question:

“If we already have MySQL and SQLite, why not build our own tool for managing them comfortably?”

And that produced AhdDataStudio.

There is one detail here that I particularly like:

AhdDataStudio is not some hidden management screen embedded inside the compiler.

It is a real AhdCode application written in AhdCode.

The language had reached the point where it was building one of its own development tools with itself.

Running:

ahdcode databases

opens the bundled AhdDataStudio, which can manage both MySQL and SQLite.

This was one of the moments when the language project began to feel “real” to me.

I was no longer merely saying:

“You can write user applications in AhdCode.”

I had also written one of AhdCode's own ecosystem tools in AhdCode itself.

Getting Data from the Web: From HTTP to Scraping

The web side did not stop at returning HTML to a browser.

An outbound HTTP client arrived.

In AHD terms: AhdCode can not only respond to incoming web requests, but can also send requests to other web services.

This makes it possible to communicate with JSON APIs (AHD translation: web services where two pieces of software exchange JSON data).

External services such as Gemini can also be called through the standard HTTP tools.

I deliberately do not call this a “Gemini module.”

AhdCode does not need a hidden AI-vendor layer dedicated specifically to Gemini.

If HTTP exists, JSON exists, and the service provides a standard API, then AhdCode can already talk to it.

Then HTML parsing arrived (AHD translation: turning incoming HTML text into a document structure the program can understand and navigate).

HTML returned by an HTTP request can be converted into an HTML document structure.

Elements can be selected by tag, such as div, a, or table.

They can be selected by ID.

By class.

By attributes such as href or data-*.

Elements can also be found through parent-child and descendant relationships.

The natural result of that was scraping.

In AHD terms:

Fetch a web page.

Parse its HTML.

Select the elements you want.

Extract the data.

Process it if you want.

Write it to SQLite or MySQL if you want.

Send it to another API if you want.

Generate CSV, Excel, Word, PDF, or a chart from the result if you want.

This was where the chain logic I had begun building into the standard library in the early days showed itself again.

Data was not isolated.

CSV was not isolated.

Plot was not isolated.

HTTP was not isolated.

The HTML parser was not isolated.

MySQL was not isolated.

At some point, it became possible to combine these pieces into real workflows.

For me, that is where the real value of building a standard library lies.

v1.0.0: Not Finished, but Built on a Complete Foundation

AhdCode v1.0.0 does not mean “the project is finished” to me.

But it definitely no longer means:

“I still have not reached any of the actual goals.”

In fact, the repository's own description is fairly clear today:

The language, toolchain (AHD translation: the compiler, CLI, formatter, LSP, REPL, and development tools), and Web framework have reached the feature surface defined for v1.0.0.

Comparing that with what I had in mind on the first night makes the picture even more interesting.

I wanted a compiled language with its own syntax.

It exists.

I wanted Go behind the scenes without forcing users to write Go.

It exists.

I wanted native executables.

It has them.

I wanted to run things comfortably from the terminal.

Done.

I wanted a persistent REPL.

It exists.

I wanted a formatter.

It exists.

I wanted the editor to genuinely understand the language.

There is an LSP.

And not merely autocomplete; the basic language-tooling surface I expect for daily use is already there.

I wanted VS Code integration.

It exists.

I wanted the initial structure of a web project to be generated automatically.

ahdcode init web does that.

I wanted multiple starters.

There are Empty, Basic, Admin, MVC, and CRUD options.

I wanted to run app.ahd locally and open it in a browser.

ahdcode dev app.ahd does that.

It also handles the rebuild/restart cycle whenever files are saved.

I wanted it to connect to MySQL.

It can.

SQLite is there too.

And AhdDataStudio, written in AhdCode itself, can manage both of them.

I wanted to write real web applications using HTML, CSS, and JavaScript.

That works.

I wanted it to cover real application needs such as server-side sessions, forms, validation, CSRF, and routing.

Those exist too.

I wanted it to retrieve data from elsewhere.

There is an HTTP client.

I wanted it to read web pages.

There is an HTML parser and selector system.

I wanted scraping.

It can be done by combining the existing HTTP and HTML tools.

So the problem in front of me is no longer getting AhdCode to the point where:

“It can do something real.”

That threshold has already been crossed.

A significant portion of the work from this point forward is less about inventing a completely new fundamental capability and more about maturing what already exists.

Performance can improve.

Platform support can become stronger.

Existing APIs can be refined over time.

Web ergonomics can improve.

New standard modules can be added.

More advanced refactoring tools (AHD translation: tools that safely transform code structure without changing program behavior), which the LSP deliberately leaves outside its current scope, could be considered later.

And of course, one of the major missing tools is still a debugger.

An LSP and a debugger are not the same thing.

Although AhdCode's Language Server is already quite comprehensive, a real debugger based on the Debug Adapter Protocol (AHD translation: the standard that lets an editor communicate with a debugger), capable of stepping through programs and inspecting variables, is not yet part of the system.

So there is still plenty to do.

But the character of the to-do list has changed.

On the first day, the dominant question was:

“Can we make this possible?”

Today, the more important question is:

“How do we make what we have already made possible cleaner, more consistent, and more comfortable to use?”

At the beginning, I was trying to push the boundaries outward.

Now I am thinking about how to live more cleanly inside those boundaries.

I think that change matters more than the version number itself.

The Real Value of v1.0.0: A Reference Point

In software, 1.0.0 is a strange psychological boundary.

People can interpret it roughly as:

0.x.x = we are still experimenting
1.0.0 = that's it, finished

I do not look at AhdCode that way.

To me, v1.0.0 means:

“We now know what we are building.”

And after the first ten days, I can add one more sentence:

“We can now genuinely do a significant portion of what we originally wanted to do.”

That does not mean nothing will ever change from now on.

It means the foundation on top of which those changes will happen is much clearer.

The language will obviously continue to evolve.

New modules may arrive.

Existing features may mature.

Some things may become simpler.

Some APIs may receive second versions.

I will probably look at some APIs that seem perfectly sensible to me today and, a few months from now, ask:

“What on earth possessed us to design this like that?”

But putting the first night's goals next to today's system already makes one thing obvious: AhdCode is no longer an experimental parser that understands a few keywords. It is a system in which the language, standard library, toolchain, web layer, and data/document tools work together.

More importantly, I now have a reference point against which I can evaluate new features.

When a new idea appears, I can ask not only:

“Can AhdCode do this?”

but also:

“Does this actually feel like AhdCode?”

And perhaps even more importantly:

I now have a much clearer idea of what AhdCode should not become.

Conclusion: Ten Days Ago It Was a Question; Today It Is v1.0.0

On the night of August 27, I was questioning how unreachable programming-language development really was.

Ten days later, I have AhdCode v1.0.0.

If someone had told me on August 27:

“Ten days from now, this will have 46 releases.”

I probably would not have believed them.

“You will use four AI subscriptions for the same project.”

That I might have believed a little more easily.

“You will almost completely fill two ChatGPT conversations talking about little else but this programming language.”

I probably would have replied:

“Yeah, that one is possible.”

But v1.0.0 was genuinely not part of my original plan.

Even more interesting was the fact that a significant portion of the things I had talked about on the first night as:

“It would be nice if we could do this someday.”

had become working features ten days later.

From developing web applications and running a local development server, to MySQL and SQLite, editor tooling, the formatter and REPL, outbound data retrieval, and HTML parsing, many of the subjects that looked like distant goals on the first night are now parts of the working system.

That is why the fundamental question has changed too.

“Can we do it?”

has become:

“How can we do it better?”

This process also showed me something more important than how quickly AI can generate code:

Faster code generation does not remove the burden of deciding what to build and how it should behave.

I came to understand much better that a programming language is not merely syntax.

I learned how compilers think.

I saw how a tiny decision in API design can still come back to meet you dozens of releases later.

I saw that an error message is not merely a technical detail, but part of how the language communicates with its users.

I saw that it matters less for a module to be powerful in isolation than for it to behave consistently with the modules around it.

I saw the importance of having the compiler and editor tools share the same real language analysis.

I saw that a programming language is not only about running code; the development experience it gives you while writing that code is also part of the product.

And while developing a large project with AI, I learned that it is not enough for code-generation speed to scale. Review and decision-making quality have to scale too.

Most importantly, I had the chance to test the question that had been running through my mind since the first night:

“How would I do it?”

against something that actually works.

At the end of the first AhdCode post, I wrote:

“Maybe three people will use it. Maybe I will be the only one.”

That thought has not changed.

A programming language does not need millions of users to be valuable to me.

What changed over these ten days was not merely AhdCode's feature count.

The way I look at the project changed too.

In the first days, every working feature pushed the boundaries of the project a little farther outward. Today, something equally important is making sure the pieces already inside those boundaries actually work together, and do so consistently.

AhdCode is still a project growing through curiosity.

But it has moved far beyond the experiment of:

“Can I create a working programming language?”

Most of the fundamental use cases I imagined on the first night genuinely work today.

Some tools I never even talked about on that first night have already become complete parts of the system.

That is why the next phase feels somewhat different to me.

Of course, adding more features is possible.

I probably will add more.

Let us not forget that our 2:00 AM variable is still true.

But I am also learning that every curiosity does not automatically need to become a new feature.

Sometimes the next major improvement is not adding another module, but making the ten existing modules communicate with one another more cleanly.

Sometimes making the existing syntax more consistent is more valuable than adding new syntax.

Sometimes, instead of saying:

“We built that too.”

it is a bigger step forward to be able to say:

“We can now use this with confidence.”

I think I learned that together with AhdCode.

I cannot imagine a more appropriate point for v1.0.0.

For now, I will close the second chapter of AhdCode's story here.

We were together again for the first post of September. I honestly have no idea what the next post will be about. Judging from the last ten days, it is already fairly obvious that my ability to predict the topic in advance is not particularly reliable.

But in the worst-case scenario, I will be back here on September 27.

Because if tradition continues, I will return with the letter I write to my new age—28.

As for whether AhdCode v1.0.0 will genuinely remain v1.0.0 until then, I cannot offer any guarantees.

Considering that I ended the first article by saying I would slow down a little and then produced 46 releases in ten days, any promises I make on that subject probably have very little legal force anyway.

Until the next post, take care.


Appendix: “So What Exactly Did You Do with Go?”

For anyone who made it this far and is still wondering, “AhdCode uses Go, but what exactly does that mean?”, let me leave a very small and representative example.

Imagine that we write the following AhdCode:

number: Int := 9
if number % 3 == 0 {
    write("Yes")
} else {
    write("No")
}

To a human reader, what happens here is fairly simple:

We define a number. If it is evenly divisible by 3, we print Yes; otherwise, we print No.

The compiler does not read this the way we do.

First, the Lexer splits the source code into small meaningful pieces. In rough AHD terms:

number   → name
:        → a type is coming
Int      → integer type
:=       → initial assignment
9        → number
if       → condition begins
number   → variable
%        → remainder
3        → number
==       → is equal to?
0        → number
write    → produce output

Then the Parser determines how those pieces relate to one another.

It does not merely say, “I saw an if here.” It reconstructs the program roughly as:

Define an Int variable.
Then:
    check the condition
    number % 3 == 0
If true:
    write("Yes")
Otherwise:
    write("No")

Semantic checks then step in and ask questions such as whether number is actually a number, whether the % operation is valid here, and whether the condition genuinely produces a true/false value.

This stage matters because looking grammatically valid is not enough. What the code says also has to make sense under the rules of the language.

Once all of those checks pass, AhdCode's Go backend translates that structure into Go code roughly resembling:

number := 9
if number%3 == 0 {
    fmt.Println("Yes")
} else {
    fmt.Println("No")
}

In the final stage, Go's own compiler takes over and turns that code into a program the operating system can run directly.

So, in the shortest AHD translation:

AhdCode
   ↓
Lexer: "What pieces are here?"
   ↓
Parser: "What do these pieces mean together?"
   ↓
Semantic Analysis: "Does what they say actually make sense?"
   ↓
Go Backend: "How do I express this in Go?"
   ↓
go build
   ↓
Executable program

The important point is this:

The user does not write Go.

The user writes AhdCode.

The Lexer, Parser, type system, and semantic rules belong to AhdCode.

The Language Server uses the same real compiler frontend (AHD translation: the lexer, parser, and semantic-analysis side responsible for reading and understanding the code).

The Formatter understands AhdCode syntax and its AST.

The REPL follows the same language rules.

Go provides a powerful foundation for turning the structure produced after all those AhdCode decisions into something the computer can execute.

So what I did with Go was roughly this:

I did not hand AhdCode's personality and rules over to Go. I built a system that translates what AhdCode says into a form Go can execute.

Go runs the engine; AhdCode is still behind the wheel.