~/lichen.page

Green Paper

April 19, 2026

This green paper (like a white paper that took a walk in the forest) will describe some of the interesting design decisions taken in this project, and roads taken and not taken.

artwork created by frsw

Using The PDS As A Git Remote

One of the more unusual design decisions lichen makes is to use an ATProto PDS as a git remote, and automatically store backups of all user sites to their PDS via git using git-remote-pds.

I arrived at this, because in the earlier version of lichen-markdown it was self-hostable, which was good for data autonomy, but inaccessible to non-technical users. I wanted to provide a hosted version, but not to control users' data. The ATproto PDS seemed like a middle way to achieve this "best of both worlds" where there is a hosted version and the user keeps autonomy over their data. The data format of static site generator is a folder of files, so git was a natural and interoperable format.

I was inspired by git-ssb that one way to do this was to actually implement the git remote helper api.

I considered using tangled but I didn't want users to have to mess with ssh keys or other configuration. I wanted things to be as simple as "you log in" and all your data automatically is backed up to your PDS.

This design fufills that, and was an interesting rabbit hole along the way.


Lichen CLI, Agent-Assisted Workflows & A Brief Detour Into A Shell In The Browser

While many of my peers have avoided AI and have understandable criticisms, I find the possibility that it can empower non-technical people in new ways to be really cool and not to be passed over.

These days I am more interested in people discerning the good uses of a technology from the bad ones, than in purity politics, so I've had a general interest in finding positive approaches to the use of llms.

I wanted to make Lichen compatible with working with an AI agent, and considered multiple ways of doing this along the way.

In the end, I implemented a way to generate an API token via the dashboard settings pages, and then give this to your local agent so that it can use the API to modify the style of your sites (e.g. "fix this css issue", or "make a hugo site for a blog based on categories"), using a lichen-cli skill.

This is actually how I like to use Lichen, so I hope more people discover this feature, even though its a bit hidden — and it works well with lichen.page. So my favorite use case is to actually use my local agent to work on CSS using natural language, and then use the lichen.page web UI to actually write the content of my pages and/or share it with others to collaborate on the content.

Everything is also backed by git, so its easy to revert things if things ever go astray.

Before I arrived at this design, I went down a big rabbit hole of adding an actual shell in the browser where you could run an agent via terminal on your site via the browser directly. It was sort of interesting that this works, but this runs into all sorts of security and resource-management issues in a hosted context. I tried varies approaches to sandboxing (bubblewrap, systemd, incus vms), but in the end I think having the agent run locally and connect via API actually avoids all these issues and works just as well (other than requiring some initial setup, and knowing that its possible). Then if your agent starts mining bitcoin in your local terminal, thats the user's issue to deal with. Using git as the transport, its all pretty seamless between the local and remote once the token is given for authentication.


Permacomputing & Post-Permacomputing

My original interest in lichen-markdown was grounded in permacomputing. I appreciated that as just a few php files, it could be read and understood in an afternoon. I used the tool for a number of websites and group collaborations, but ran into the issue that when a group wanted to collaborate in real-time, we would open another tool that supported that, like hedgedoc.

If something is so minimal, that you start using other things additionally, that felt a bit to me like cheating. And collaboration did not seem like a feature that could be "dropped" in the spirit of low-tech computing, or other approaches to sufficiency. If we are dropping collaboration, then what is the point of permacomputing?

I considered trying to add realtime collaboration/sync to lichen-markdown in php, but it turns out that using websockets like that in php is an actual limitation of php. Not impossible, but more difficult than in a more modern language. Part of the question of permacomputing is when and why do we need to adopt new tools, beyond the incentives of planned obsolescence — but this was a case where I was encountering a practical reason to move beyond php — the desire for collaboration.

So I decided to rewrite the tool in Rust, which I started in December of 2025. I then decided to incorporate other experiments into the project too (explained more below). That said, lichen-markdown and lichen-gemini still exist in their original forms and I think that's beautiful.


P2P Sync With Git & Iroh

This was another big rabbit hole. Still thinking about ways to have users keep their own data, while depending on my server as little as possible, I considered if I could distribute lichen.page as a tauri app and use iroh for realtime P2P collaboration.

The answer is yes, but the local-first P2P version still had some aspects of the UX story that were worse than the server version, which left me wondering, if servers are possible, then why don't we just use a server?

The two UX issues that were still not ideal (even after realtime collaboration was working seamlessly):

Inviting someone to quickly and easily collaborate on a web page was one of my favorite features of lichen, so that felt like a significant loss.

That said, getting P2P sync via git over iroh to work in realtime and be eventually consistent was one of the most interesting technical problems I've worked on, and I still think its cool even though it has these UX issues. The most interesting code for the sync is here if anyone is curious.

In short, peers exchange git pack files via iroh blobs, using a conflict-free merge driver to avoid conflicts, and using lowest sha wins as a tiebreaker so that git HEADs converge once their filetrees are identical. It seemed to work well (although not super thoroughly tested), and I'm still curious if there is anything it might be useful for...


Flat File Databases (interoperability-maxxing with git, atproto and markdown)

While I ditched much of the elegant simplicity of the original lichens, I still tried to keep some aspects of simplicity where I could, including using a flat file database. Static site generators tend to already be based on a folder of files, so I also made lichen-specific data follow a similar form. As a system administrator, I have often experienced all sorts of weird database issues with open source applications I host for others, sometimes causing weird headaches at unexpected hours. I hope that if anyone is ever running this software, the flat file database helps them have smoother and simpler debugging and sleep well at night.


Malleable Software

There was someone once who numbered the software freedoms, and at least one of them was true in theory, but not in practice, for most people, until recently.

I decided to create a "skill" which is basically just a prompt to read the source code of the codebase and the documentation and invite the user to deploy it themselves and make changes. Its a little more complicated than that but not significantly. I found it to be an interesting thought experiment, and I'm curious how software can be designed to encourage easy modification.


← back to index