{"slug": "show-hn-frontstep-v0-5-2", "title": "Show HN: FrontStep v0.5.2", "summary": "FrontStep v0.5.2, a tool that generates a one-page dashboard of all projects from a `CURRENT_STATUS.md` file maintained by a coding agent, is now available. The tool, which requires installing a skill for the agent, displays open, paused, and closed projects with silence indicators and buttons to open a terminal or editor. Installation uses Astral's uv tool, which is now part of OpenAI as of March 2026, and the project is hosted on GitHub by GiovanniCst.", "body_md": "**One page with the state of every project you have.** Which fronts are open, what the next step\nis, who you are waiting on, and how many days each one has been silent.\n\nFrontstep ships **a skill for your coding agent**, and the skill tells it one thing: keep a\n`CURRENT_STATUS.md`\n\nin each project up to date, as part of the work, without being asked. At the top\nof that file sit six lines — what the project is, who holds the ball, when it last moved, what\nhappens next — and those are the agent's job too.\n\nFrontstep reads those lines, from every project, and derives one page from them. No database, no form to fill in, nothing to remember at the end of a session: you work, the agent writes, and the next time you open the dashboard it already knows where everything stands.\n\nThat is the whole idea. **The skill is not an accessory, it is the engine** — install it (see below)\nand the thing runs itself. Skip it, and you are back to editing files by hand.\n\nThree sections — open, paused, closed — with a card per project: where it lives, what it is, what\nhappens next, and how long it has been quiet. The **silence line** across the top is the view no\nsingle file can give: one tick per open project, from the one that has been quiet longest to today,\non a logarithmic axis. It is where you see the tail of things you have stopped thinking about.\n\nEvery card carries two buttons that save you a trip: **Terminal** opens one *already inside that\nproject's folder*, and **Editor** opens its status document, for when you want to fix a line\nyourself. The editor is **the one you have chosen**: Frontstep asks the system, it does not name a\nprogram. For the terminal there is no such question to ask outside Windows and Debian-like Linux, so\nelsewhere it opens the one your desktop ships with — and one line of configuration overrides it.\n\nLight and dark, following the system unless you say otherwise, and mobile friendly too. The colours are not chosen by eye — the contrast ratios are computed from the stylesheet's own tokens by a test.\n\n**macOS and Linux**\n\n```\n# 1. Download and run Astral's installer for uv — one program that brings its own Python\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n\n# 2. Install Frontstep with it, straight from this repository\nuv tool install https://github.com/GiovanniCst/frontstep/archive/main.zip\n\n# 3. Start it\nfrontstep serve\n```\n\n**Windows**, in PowerShell\n\n```\n# 1. Download Astral's installer for uv and run it (irm fetches, iex executes) — uv brings its own Python\nirm https://astral.sh/uv/install.ps1 | iex\n\n# 2. Install Frontstep with it, straight from this repository\nuv tool install https://github.com/GiovanniCst/frontstep/archive/main.zip\n\n# 3. Start it\nfrontstep serve\n```\n\nOpen a new terminal after step 1, since a shell only picks up a new PATH when it starts. If\n`frontstep`\n\nis still not found, `uv tool update-shell`\n\nfixes it for good — and meanwhile\n`uv tool dir --bin`\n\nprints the folder it was installed into, so running it from there works right\naway.\n\nWhat step 1 actually does:it downloads a script from`astral.sh`\n\nand runs it immediately, without saving it or showing it to you. It needs no administrator rights and installs into your own profile.[Astral]makes uv, Ruff and ty, andis now part of OpenAI([March 2026]) — so that is who you are trusting for the length of that one line. uv itself is open source (MIT/Apache-2.0), but reading the source is not the same as reading what a URL serves you today. If you would rather not, the alternatives below install uv from a package manager instead, or skip it entirely.\n\n## Why not `pip install`\n\nBecause on a fresh machine it usually cannot run. Measured on stock images, August 2026: Debian 13\nand Ubuntu 24.04 ship python3 with neither `pip`\n\nnor `ensurepip`\n\n— so even `python3 -m venv`\n\nfails;\nFedora and Arch base images have no Python at all; and where pip does exist, Debian, Fedora and\nHomebrew refuse to install into the system Python (PEP 668).\n\nuv is one static binary with the same three lines everywhere, and the CI runs the first two of them on six distributions plus Windows and macOS — so this page cannot quietly stop being true.\n\nThat is the whole installation. There are no questions to answer first: `serve`\n\nstarts without a\nconfiguration and prints an address with a key on the end —\n\n```\nFrontstep 0.5.2 — not set up yet.\n\n  Open this, and it will ask you where your projects are:\n\n    http://127.0.0.1:9015/?key=…\n```\n\n— and the page offers the folders that are really on your machine, each with **how many folders\ninside already have a status document**. Pick one, press Start, and the dashboard is there. Nothing\nto restart.\n\nThe key is in the address because that page decides which folders Frontstep may read and write. Whoever can see the terminal started the program; on a shared machine, being able to reach a port is not the same thing.\n\nPrefer a terminal? `frontstep init`\n\nasks the same questions there and writes the same file.\n\nNeither way writes inside your existing projects. `init`\n\nalso creates one example folder of its own,\nwhose status document doubles as the tutorial.\n\nIn a container, setting up from the browser works too — but the folders it offers are the container's, so the paths it writes are only right if what you mounted is mounted at the same place.\n\n**It is a local, single-user application.** No authentication, no accounts, no multi-user. It binds\nto `127.0.0.1`\n\nfor that reason and says so out loud if you tell it to bind anywhere else.\n\nBinding to localhost is not the same as being private, though, so two checks stand in front of everything that writes:\n\n**it only answers to the name you dialled it by.** Localhost always works; any other name has to be listed in`allowed_hosts`\n\n. This is what stops a site whose domain resolves to`127.0.0.1`\n\nfrom reaching the dashboard as if it were the dashboard;**every write carries a token the page is given when it is rendered.** A form on another site cannot send that header, and another account on the same machine has never been served the page. The token lives in memory and changes at every restart, so a tab left open across one is told to reload rather than quietly failing.\n\nReads are covered by the first check, writes by both. Nothing defends against a program running as you — it can read your files directly, so there is nothing a token could add.\n\nNothing to provision: no database, no service to run, no account anywhere.\n\nPython |\n3.11 or newer — that is where `tomllib` arrived, and the configuration is TOML. uv brings its own, so this only constrains you if you install another way |\nDependencies |\nthree: `Flask` , `mistune` , `MarkupSafe` . `gunicorn` is optional, as the `server` extra, and only if you would rather not use Flask's own server |\nOperating system |\nLinux, macOS, Windows. The CI runs the suite on Ubuntu (3.11→3.14) and on Windows and macOS at both ends of that range, and installs it from the lines above on Debian 13, Ubuntu 24.04, Fedora, Arch, openSUSE and Alpine |\nBrowser |\nany current one. The page is server-rendered HTML with a little vanilla JavaScript — no framework, no build step, and it fetches nothing from the internet |\nDisk |\na few MB, plus whatever Python you install it under |\n\nFrontstep reads the folders you point it at, and everything it writes is listed under **What the\npage can write** below. It never needs root, and it binds to `127.0.0.1`\n\n.\n\nFrontstep is an ordinary Python package: **anything that installs one will install it.** These are\nnot covered by the CI the way the three lines above are, so they are offered as directions rather\nthan promises.\n\n**Get uv from a package manager**, if you would rather not pipe a script into a shell — then carry\non from step 2 above:\n\n```\nbrew install uv                        # macOS\nwinget install --id=astral-sh.uv -e    # Windows\npipx install uv                        # anywhere pipx is\n```\n\n**Skip uv altogether.** In a virtual environment you made yourself, where PEP 668 has no say:\n\n```\npython3 -m venv ~/.venvs/frontstep\n~/.venvs/frontstep/bin/pip install https://github.com/GiovanniCst/frontstep/archive/main.zip\n~/.venvs/frontstep/bin/frontstep serve\n```\n\nThis one uses **your system's Python**, so it is the one that can fail for a reason none of the\nothers have: `python3 -m venv`\n\nbuilds the environment around whatever version you happen to have,\nand if that is older than 3.11 the install stops with *\"requires a different Python\"*. Tried on a\nmachine running 3.10 and that is exactly what it said. `python3 --version`\n\nfirst, or let uv bring\nits own.\n\n**From a clone**, which is also how you would run it to change it — see `CONTRIBUTING.md`\n\n:\n\n```\ngit clone https://github.com/GiovanniCst/frontstep && cd frontstep\nuv tool install .          # or: pip install -e .\n```\n\n**With Docker**, without installing Python anywhere: see [its own section](#in-a-container) below.\n\nWhichever way you choose, `frontstep doctor`\n\nsays what this machine has and what it is missing.\n\nNo image is published yet, so this means cloning and building. `docker-compose.yml`\n\nis commented\nline by line, and the whole thing is:\n\n```\ngit clone https://github.com/GiovanniCst/frontstep && cd frontstep\n\n# The config the container mounts is ./config.toml — `init` writes elsewhere\n# unless you say so, and Docker turns a missing mount source into a DIRECTORY,\n# which fails in a way that does not name the cause.\nfrontstep init --config ./config.toml --root /projects\n\nFRONTSTEP_ROOT=~/code docker compose up -d      # → http://127.0.0.1:9015\n```\n\n`--root /projects`\n\nthere is the path **inside** the container, and `FRONTSTEP_ROOT`\n\nis where those\nfolders really are on your machine — the two are the same folder seen from two sides. Then add\n`host_path`\n\nto that root, for the reason below.\n\n**Two things have to be mounted, and neither can be guessed**: the folders your projects are in, and\nthe configuration. The projects mount is not read-only — Close, Pause and the pencil write in there.\n\nThe catch worth knowing before you start is that a path inside the container is not a path on your machine, and the cards show you paths you are meant to be able to use:\n\n```\n[[roots]]\npath = \"/projects\"        # where they are INSIDE the container — this is what Frontstep reads\nhost_path = \"~/code\"      # where they are on YOUR machine — this is what the cards show and copy\n```\n\nWithout `host_path`\n\nevery card reads `/projects/…`\n\nand **Path** copies an address that exists\nnowhere outside the container.\n\n**What a container cannot do**, whatever you mount: there is no desktop in there, so the server\ncannot open a terminal or an editor. **Terminal** becomes a `frontstep://`\n\nlink, which the handler\nin [ contrib/windows-wsl/](/GiovanniCst/frontstep/blob/main/contrib/windows-wsl) answers once registered;\n\n**Editor disappears**, because from a page the only way to start a program is a registered URI scheme and none of them means \"whatever this system opens\n\n`.md`\n\nwith\"; **Path** still copies the host path, and still works.\n\nTwo more things the compose file already does, and that are worth keeping if you write your own:\n\n**it publishes on** Frontstep has no authentication and writes in the files it is shown: the second form would put it on every interface of the host;`127.0.0.1:9015`\n\n, not on`9015`\n\n.**it runs as a fixed uid**(10001). Whatever writes in your files has to be able to write in your files:`user: \"${UID}:${GID}\"`\n\nis the simplest way to make that yourself, and it is in the file, commented.\n\nSet `TZ`\n\ntoo — a container on UTC quietly shifts \"today\" by a couple of hours at the ends of the\nday, which is exactly when a status document gets written.\n\nInstalling on the machine avoids all of this, and is three lines with no daemon.\n\nA project shows up on the dashboard as soon as it has a `CURRENT_STATUS.md`\n\nwith this header:\n\n```\n# My project\n\n**Status:** active | waiting | paused | done\n**Updated:** 2026-08-14\n**Next step:** one line, imperative: what happens next session\n**Waiting for:** a person or an event — empty if the ball is yours\n**App:** what the product is called, not the folder\n**Description:** what this project is, in one line\n```\n\nTwo optional fields: `Tags:`\n\nfor filtering, and `Prod:`\n\nwhen the project is deployed.\n\n**The status is declared, the staleness is measured.** You never write \"stalled for 12 days\" — the\ndashboard computes that from `Updated`\n\n. You only declare whose turn it is.\n\nThe dashboard is a reader. Everything it can write is a button you press, and this is all of them:\n\n| From the page | What it writes | Where |\n|---|---|---|\nClose / Pause on a card |\nthe `Status` line, and `Updated` with it |\nthat project's status document |\nthe pencil next to Next step |\nthe `Next step` line, and `Updated` with it |\nthat project's status document |\nNew project |\na folder and a status document — plus `AGENTS.md` , if you tick it |\nunder a root you declared |\nSkill: Claude |\nthe agent skill | `~/.claude/skills/frontstep/` — the only thing it writes outside your projects and its own configuration |\n| the first run | the configuration file | where your system keeps configuration |\n\nThe first two rewrite **one named line** and nothing else: atomically, keeping the file's owner and\npermissions, and keeping the language and the exact field names the document already uses. A command\nonly appears where there is a line to rewrite — no `Status`\n\nline, no Close button.\n\nThe other three create files rather than editing them, and none of them overwrites: **New project**\nrefuses a folder that already has a status document, `AGENTS.md`\n\ngets our section between two\nmarkers and keeps everything you wrote outside them, and the skill goes to a path that is ours by\nname.\n\nWould you rather it never touched your files?\n\n```\nwritable = false        # in your config.toml\n```\n\nEvery one of them then disappears from the page **and** the routes behind them answer `403`\n\n— the\ninterface is not the barrier. Note that it also turns off **Terminal** and **Editor**: `launch`\n\nfollows `writable`\n\nunless you set it yourself, because somebody who asked for a dashboard that does\nnot touch their files did not ask for one that starts programs.\n\nThree more buttons on each card write nothing. **Path** copies the path. **Terminal** and **Editor**\nopen the project on your machine, and they work with nothing installed and nothing to register: the\nbrowser cannot start a program, but the server runs on the same machine as you, so the button asks\nit to.\n\n**The editor is your own default**, and Frontstep does not choose it: it asks the system to open the\ndocument, the way double-clicking it would — `xdg-open`\n\non Linux, `open -t`\n\non macOS, `os.startfile`\n\non Windows. The answer is a choice you made in your own settings years ago, and no editor is named\nanywhere in the code.\n\n**The terminal cannot always be asked for**, and that is a limit worth stating rather than glossing.\nWindows has a default terminal, and Debian-like Linux has `x-terminal-emulator`\n\n, which is that same\nquestion in symlink form — there, it is your choice that opens. Everywhere else there is nothing to\nask, so Frontstep opens the terminal your desktop shipped with, by name: Ptyxis, GNOME Console,\ngnome-terminal, konsole, xfce4-terminal, mate-terminal, xterm, and `Terminal.app`\n\non macOS. That is\nwhat is certainly installed, not what you would have picked — so if it is wrong, name yours below.\n`frontstep doctor`\n\nsays which one it would use.\n\nName your own if the guess is wrong. A **list**, one argument per item; `{}`\n\nis the project folder\nand `{file}`\n\nits status document:\n\n```\nterminal = [\"kitty\", \"--directory\", \"{}\"]\neditor   = [\"subl\", \"{}\"]\nlaunch   = false        # or: open nothing at all\n```\n\nOpening needs `bind`\n\nto be a loopback address, whatever `launch`\n\nsays — a dashboard reachable from\nthe network that starts a terminal on the machine it runs on is a remote shell. In a container it is\noff for the same reason, and nothing is lost: there is no terminal in there to open. When it is off,\nthe two buttons fall back to what they were before — a `vscode://`\n\nlink, and the `frontstep://`\n\nhandler in `contrib/`\n\n— which still work exactly as they did.\n\n```\nfrontstep doctor\n```\n\nSays what this machine has and what it is missing: the Python version, whether the command can be\ntyped or only reached through `python -m`\n\n, where the configuration is or would go, whether the port\nis free, which of your roots have projects in them, and **which programs the Terminal and Editor\nbuttons would open** — those two vanish rather than fail when there is nothing to open with, and a\nbutton missing without explanation is its own kind of bug.\n\nIt exits non-zero only for things that actually stop it working. Everything it checks is something that has gone wrong on a real machine; nothing is there because it might.\n\nOn a machine that has `~/.claude`\n\n, the first run offers this as a **tick, already ticked** — the\nskill is installed before you ever see the dashboard. After that, two buttons in the top bar,\n**Skill: Claude** and **Skill: other agents**, do the same thing and say where the file goes.\n\nThe two are not the same job, because the two agents do not read the same file:\n\n| reads | where it goes | |\n|---|---|---|\nClaude Code |\nan Agent Skill | `~/.claude/skills/` — once for every project on the machine |\nevery other agent |\n`AGENTS.md` |\none per project, at its root —\n|\n\nClaude Code reads\n\n`CLAUDE.md`\n\n,not`AGENTS.md`\n\n—[its own documentation says so]. That is why the skill exists and why the two buttons are separate. Installing`AGENTS.md`\n\nin a project does nothing for Claude; the skill covers it, and covers every other project at the same time.\n\nFor a project being created here, **New project** carries an **Add AGENTS.md** tick that writes it\nfor you. For one that already exists, the same from a terminal:\n\n```\nfrontstep skill --install claude   # Agent Skills (~/.claude/skills/)\nfrontstep skill --install agents   # AGENTS.md, in the current folder\nfrontstep skill --print            # print the Claude skill instead of installing\nfrontstep skill --print --install agents   # print the AGENTS.md section instead\n```\n\n`--install agents`\n\nwrites its section between two markers, so running it twice replaces that\nsection instead of stacking a second copy, and everything outside them is left exactly as it was —\nan `AGENTS.md`\n\nyou already wrote keeps what it says.\n\nThen, to populate projects you already have, ask your agent:\n\nRead the Frontstep skill and add a\n\n`CURRENT_STATUS.md`\n\nto every project in`~/code`\n\n. Take the description from each project's README if there is one; otherwise look at the files and infer it.\n\nIf you would rather not involve an agent, `frontstep adopt`\n\ncreates minimal status documents in the\nfolders you pick — enough to make the projects appear, so you can fill them in from there.\n\n`docs/CONVENTION.md` |\n\n`CONTRIBUTING.md`\n\n`CHANGELOG.md`\n\n`contrib/`\n\n`frontstep://`\n\nhandler — the fallback now, for when the server may not open a terminal itself**Apache-2.0.** Use it, change it, sell it, build on it.\n\nTwo things travel with it, and both are short:\n\ncarries the attribution, and section 4(d) of the License requires it to be kept. In a single-page application the place such notices appear is the foot of the page, so that is where it lives:`NOTICE`\n\n**G.J.C. 🧠**. Add your own name beside it; do not put yours in its place. A fork's footer says`Forked from a project by G.J.C. 🧠`\n\nand links back.— the code is free, the name travels with one condition. A published fork`TRADEMARK.md`\n\n**keeps Frontstep in its name and adds its own**:`Frontstep-Evolution`\n\n,`Go-Frontstep`\n\n,`Goofie-Frontstep`\n\n. So the genealogy stays readable and the two builds stay told apart — which matters because this thing writes into your files, and a name shared by two programs that behave differently promises nothing.", "url": "https://wpnews.pro/news/show-hn-frontstep-v0-5-2", "canonical_source": "https://github.com/GiovanniCst/frontstep", "published_at": "2026-08-15 13:34:14+00:00", "updated_at": "2026-08-15 13:40:40.562506+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-tools"], "entities": ["FrontStep", "Astral", "OpenAI", "GiovanniCst", "GitHub", "uv"], "alternates": {"html": "https://wpnews.pro/news/show-hn-frontstep-v0-5-2", "markdown": "https://wpnews.pro/news/show-hn-frontstep-v0-5-2.md", "text": "https://wpnews.pro/news/show-hn-frontstep-v0-5-2.txt", "jsonld": "https://wpnews.pro/news/show-hn-frontstep-v0-5-2.jsonld"}}