npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

fastcoder

v1.4.0

Published

Fastcoder — CLI tool to register, inspect and report on local development projects.

Readme

Fastcoder

CLI tool to register, inspect and report on local development projects.

Features

  • Register and remove projects (persisted in SQLite at ~/.fastcoder/fastcoder.db)
  • Read each project's tasks folder (default .docs/, configurable via TASKS_FOLDER in .env or the global settings — e.g. .docs/config.json with a checks array of shell commands)
  • Run shell commands inside any registered project
  • Run periodic check passes and store reports
  • Drive coding tasks through stage folders (todo → doing → validate → test → document → done) and implement them with Claude Code
  • Run a single do that executes one task through the full flow (continue, specification, do, validate, test, document, periodic) in priority order, across one project or every project
  • Track every Claude Code run as an execution (status, tokens, usage-limit headroom)
  • Retry failed tasks automatically and quarantine repeat failures in a failures/ stage
  • Record exceptions for interrupted runs and an action log of every step
  • A web-UI Chat on the Claude Agent SDK: saved chats linked to a project and an AI account, streamed replies, and Fastcoder actions (tasks, runs, settings) with confirmation for destructive ones
  • Full web interface (React + Vite + Express, TypeScript) exposing every feature — manage projects, the task board, executions, exceptions, logs, reports, the scheduled job and settings
  • Install/remove a system scheduled job (launchd / crontab / Task Scheduler) that runs the flow on a schedule, with a health check that tells you when the job is installed but not actually running and a one-click repair

Install (global CLI)

Prerequisites

  • Node.js ≥ 22 (Node 22 LTS or Node 24 LTS recommended). Older Node versions are unsupported — Node 18 reached end-of-life in April 2025 and better-sqlite3 no longer ships prebuilt binaries for them.
  • A C/C++ toolchain only if no prebuilt binary exists for your Node version/platform (see Troubleshooting below). Prebuilt binaries are shipped for the recommended Node LTS versions, so most users do not need a compiler.

Install

cd /Users/username/projects/fastcoder
npm install
npm install -g .

Now fastcoder is on your PATH.

Update the local CLI (without publishing to npm)

To test your local working copy as the global fastcoder command — without ever pushing to npm and reinstalling from there — rebuild and reinstall from the project directory. Pick whichever workflow fits how often you iterate:

One-off update (recommended). Reinstall the current local code over the global install. --force ensures npm overwrites the existing global package even when the version number in package.json has not changed:

cd /Users/username/projects/fastcoder
npm run build:all       # compile dist/ AND web-ui/dist (full version)
npm install -g . --force

Or, equivalently, via make:

make update-global-full   # build web UI + CLI, then reinstall globally (--force)

make update-global-full rebuilds the web UI and the CLI before reinstalling. If you only changed CLI/src/ code, use make update-global (rebuilds the CLI only). The individual steps are also available as make build-web and make build.

Why build:all / build:web? npm install -g . runs the prepare script, which only compiles the TypeScript CLI into dist/. It does not rebuild the React web interface. If you changed anything under web-ui/ and want the full local version, build the web bundle first (npm run build:web) so the packaged web-ui/dist is up to date. If you only changed CLI/src/ code, npm install -g . --force alone is enough.

Live-linked update (best for frequent iteration). npm link symlinks the global fastcoder to this folder, so you only need to recompile — no reinstall:

cd /Users/username/projects/fastcoder
npm link                 # link once; global `fastcoder` now points here
npm run build:all        # recompile after each change (re-run as needed)

Re-run npm run build (CLI) or npm run build:web (web UI) after edits and the global fastcoder immediately reflects the rebuilt output. Run npm unlink -g fastcoder (or make uninstall-global) to undo the link.

No-install run. To execute the local code directly without touching the global install at all, run it straight from source or the compiled output:

make dev                 # run the CLI from TypeScript via ts-node
node bin/fastcoder.js    # run the compiled dist/ build
npm start                # same as `node bin/fastcoder.js`

Troubleshooting install

