DEV Community

Sukanya Mondol
Sukanya Mondol

Posted on

AstraOS: I built a Linux distribution with an AI assistant that asks before it touches anything

AstraOS is a Linux distribution built from Debian packages, with its own package selection, desktop configuration, branding, installer configuration and build pipeline. Its ISO builds in GitHub Actions, passes the checks that build runs, and boots in VirtualBox. It is also an alpha: version 0.2.0, codename Nova, x86_64 only, not finished, and nothing in it has ever run on physical hardware.

Why it exists

The founding brief was blunt about what it did not want: "I do not want a website pretending to be an operating system. I want an actual, bootable, installable Linux distribution that can eventually run on physical computers."

The roadmap gives the reason. AstraOS should be the operating system for the PC people already own: a private, local-first computer that turns plain-language instructions into controlled, verifiable work. Windows 10 support ended in October 2025 and many working PCs cannot officially run Windows 11. The "AI distributions" that get talked about route agent work to cloud services by default, and cloud agent products have drawn privacy criticism for reading and writing personal folders.

The hardware target follows. The reference machine is an Intel Core i5-2500S, a 2011 Sandy Bridge chip, and the assistant is sized for that class on purpose. One principle drives the rest: keep the system usable on modest hardware, which is why the desktop chrome is flat and the expensive graphics live on the boot splash.

What is actually in it

Base. Debian 13 (trixie), pinned in one file and checked against the live archive before a build, using Debian's own linux-image-amd64 kernel (6.12 series) with systemd as the init system. It is a derivative, not a new kernel and not an official Debian release. Packages are .deb with APT and dpkg, selected from ten reviewed lists under config/package-lists, and the root filesystem is ext4 once installed and squashfs on the live image.

Desktop. Xfce on X11, configured and branded: its own wallpaper, panel, icon theme, cursor, LightDM greeter, Plymouth splash and GRUB menu. The identity has two layers. The brand layer, a neon ring with gradients and bloom, appears where you see the system briefly: boot, login, installer. The desktop layer is flat graphite and cyan with no transparency, because a blur pass on every panel repaint is what makes a desktop feel slow on old hardware.

Installer. Calamares, configured and branded. The target disk is never assumed and erasing is never the default, and the build refuses to produce an image that breaks that.

Target hardware. x86_64 Intel or AMD from roughly 2008 onwards. VirtualBox is the primary target, and the guest agents for QEMU/KVM and VMware ship in the image. Graphics drivers are open-source only, so NVIDIA goes through nouveau.

Recovery. A failsafe GRUB entry that drops the splash and turns off modesetting and ACPI, so a failure is visible instead of hidden. astraos-recovery-guide prints the guidance on a running system, and docs/RECOVERY.md covers the cases that need the medium. The snapshot, break, restore drill with Timeshift has not been performed.

The assistant

The interesting part of this project is not the model. It is what happens between the model's request and the machine.

The assistant runs entirely on the computer: a small Python server using only the standard library, and one HTML file with the styles and script inline. A test fails if an external address appears in that page. There is no cloud provider to configure and no API key to enter.

The repertoire is closed. The model may ask for one of 32 named actions and nothing else. The plan is re-checked against that catalogue before it runs, an unknown action name is refused rather than guessed at, and llama.cpp constrains generation with a JSON schema, so a tool call is valid or empty, never half-written.

The confirmation set is seven actions. run_command, shutdown, reboot, suspend, close_window, type_text and press_key. Each has a question written for it, because a person cannot consent to a category of thing. The page shows "the assistant wants to run this command (command='df -h')", not "allow the assistant to run a command". The set grew by one when the research tools landed: write_file writes into the assistant's own workspace and asks as well, so the catalogue asks before eight actions today while the README still says seven.

Underneath sit four permission levels: observe reads and changes nothing, prepare changes the session's surroundings reversibly, modify can change or lose your work (typing, key presses, closing a window, writing a file), and privileged changes the machine (suspend, reboot, shutdown, running a command). Everything above prepare is denied until a human says yes, and the approval names the resolved arguments and the effect rather than the category.

The reasoning matters more than the list. The model cannot approve itself: the plan comes from the model, the yes comes from a person in front of the screen, and the web page and the command line both go through one enforcement point, so neither can take a different route around it. A denial is not a sentence in a message. It is the action not running.

One decision I got wrong and reversed. I had argued that asking for every typed phrase would make typing useless, so type_text and press_key were left out of the set. That was wrong, because a terminal turns typing into a way to run a command. They are in the set now, and the person is asked once per plan with the exact text, not once per phrase.

Documents are data. When the assistant reads a file containing instruction-shaped text, the request is marked as coming from a document and the guard refuses everything above observe for it. The test fixtures order the assistant to open an exfiltration URL, run a command and type over a document. Each one is refused, and the refusal is recorded.

The sandbox covers the model server, not the actions. With bubblewrap or firejail installed, llama-server runs with the root and the model folder read-only and a private /tmp and /dev/shm. The network stays shared on purpose, because the page reaches the server over 127.0.0.1. Landlock is not used. The actions run as you, with your rights, and are not sandboxed.

Undo is a tested library, not yet a feature. It copies files into a snapshot directory with a manifest, restores them exactly, and removes paths that did not exist before. What is missing is the wiring: no privileged action takes a snapshot yet, and there is no astra-ai undo command.

The budgets exist so a weak model cannot loop forever. A plan longer than twelve steps is refused before it starts. A task that spends its 900-second budget is filed paused where it stopped rather than failed, and astra-ai resume continues it. A task may make at most 100 tool calls. A memory cap exists as RLIMIT_AS on the model server and is off by default.

