{"slug": "show-hn-estela-rebuild-billable-hours-from-your-claude-code-and-codex-logs", "title": "Show HN: Estela – Rebuild billable hours from your Claude Code and Codex logs", "summary": "Estela, a new open-source CLI from developer jdleonruiz, rebuilds billable hours and AI costs by reading the session logs Claude Code writes to ~/.claude/projects/, Codex writes to ~/.codex/sessions/, and GitHub Copilot writes to VS Code's workspaceStorage, plus local Git history. The tool runs entirely locally with no account and requires Node 22.5 or later, and it reports measured hours and real AI cost for Claude Code and Codex while leaving models missing from its price catalog with an empty cost rather than an invented one. Estela installs via `npx estela setup` and does not install hooks, inspect processes, store prompt content, or send data anywhere.", "body_md": "**English** · [Español](https://github.com/jdleonruiz/estela-cli/blob/main/README.es.md)\n\nDevelopment time tracking you **don't have to fill in**. Estela reads what your\nAI agents and your Git already wrote to disk and rebuilds where your time went,\nalong with what the AI cost.\n\n```\nnpx estela setup\n```\n\nTwenty seconds later you have the last few months of your history. No account, no card, and nothing leaves your machine.\n\n<sub>The local dashboard (`estela web`), here with the made-up data from `estela demo`.</sub>\n\nA timer you have to remember to start always fails. And with an AI agent, time isn't measured in keystrokes anymore: it goes into writing the prompt, reading what comes back, and trying it out.\n\nBut that work **leaves a trail**. Claude Code saves every session in\n`~/.claude/projects/`, Codex in `~/.codex/sessions/` and GitHub Copilot in VS\nCode's `workspaceStorage`, with their model and tokens. Git records when you\ncommitted and what. Estela reads all of it and lines it up.\n\nCodex gives you **measured** hours and real AI cost, same as Claude Code. A\nmodel that isn't in the price catalog gets an empty cost rather than an\ninvented one, and `estela doctor` tells you how many turns are in that\nstate.\n\nGitHub Copilot in VS Code (chat and agent mode, on Windows, macOS and Linux) gives measured hours too: when each request starts and when it finishes. It has no AI cost, because Copilot is a flat subscription, and inline completions leave nothing on disk, so that time comes from your commits.\n\nWhat it doesn't do:\n\n- **It doesn't install hooks.** Your`husky` and`lefthook` stay untouched, and\nyour commit messages aren't modified. An identifier written into history\ncan't be taken back once it's pushed.\n- **It doesn't inspect processes or your terminal.** It reads files that already\nexist.\n- **It doesn't store the content of your prompts.** Only when, how much, and\nwith which model.\n- **It doesn't send anything anywhere.** The free plan is entirely local.\n\nKeep it. [ccusage](https://github.com/ryoppippi/ccusage) reads the same files\nand tells you what the AI cost you; Estela tells you how many hours you worked\nand what to bill the client. Both only read, so they run side by side.\n[Side-by-side comparison](https://getestela.dev/en/vs/ccusage).\n\nYou need **Node 22.5 or later** (for `node:sqlite`).\n\n```\nnpx estela setup     # detects agents and repositories, rebuilds your history\nnpx estela web       # opens the dashboard at http://localhost:4319\nnpx estela doctor    # checks your data and flags anything wrong\nnpx estela --version\n```\n\nIf that's where you already are, Estela installs without leaving it:\n\n```\n/plugin marketplace add jdleonruiz/estela-cli\n/plugin install estela@estela-cli\n```\n\nThen ask in plain words — *\"how many hours have I put into this?\"*, *\"what can\nI bill for this month?\"*, *\"show me an example first\"* — and Claude Code reaches\nfor the right command on its own. The explicit forms are `/estela:setup`,\n`/estela:status` and `/estela:demo`.\n\nThe demo fills a whole dashboard with made-up data and touches nothing of yours, which is the honest way to look at a program that wants to read your transcripts: see what it does before you let it near your own history.\n\nNo Claude Code, Codex or Copilot? It still works: without transcripts, Estela rebuilds your time from your commits alone, and marks it as estimated.\n\n`npm` doesn't update global installs on its own. If you installed with\n`npm install -g estela`, Estela tells you when there's a newer version (it asks\nnpm at most once a day, in the background, without blocking anything); update\nwith `npm install -g estela@latest`.\n\n`setup` asks no questions and doesn't overwrite anything you've set up by hand:\nyou can run it again.\n\nEstela speaks English and Spanish, following your system's language. Force one\nwith `--lang en` on any command, or `ESTELA_LANG=en` for good.\n\nEstela runs on Windows. It's tested by hand on a real machine, not in CI, so if\nsomething looks off, [open an issue](https://github.com/jdleonruiz/estela-cli/issues).\nTwo things trip people up before Estela even starts:\n\n- **`npm : ... cannot be loaded because running scripts is disabled`** —\nPowerShell blocks npm's own scripts by default. Once, and only for your user:`Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` .\n- **`npm error Class extends value undefined is not a constructor or null`** —\nyou have two Node installs fighting over the same folder, usually`nvm-windows` plus a Node from the installer or`winget` . Keep one: uninstall\nthe standalone Node, then`nvm install lts` and`nvm use lts` from an\nadministrator terminal.`where.exe npm` should list a single path.\n\nProjects are created as internal and without a rate, because making one up would produce fake numbers from the first minute. When one belongs to a real client:\n\n```\nestela client add --id acme --name \"ACME\" --currency EUR\nestela project add --id acme-web --client acme --name \"ACME website\" --repo ~/dev/acme-web\nestela rate set --project acme-web --rate 50\n\nestela author --project acme-web      # which email you commit with there\nestela report --project acme-web --cutoff 2026-08-31 --dry-run\n```\n\n**`estela author` matters more than it looks.** In a client's repository you\nalmost never commit with your global email, and without telling Estela it\ncaptures three commits out of seventeen hundred.\n\n**The language is the client's, not your terminal's.** What your client receives\n(the PDF, the CSV, the report and the published panel) comes out in the language\nyou set for that client, so you can use Estela in Spanish and bill a company in\nEnglish:\n\n```\nestela client add --id acme --name \"ACME\" --currency EUR --language en\n```\n\nWithout it Estela uses your terminal's language, and tells you when it does.\nRunning `client add` again keeps the language you set (`--language auto` removes\nit), and `--lang en` on a single command overrides everything. A published panel\nis a static file, so to change its language you republish it.\n\nThe report backs up your work with hours and commits. It isn't an invoice: Estela doesn't issue tax documents, so attach it to your own.\n\n**A cutoff doesn't mean you stop working on the project.** Without\n`--dry-run`, `estela report --cutoff <date>` marks those hours as invoiced\nand keeps letting new hours pile up for the next cutoff:\n\n```\nestela report --project acme-web --cutoff 2026-08-31 --pdf august.pdf\n# ...keep working as usual...\nestela report --project acme-web --cutoff 2026-09-30 --pdf september.pdf\n```\n\nWhen a project is genuinely done, close it — nothing gets deleted, and if\nit captures work again (a teammate, or you without remembering), `estela doctor` flags it instead of silently losing it:\n\n```\nestela project close --project acme-web\nestela project reopen --project acme-web   # if you need to pick it up again\nestela login --email you@example.com    # once\nestela publish --project acme-web\n```\n\nThis uploads a read-only dashboard with an unguessable link, hosted on\ngetestela.dev — no server of your own needed. It shows hours and commits;\n**never your rate or your AI usage**, because as long as you're the one paying\nfor it that spend is yours, and a client who knows which part an AI generated\nhas a new argument for negotiating your rate down.\n\nPublishing again from the same machine reuses the link automatically. From a\ndifferent machine, pass `--token` with the existing one, or your client ends up\nwith a dead link. The Free plan allows one published dashboard at a time; Pro\nand Teams have no limit.\n\nOn a flat subscription, your real spend isn't the sum of the tokens: it's the fee split across what you used.\n\n```\nestela subscription add --id max --name \"Claude Max\" --fee 100\nestela ai-cost\n```\n\nCache is counted separately because it's usually most of the bill — ignoring it underestimated spend fivefold.\n\nMeetings, travel, research, and development without an agent that didn't leave commits either:\n\n```\nestela log --project acme-web --hours 1.5 --kind meeting --what \"Weekly check-in\"\n```\n\nAn import never touches them.\n\nIf you coded by hand, your commits are still a trail: Estela infers the time\nfrom them and marks it as **estimated**, so you know which part of your hours is\nmeasured and which is assumed. The estimate errs on the short side on purpose:\nthese hours end up in a report someone pays for.\n\n|  | Free | Pro | Teams | \n|---|---|---|---|\n| Everything above, locally | ✓ | ✓ | ✓ | \n| Sync across machines | — | ✓ | ✓ | \n| Hosted dashboards at once | 1 | unlimited | unlimited | \n| **Measured** team hours | — | — | ✓ | \n| AI budget per project | — | — | ✓ | \n| Projects | unlimited | unlimited | unlimited | \n\nPro is one person on several machines; Teams is several people.\n\nTeams is billed **per measured person** — $10/month, €10 in the eurozone,\nthree-person minimum — not per\nproject. Projects are unlimited on purpose: if each one cost money you'd end up\nmeasuring only two or three, which is the opposite of what this is for. Someone\non several projects is paid for once.\n\nAI cost is reported **per project, never per person**: what each person spends\nout of their own pocket is theirs. Paying per seat doesn't change that.\n\nMore at [getestela.dev](https://getestela.dev/en/).\n\n```\nnpm install\nnpm test\n```\n\nNode 22 and **zero runtime dependencies**, on purpose: nobody installs a program\nthat reads their transcripts if they can't audit it, and an empty dependency\nlist can be audited in an afternoon.\n\nIssues and pull requests are welcome, and the\n[good first issues](https://github.com/jdleonruiz/estela-cli/labels/good%20first%20issue)\nare a good place to start. One thing to know so nobody's put off: this\nrepository mirrors the open part of a larger repo where the paid service also\nlives, which is why each commit here is a release. I review PRs here and apply\nthem to the main repo keeping you as the author, and the next release commit\ncredits you as co-author. PRs welcome — I merge them into the main repo.\n\nEverything that installs on your machine is open source under the MIT license:\nthe CLI, what reads your transcripts and your git, what calculates hours and\ncost, and the dashboard that `estela web` opens. It's exactly what\n`npm install estela` downloads, and you can read it at\n[github.com/jdleonruiz/estela-cli](https://github.com/jdleonruiz/estela-cli).\nEach npm version has a matching tag there.\n\nWhat **isn't** here is the paid service: the server that syncs your machines and\nthe one behind team projects. That part is closed, and it's what keeps the\nproject going.\n\nThe split isn't an accident. The free plan works entirely without an account, a card, or a network connection, and that claim is worth nothing if you have to take it on faith: with the code in front of you, you can check for yourself that nothing leaves your machine.\n\nThe test fixtures are made up on purpose. The cases come from real repositories — that's why they cover messes nobody would think of — but neither a client's team roster nor how much each of its people commits belongs in a public repository.", "url": "https://wpnews.pro/news/show-hn-estela-rebuild-billable-hours-from-your-claude-code-and-codex-logs", "canonical_source": "https://github.com/jdleonruiz/estela-cli", "published_at": "2026-09-29 15:39:00+00:00", "updated_at": "2026-09-29 15:47:57.036520+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-agents", "ai-products"], "entities": ["Estela", "Claude Code", "Codex", "GitHub Copilot", "VS Code", "jdleonruiz", "ccusage", "Node 22.5"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-estela-rebuild-billable-hours-from-your-claude-code-and-codex-logs", "markdown": "https://wpnews.pro/news/show-hn-estela-rebuild-billable-hours-from-your-claude-code-and-codex-logs.md", "text": "https://wpnews.pro/news/show-hn-estela-rebuild-billable-hours-from-your-claude-code-and-codex-logs.txt", "jsonld": "https://wpnews.pro/news/show-hn-estela-rebuild-billable-hours-from-your-claude-code-and-codex-logs.jsonld"}}