If npm install (or npm i -g fastcoder) fails while building better-sqlite3 with an error like make: cc: No such file or directory or prebuild-install warn install No prebuilt binaries found, the native SQLite addon is falling back to compiling from source because no prebuilt binary matches your Node/OS combination — and the system has no C compiler. Fixes (pick one):

  • Use a Node version with a prebuilt binary (cheapest). Switch to Node 22 LTS or Node 24 LTS:

    nvm install 22 && nvm use 22
    npm i -g fastcoder
  • Install the build toolchain so the source compile succeeds:

    • Linux / WSL (Debian/Ubuntu): sudo apt-get update && sudo apt-get install -y build-essential python3
    • macOS: xcode-select --install
    • Windows (PowerShell as admin): npm i -g windows-build-tools (or install "Desktop development with C++" from the Visual Studio Build Tools)

    Then re-run npm i -g fastcoder.

Lint & format

npm run lint:all           # ESLint check, root + web-ui
npm run lint-fix:all       # ESLint --fix, root + web-ui
npm run cs-check           # Prettier --check
npm run cs-fix             # Prettier --write
npm --prefix web-ui run typecheck   # tsc -b, no emit

See .docs/guidelines/code-linting.md for the full script table, config locations, and severity policy.

Quick start

fastcoder register --name my-app --path /path/to/repo
fastcoder list
fastcoder check
fastcoder doctor           # environment health: dependencies, tools, settings
fastcoder serve            # http://localhost:4787
fastcoder cron:install     # every 15 minutes by default (macOS/Linux/WSL/Windows)
                           # first checks `claude` is runnable from a cron-like
                           # environment (warn-only; skip with --no-preflight)
fastcoder cron:status      # prints `health: ok` or `health: FAILED — {reason}`
                           # and `Last tick: …` (unhealthy after 3 missed intervals)
                           # also unhealthy when the job's script no longer exists
fastcoder cron:repair      # re-installs the job when the health check fails
fastcoder run my-app "git status"

Run without arguments for an interactive menu:

fastcoder

Task workflow

Fastcoder drives coding tasks through a set of stage folders inside each project's tasks folder (default .docs/tasks/; change the name via the TASKS_FOLDER variable in .env or in the global settings). Create the structure once:

fastcoder init my-app

This creates tasks/{backlog,ai-backlog,specification,todo,doing,blocked,validate,test,document,done,failures,garbage,periodic}. Drop a Markdown task file (one feature per file) into tasks/todo/ describing what you want done.