Every decision is recorded as a JSON line carrying the SHA-256 of the line before it, so astra-guard verify can name the first record that was edited or removed. The chain is tamper-evident, not signed.

The engines are built in CI. Compiling llama.cpp costs about twenty minutes of every core, so the Build AI engine workflow builds it for two variants: avx for the Sandy Bridge class and avx2 for Haswell and later. The avx build is proven on an emulated Sandy Bridge with a real model answering over HTTP, because that class of machine once died with SIGILL and printed nothing. The avx2 build is proven natively, with a disassembly check that the 256-bit code is really there. No variant is ever compiled for the build machine's own instruction set. Both are published as the ai-engine-2026-10-19 release, and the image build downloads those assets, verifies their SHA-256 and installs both variants.

The executor is a 1.7B model that reads one request and makes one tool call; the middle brain is a 4B model that writes the plan. The split follows the measured finding that multi-agent systems on small models are planner-limited rather than executor-limited, so the parameter budget goes into the planner.

Try it

Build it yourself on a Debian 13 host with about 25 GB of disk:

git clone https://github.com/rafikulislammollaq-dev/astraos.git
cd astraos
make bootstrap     # install the build dependencies
make iso           # build the image into dist/
Enter fullscreen mode Exit fullscreen mode

make check runs the static suite, make lint checks shell syntax, and make validate-iso, make checksums and make manifest work on the image in dist/. Or run the Build ISO workflow from the Actions tab and take the astraos-iso artifact.

In VirtualBox. Verify the download first:

sha256sum -c astraos-0.2.0-alpha-amd64.iso.sha256
Enter fullscreen mode Exit fullscreen mode

Expect astraos-0.2.0-alpha-amd64.iso: OK. If it does not, stop.

Create the VM: name it AstraOS 0.2.0 Alpha, point it at the verified ISO, choose Type Linux and Version Debian (64-bit), decline VirtualBox's unattended installation, and give it 4096 MB of memory, 2 processors and a 30 GB dynamically allocated VDI disk. The installer's minimum is 2048 MB and 8 GB. For firmware, tick Enable EFI under Settings, System, Motherboard for UEFI, or leave it unticked for legacy BIOS.

Start it, wait for the GRUB menu and choose the normal entry. The live user is astra with no password, and the live session is not persistent.

To install, launch "Install AstraOS" from the menu or the dock and authenticate through the polkit prompt. On partitioning, choose Erase disk, because the disk is virtual, and check that the device you are erasing is the virtual one. Create a user with a password, read the summary, confirm, and choose Restart now when the queue finishes. Before booting the installed system, remove the ISO from the optical drive. That is the step people skip, and then they conclude the installer failed.

On physical hardware, the documentation says do not do this yet. AstraOS 0.2.0 Alpha has never been booted on physical hardware, the installer has never been run there, and no hardware has been tested. The procedure is written in advance so it is not improvised afterwards: verify the checksum, back up everything you cannot lose, write the image to a USB drive with

sudo dd if=astraos-0.2.0-alpha-amd64.iso of=/dev/sdX bs=4M status=progress oflag=sync
Enter fullscreen mode Exit fullscreen mode

which erases that drive entirely, boot from it, partition the disk you chose, create the account and confirm. There is deliberately no script in the repository that picks the drive for you. If your firmware refuses the medium, turn Secure Boot off. Use a spare machine or a separate SSD.

What it does not do yet

No physical hardware has been tested at all. The one proven installation is virtual, legacy BIOS, one ext4 partition, no encryption and no swap, and nobody has logged into the installed system. That installed system also carries the live image's initramfs, because nothing in the install sequence regenerates one.

No browser has been launched inside a booted image. The network stack is proven in CI: NetworkManager active, an IPv4 address, a real name resolved over DNS.

The ISO is about 2.4 GB, which is 2,432,696,320 bytes for the last measured build. The next one is expected to be about 3.5 GB with the assistant bundle, and that figure is arithmetic, not a measurement.

The live session has no persistence, the desktop is X11 only, the theme is colour-only so window decorations use the upstream xfwm4 theme, and an upgrade of Debian's base-files can overwrite /etc/os-release and make the system identify as Debian. /etc/astraos-release is the file the project owns, and it is safe.

Wi-Fi is untested, no proprietary GPU driver is shipped, and the firmware for older Broadcom cards cannot be in the image because Debian does not redistribute it.

The assistant has no automatic undo wired to an action, no TLS on the paired phone connection, a tamper-evident ledger rather than a signed one, unsandboxed actions, no wake word, no image input, no stored conversation history, and no published answer-quality numbers for real hardware. astra-ai eval is the instrument that would produce them, and it has only been run as a smoke test on the smallest model in the catalogue.

What I need

The repository is at github.com/rafikulislammollaq-dev/astraos, under the GPL, version 3 or later.

Three specific things would help more than anything else:

  1. Someone with a spare machine. Install it on physical hardware and report what happens. That is the single largest untested area, and a report saying it failed is worth more than a success.
  2. Someone who knows Calamares well enough to review the installer configuration. It was written by reading the documentation, not by using the installer every day, and it is the part of the image most likely to be wrong in a way nobody has noticed.
  3. Wi-Fi chipset results. Which chipsets work, which need firmware that is not in the image, and which need drivers this project will not ship.

Translations are wanted too: the installer and the AstraOS utilities are English only. And if a claim in the README is wrong, say so. Every claim in it is tied to a CI run, a test or an artifact, and "untested" is a word I use on purpose.

Top comments (0)