init also installs the fastcoder Claude helpers into the project (skipping any already present): the fcd-* slash commands into .claude/commands/, the bundled periodic task files into <tasks-folder>/tasks/periodic/, a starter root sonar-project.properties keyed to the project folder name (never overwritten — this is what the bundled sonarqube.mk scan commands read sonar.sources/ sonar.tests/coverage paths from), and the bundled skills flat at .claude/skills/<skill>/SKILL.md — the only layout Claude Code discovers (currently fcd-usability, sonarqube-setup, sonarqube-todo-tasks, fix-lint, makefile-setup, ai-backlog-evaluation, fcd-worktree-creation and fcd-git-worktree). The fcd-git-worktree skill teaches an agent to create, set up (linking the application's own ignored dependencies and local config, recorded in <tasks-folder>/guidelines/git-worktree-setup.md), use and safely remove git worktrees under <tasks-folder>/worktrees/ with the plain git CLI. When that record exists, Fastcoder applies its "Link from the main tree" list itself each time it prepares a (WT-…) or per-task worktree, so those runs build and test without an agent setup step. The ai-backlog-evaluation skill scores each ai-backlog/ idea and then discards, promotes, splits or parks it for human approval; a promoted file is renamed {timestamp}_ai-promoted-{slug}[.step-1].md with a fresh timestamp, so AI-promoted tasks stand out from hand-written ones. Because promotion is unattended, a risky idea (breaking change, wide blast radius, possible data loss) is always parked for human approval whatever its value — value never overrides risk, and only low-risk ideas are auto-promoted. When an idea proposes several ways to do the same thing, the skill picks the option that fits the project and rewrites the idea file so that option is the single stated path (the rejected ones stay as a short annotated list); a human is asked only for the hard calls — close options, a product/cost trade-off or a choice that would be expensive to undo. It is driven by the bundled 005-ai-backlog-auto-evaluation(1Xday).md periodic task, which runs in manage-tasks mode (see below). A local V2 task record (.json in ai-backlog/ with its body under <tasks-folder>/tasks-source/) is first converted back to an ordinary backlog markdown file and then triaged; records it cannot convert are left untouched and listed as skipped (V2 record) in the run summary.

init never overwrites an existing file, so it cannot bring an older project up to date. Use update for that:

fastcoder update my-app             # refresh the bundled fastcoder assets
fastcoder update my-app --dry-run   # report what would change, write nothing

It refreshes the fastcoder-owned assets — the fastcoder-* commands and the bundled skills (including their references/) — to the version shipped with the installed fastcoder, creates any missing stage folder, and adds missing starter templates. Project-owned files (periodic task files, makefile modules, the root Makefile, the root sonar-project.properties, the guidelines README.md/index.md) are only ever added, never overwritten, and nothing is ever deleted. The same action is available in the interactive project menu as "Update structure", as the "Update structure" button on the web UI project page, and as "Update structure on all projects" on the Settings page (POST /api/projects/:id/update and POST /api/settings/tasks-folder/update).

It also seeds <tasks-folder>/guidelines/ with a README.md and an index.md (one line per guideline, saying why it exists) — neither is overwritten on re-init. The document step keeps both, and the project README, up to date; it never writes changelogs or step logs.

Tasks flow through the stage folders in this order:

ai-backlog → backlog → specification → todo → doing (.do) → validate → doing (.validate) → test → doing (.test) → document → doing (.document) → done

doing/ is the single active-processing folder for every step. While a file sits there its name carries a .{step} tag (.do, .test, .validate, .document) recording which step owns it; the tag is stripped when the step finishes and the file moves to the next queue folder. See .docs/guidelines/fastcoder-flow.md for the complete reference.

do — run the next ready task through the flow

fastcoder do my-app      # scope the flow to one project
fastcoder do             # global: span every project

do runs one task through the complete fastcoder flow. Each invocation tries every step in priority order and executes the first one that has work:

| Priority | Step | What it does | | -------- | --------------- | ------------------------------------------------------------------------------------------------------------------------ | | 1 | continue | Retries a task that failed on its first do attempt | | 2 | specification | Turns a raw brief in specification/*.md into todo/*.step-N.md plans, and archives the brief to done/*.specified.md | | 3 | do | Implements the next *.step-N.md from todo/ → moves to validate/ | | 4 | validate | Validates a task from validate/ → moves to test/ | | 5 | test | Writes/runs tests for a task from test/ → moves to document/ | | 6 | document | Generates docs for a task from document/ → moves to done/ | | 7 | periodic | Runs one due health-check task from periodic/ (stays in place) |

Periodic task files are permanent, read-only definitions — a run never writes into them. Each run prepends a newest-first entry to <tasks-folder>/logs/periodic-tasks-log.md (seeded by fastcoder init, never overwritten on re-init).

A periodic file only ever has one run in flight, even across processes: two cron ticks racing on the same due file resolve so that exactly one runs and the other skips silently, and running a periodic task on demand while its run is in flight is refused instead of starting a second one. A running periodic task also counts towards the global, per-project and per-stage parallel limits, so the flow skips the periodic step while a health check is still running.

By default a periodic run is report-only (it never fixes anything, it only files ai-backlog entries). A periodic file that contains the line Periodic-mode: manage-tasks opts into the second mode instead: the run may create, move, rename and delete markdown files inside <tasks-folder>/tasks/, but still must not touch source code or tests. The marker lives in the file content — there is no CLI flag or setting — and the periodic file itself is never moved or renamed in either mode.

Scheduling rule: project priority → step priority → project rotation tie-break. Projects marked priority are served first: the whole step chain is attempted against them, and only when none of their steps has work do the other projects run — so a priority project's document task beats a normal project's todo task, and while a priority project always has work the others stay idle (intended; unprioritize it to let them resume). Inside a group, steps have a fixed priority and the highest-priority step with work always runs; project rotation only breaks ties between otherwise-equal projects. A paused project never runs, priority or not, and the global pause stops every project at once — toggle it from the Pause Fastcoder / Resume Fastcoder button in the web UI header (Projects and Dashboard pages), the Global pause switch on the Settings page, the CLI config menu, or the globalPause field on GET/PUT /api/settings. See .docs/guidelines/fastcoder-flow.md for the full definition.

Technical blackout. A hold that stops every Claude-invoking step until a chosen end time, leaving only the Claude-free unblock recovery running. Declare or end it from the Technical blackout card on the web UI Settings page (end date, reason, description, Save / Clear) or through PUT/DELETE /api/settings/technical-blackout; the same card holds TIMEOUT_FOR_ERRORS, the blackout length applied when Claude returns a service error. fastcoder config prints the current blackout (or not set) and the Timeout for errors: {n} min line for a terminal-only check. While one is active — or while the global pause is on — a red banner at the top of every web UI page says so. The blackout ends by itself at its end time. See .docs/guidelines/technical-blackout.md.

Keep the machine awake during runs. While a flow step's Claude run is in progress, Fastcoder holds an OS sleep assertion bound to the run's process and released when it ends: caffeinate -i -s on macOS, systemd-inhibit on Linux, SetThreadExecutionState on Windows (no-op on WSL and inside the Docker container, which cannot keep the host awake). On by default; toggle it from the Settings page, the fastcoder config menu or the keepAwakeDuringRuns field on GET/PUT /api/settings. See .docs/guidelines/settings.md.

Per-task model override. A task file can pin the Claude model it runs on by adding a .{model} tag to its name — add-login.opus.step-1.md runs on opus regardless of the configured default. {model} is one of sonnet, opus, haiku, fable. The tag stays on the file through every stage, so the same model handles the task's do, test, validate and document steps.

The do step itself:

  1. Runs a check pass to inspect task status.
  2. If the project has a task that failed on a previous do, that task is retried first (see below). Otherwise it moves the first file in tasks/todo/ into tasks/doing/ tagged .do.
  3. Runs Claude Code against the task file in tasks/doing/ to implement it.
  4. On success, strips the tag and moves the file to tasks/validate/.
  5. On failure, the file stays in tasks/doing/ and an exception is recorded — pending when the run can be resumed (e.g. a usage limit was hit) or ignored when it cannot.

Failure retries. The next time the flow runs for a project with a failed task, the continue step resumes that task to analyse and fix the failure. If the retry succeeds the task moves to tasks/validate/; if it fails again the task is moved to tasks/failures/ and the exception is marked failed-solving.

Global do. With no project, fastcoder do considers every registered project, using Priority scheduling with round-robin tie-breaking: it walks projects starting from the one after the project executed last time, and stops at the first step with work, executes it and exits — so a scheduled fastcoder do makes steady progress across every project and every stage of the flow.

check — inspect status and preview the next do

fastcoder check my-app     # one project
fastcoder check            # all projects

check runs the project's configured check commands and reports task counts per stage. It also lists, in flow priority order, the files that are ready to execute in the next fastcoder do cycle — the one the next run will actually pick is marked ▶ (runs next), and steps disabled in settings are shown with a [step disabled] note:

report #1 my-app (project #1) — .docs found · files: 0 · checks run: 0 · tasks: … · next: do → add-login.step-1.md
  Ready for next `do` cycle:
  ▶ do              todo/add-login.step-1.md (runs next)
    validate        validate/fix-header.step-1.md
    test            test/cache-layer.step-1.md
    periodic        periodic/daily-project-health.md

doctor — check the environment

fastcoder doctor

Reports whether the machine has what fastcoder needs, grouped as Dependencies (Node.js vs. engines.node, Git, the Claude Code CLI), Recommended tools (Playwright CLI, GitHub CLI, a SonarQube MCP entry in the project's .mcp.json), Recommended settings (at least one AI provider account registered) and Task queues (every registered project's task-stage folders for a task file that sits in more than one stage at once, e.g. todo and doing). Each non-OK line carries a hint on how to fix it.

It is informative only: nothing it reports blocks anything, and the command always exits 0. Unlike check, which inspects a single project's task queue, doctor mostly inspects the machine — the Task queues group is the one project-aware exception. The same report is available over HTTP at GET /api/doctor and on the web UI's Doctor page (/doctor), which shows the same rows with a status badge and a Refresh button. See .docs/guidelines/doctor.md.

config — settings and AI provider accounts

fastcoder config

Prints the application settings and the registered AI provider accounts, then opens an interactive editor. Each account pairs a provider (Claude Code, Gemini CLI, GLM, …) with its own config dir, default model and enabled flag, and is printed as {name} ({provider}) — model {model} — {configDir or 'provider default'} — {enabled|disabled}. The "AI provider accounts" entry (also reachable as Manage AI provider accounts in the interactive menu) adds, edits, deletes an account and refreshes its usage limits. The same accounts are managed over HTTP under /api/ai-provider-accounts and on the web UI's AI Providers page. An enabled account whose 5-hour session usage reaches 90% is skipped when the flow picks who runs the next task, and shows up as a warning in the global alerts banner at the top of every web UI page until its session window resets. See .docs/guidelines/ai-provider-accounts.md and .docs/guidelines/settings.md.

executions — track Claude Code runs

Every Claude Code run started by do is recorded as an execution. An execution is in-progress while Claude runs and becomes success or fail when it ends, capturing token usage and remaining usage-limit headroom when available. Each execution also records the account's last known Claude Code utilization at the moment it started — the 5-hour and 7-day percentages, shown as limits {short}%/{long}% in the list and a Limits: line in the detail view (n/a when no snapshot is stored). The web UI shows the same pair in a Limits column of the executions table (— for a missing side):

fastcoder executions                          # recent executions
fastcoder executions -p my-app -s in-progress # what is still running
fastcoder executions 42                       # full detail of one execution

Execution statuses: in-progress, success, fail.

If a run is killed with its host process (machine sleep, reboot, crash) its in-progress row would otherwise stay open forever and keep blocking the flow. Every flow tick reconciles such rows: after 60 minutes with no live Claude process for that task, the execution is finished as fail with the reason abandoned: process no longer running (the row is kept, never deleted).

continue — resume interrupted runs

fastcoder continue my-app      # one project
fastcoder continue             # every project

continue re-runs Claude Code for each pending exception. A resumed run that completes flips the exception to solved and moves the task to tasks/test/; a run that fails again flips it to failed-solving.

An in-flight resume counts towards the global, per-project and per-stage parallel limits: it occupies one slot, charged to both continue and the resumed file's original stage, so the flow skips the continue step while a resume of that project is still running.

exceptions and logs — inspect what happened

Every do / continue step is recorded in an action log, and failed runs are recorded as exceptions. Both can be listed and filtered:

fastcoder exceptions                          # all exceptions
fastcoder exceptions -p my-app -s pending     # filter by project and status
fastcoder logs -p my-app -a do                # logs for the `do` action
fastcoder logs --level error                  # only error-level logs

Exception statuses: pending, solved, ignored, failed-solving. Log levels: info, warn, error.

Web interface

fastcoder serve starts an Express server that exposes every application feature as a JSON API under /api and serves a React single-page app for the UI. The web app lives in web-ui/ (React 18 + Vite + TypeScript, PrimeReact components, Tailwind CSS, React Router, TanStack Query for state, and react-hook-form + zod for validation).

npm run build:web          # install web-ui deps and build the SPA into web-ui/dist
fastcoder serve           # serves the built SPA + API at http://localhost:4787

The interface has a sidebar with menu navigation, a header and a footer, and covers the whole feature surface: a Dashboard overview, full project CRUD, a per-project workspace with a kanban-style task board (create / edit / move / delete task files — several task dialogs can stay open at once, each one collapsible to its title bar, maximizable to fill the whole page, or minimizable to a chip in the bottom-left dock, with a Save that keeps the dialog open next to Save and close) and the do / check / continue / run-command actions, plus pages for executions, exceptions, action logs, reports, the scheduled job, the environment Doctor report, the AI Providers page (accounts table with add / edit / delete and a per-account limits refresh) and global settings, which links to it instead of carrying the old single Claude account, model and usage-limit rows. The Preferences card carries a Theme selector (Dark, Light, Midnight, Daylight) that applies at once and is persisted for the whole installation; THEME in .env sets the initial value and fastcoder config changes it from the terminal.

The Chat page (/chat) talks to Claude through the Claude Agent SDK (pinned; fastcoder doctor prints its version). Each chat is saved as JSON under .docs/chat-history/ in the Fastcoder install (git-ignored), can be linked to a project (the assistant then reads its files read-only) and to an AI account (Auto or a fixed one — a disabled or over-limit account is refused, never swapped silently), and streams replies live with a Stop button. Chat turns do not count as executions and do not take the flow's parallel slots. The assistant can also drive Fastcoder through its own services (list/create/edit/move/delete/pause tasks, run a task, read executions, exceptions, logs and settings); deleting a task, moving it to garbage/failures or changing a setting first asks you in a confirmation dialog. A task run started from the chat is a regular execution, shown as a job linked to its log. Task, execution and project references in replies are links, and Open chat on a project page or task dialog opens a chat linked to that project. A new chat is titled from its first message, then refined by a short model call; a title you set yourself is never overwritten. The API lives under /api/chats (with a Server-Sent Events stream at /api/chats/:id/stream); see .docs/guidelines/chat.md.

Each project can also be given a colour from a fixed palette in its create/edit dialog: the project name is then shown in that colour wherever it appears (the dashboard tables, the projects list and the project page). A paused project overrides it with gray — its name and its whole dashboard row are dimmed, and it leaves the "Running now" card as soon as nothing of its is still executing.

Each task stage has its own colour too: the stage name and its task count are shown in it on the dashboard ("Tasks by stage") and on the project board's column headers, and a stage paused for a project turns gray. The colours are constants that can be overridden per stage from .env with STAGE_COLOR_{STAGE} (the stage upper-cased with - as _, e.g. STAGE_COLOR_TODO=#0ea5e9) — see .env.example; an unset or invalid value keeps the built-in colour.

AI-provider usage limits are colour-graded the same way: each percentage is green below 70%, yellow below 90% and red from 90% up, on the AI Providers page and in a dashboard AI provider limits card that lists every registered account with its current 5-hour and 7-day windows (— when no snapshot has been fetched yet, and the whole row dimmed to gray for a disabled account).

For UI development, run the API and the Vite dev server side by side — Vite proxies /api to the running fastcoder serve:

fastcoder serve                 # API on :4787
npm --prefix web-ui run dev      # Vite dev server on :4788, proxying /api

Background daemon

fastcoder webui:install registers a per-user background service (com.fastcoder.webui: launchd on macOS, a systemd user unit on Linux/WSL, a scheduled task on Windows) that keeps the web UI running; webui:uninstall removes it and webui:status reports it. webui:status also warns when the installed daemon still runs a script that no longer exists or sits inside a task worktree (it would stop starting once that worktree is cleaned up) — run fastcoder webui:install to re-register it.

The daemon serves the compiled dist/ output, so a change in src/ only takes effect after a rebuild and a restart:

fastcoder webui:status            # adds a `build: up to date` / `build: STALE` line
fastcoder webui:refresh           # rebuild + restart the daemon (skips when nothing is stale)
fastcoder webui:refresh --force   # rebuild even when up to date
fastcoder webui:refresh --no-restart  # build only

It exits non-zero only when the build fails. The flow triggers the same refresh automatically after any step actually executed — turn it off with the Auto-rebuild the web UI toggle on the Settings page, the same entry in fastcoder config, or webuiAutoRefresh on PUT /api/settings. It is skipped while another run is active, and when the run itself started from inside the daemon (the next cron tick refreshes instead).

Run with Docker

Fastcoder also runs from a Docker image — the Web UI as the container's main process and every CLI command through compose or a small wrapper, with data in a per-major volume:

make docker-build                      # fastcoder:<version>, fastcoder:<major>, fastcoder:dev
make docker-up                         # Web UI on http://127.0.0.1:4787
docker compose exec fastcoder fastcoder list
bin/fastcoder-docker flow              # one-off CLI run, like the native command

Switch versions with FASTCODER_IMAGE (and FASTCODER_MAJOR), mount projects at the same absolute path (FASTCODER_PROJECTS_DIR) and keep the port on localhost — the API is unauthenticated. Inside the container the flow is scheduled by the server itself (cron:* report it as built in), webui:install/uninstall/status/refresh print the matching docker compose command, and doctor lists projects not mounted and Claude accounts without usable credentials (claude login in the container or ANTHROPIC_API_KEY). The host must stay awake while runs are expected. Full guide: .docs/guidelines/docker.md.

Using make

A Makefile (with one sub-file per command group under ./make/) wraps the CLI so you can drive everything with make:

make help                                     # list every target
make install                                  # npm install + tsc build
make build                                    # tsc only
make build-web                                # build the web UI bundle (web-ui/dist)
make watch                                    # tsc --watch
make dev                                      # run CLI from TS via ts-node
make install-global                           # npm install -g . (auto-compiles)
make update-global                            # rebuild CLI + reinstall locally (--force)
make update-global-full                       # rebuild CLI + web UI + reinstall (--force)
make uninstall-global                         # npm uninstall -g fastcoder

make register NAME=my-app DIR=/path/to/repo
make list
make remove  TARGET=my-app

make check                                    # all projects
make check   TARGET=my-app                    # one project
make reports LIMIT=10

make serve                                    # default port 4787
make serve   PORT=8080

make cron-install                             # */15 * * * * by default
make cron-install SCHEDULE="*/30 * * * *"
make cron-uninstall
make cron-status

make hooks-install                            # opt in to the .githooks/ hooks
make hooks-uninstall
make hooks-status

make run TARGET=my-app CMD="git status"
make menu                                     # interactive

Sub-makefiles:

make/install.mk    install, build, build-web, watch, dev, install-global, update-global, update-global-full, uninstall-global, clean, menu
make/npm.mk        ci, build-all, deps-update, pack, publish, full-publish, check-next-tag, full-publish-update (npm package/release)
make/projects.mk   register, list, remove
make/check.mk      check, reports
make/serve.mk      serve
make/cron.mk       cron-install, cron-uninstall, cron-status
make/hooks.mk      hooks-install, hooks-uninstall, hooks-status (see .docs/guidelines/git-hooks.md)
make/run.mk        run

<tasks-folder>/config.json example

Place this file inside a registered project (the folder defaults to .docs/, override with TASKS_FOLDER or the global settings):

{
  "checks": ["git status --porcelain", "npm outdated --json"],
  "notifications": {
    "onCheckFailure": [
      { "type": "macos" },
      { "type": "webhook", "url": "https://hooks.slack.com/services/..." }
    ]
  }
}

Each command is executed inside the project folder during fastcoder check, and its stdout/stderr/exit code are stored in the report.

notifications.onCheckFailure lists the push channels used when a check fails (any command exiting non-zero, or the tasks folder missing). Supported entries are { "type": "macos" } (an osascript desktop notification), { "type": "linux" } (notify-send) and { "type": "webhook", "url": "..." }, which POSTs { project, kind, summary, dashboardUrl } as JSON. Unknown or invalid entries — an unrecognised type, a webhook without a url — are ignored, and a notifier that fails is logged as a warn (see fastcoder logs) without affecting the check itself. Nothing is sent when every check succeeds.

Releasing

  1. Bump the version in package.json (e.g. npm version patch).
  2. Run make release — it tags v<version> and pushes the tag to origin.
  3. The tag push triggers the Publish npm package GitHub Actions workflow (.github/workflows/publish-npm.yml), which builds, tests, and publishes the package to npm.
  4. The workflow requires an NPM_TOKEN repository secret with publish access to the package on npm.

Layout (TypeScript)

src/
  cli.ts                          # entry: runs runMain() when invoked directly
  program.ts                      # buildProgram() + runCommand() (commander wiring)
  config.ts                       # paths/constants
  cli/                            # one file per CLI command (commander actions)
  domain/                         # Project, Report, TaskException, ActionLog, Execution (typed)
  application/                    # use-case services
  actions/                        # single-responsibility actions (run-claude-task)
  infrastructure/                 # better-sqlite3, fs, shell, system-cron, express
tsconfig.json                     # target ES2020, module commonjs, strict, outDir dist
dist/                             # compiled output (created by `make build`)
bin/fastcoder.js                 # thin shim: require('../dist/cli').runMain()

npm install runs the prepare script which compiles to dist/. Both fastcoder (compiled) and make dev (via ts-node src/cli.ts) work.