@surajheadsup/forgeos
v0.1.0
Published
ForgeOS — a reusable Engineering Operating System for Claude Code projects, installable as a CLI.
Maintainers
Readme
ForgeOS
An Engineering Operating System for Claude Code projects.
ForgeOS is a CLI that scaffolds a project and installs a complete set of engineering instructions into it, so you stop re-explaining your standards to Claude Code at the start of every session.
Install it once. Create a project. Open Claude. The rules are already there.
Why it exists
Working with a coding agent, the same conversation happens over and over:
Put the feature in its own folder. Use our table component. Every endpoint is POST. List payloads take
{ page, limit, search }with the filters insidesearch. Default page size is ten. Don't use the browser'salert. Validate on the server, not just the client. Handle the empty and error states. Responsive matters. Write tests and actually run them. And please — build the listing only. Not create, edit, delete, import and export.
ForgeOS writes that down once, as 78 instruction files Claude reads before it works. The engineering knowledge lives in Markdown, so it is inspectable, editable, versionable and reviewable — not buried in a prompt.
Installation
Requires Node.js 18.17 or newer.
npm install -g @surajheadsup/forgeosNot yet published. ForgeOS is at
0.1.0and has not been pushed to the npm registry. The name@surajheadsup/forgeosis reserved for it; until the first publish, install from a clone — see Development.
Verify:
forgeos --version
forgeos --helpQuick start
npm install -g @surajheadsup/forgeos # once
forgeos create my-project # interactive wizard
cd my-project
claude # Claude reads .claude/ and follows itThat is the whole loop. forgeos create asks what you are building, writes
forgeos.json, and installs the Engineering OS into .claude/. When you open
Claude Code in that directory it reads .claude/CLAUDE.md first and works to
those rules.
Non-interactive, for scripts and CI:
forgeos create my-project --yes
forgeos create my-api --profile backend-node --backend express --yes
forgeos create my-project --dry-run # show the plan, write nothingAlready have a project?
cd existing-project
forgeos init # inspects, confirms, installs — adds onlyThe core workflow
npm install -g @surajheadsup/forgeos
│
▼
forgeos create my-project ──► forgeos.json + .claude/
│
▼
cd my-project
│
▼
claude ──► reads .claude/CLAUDE.md
──► reads .claude/project/project-context.md
──► reads the instructions the task touches
──► implements ONE slice
──► tests it, verifies it, reports it
──► STOPS
│
▼
you ask for the next sliceFirst thing to do in a new project
Open .claude/project/project-context.md and fill it in — the real commands,
the real conventions, the decisions already made. It is the first file Claude
reads, and the only one that knows anything specific about your project. A
blank one costs every future session time; forgeos doctor warns while it is
still unfilled.
How the Engineering OS controls development
Everything lives under .claude/:
.claude/
├── CLAUDE.md the router — read first, every session
├── instructions/ 78 files, 10 sections — the actual rules
│ ├── 00-core/ task execution, slicing, planning, change safety
│ ├── 01-architecture/ structure, naming, separation of concerns
│ ├── 02-design/ design systems, responsive, typography, a11y
│ ├── 03-frontend/ views, components, CSS, forms, tables, states
│ ├── 04-backend/ controllers, services, repositories, auth
│ ├── 05-data/ mock data, seed data, API contracts, fixtures
│ ├── 06-security/ 14 files — secrets, validation, authz, privacy
│ ├── 07-testing/ strategy, unit, component, API, e2e, security
│ ├── 08-quality/ code quality, performance, regression, review
│ └── 09-workflow/ feature flow, debugging, review, git, verify
├── templates/ feature plan, API contract, test plan,
│ security review, completion report
├── project/ YOURS — never overwritten by ForgeOS
│ ├── project-context.md the stack, conventions and decisions
│ ├── design-system.md tokens, spacing, components
│ ├── security-context.md auth model, data classification, accepted risks
│ └── current-progress.md what exists, what is next
└── .forgeos-manifest.json what ForgeOS installed, for safe updatesCLAUDE.md tells Claude to, in order: read the project state, read only the
instructions the task touches, inspect the existing code, choose the smallest
slice, state the plan, implement, test, verify, report, and stop.
Managed versus yours
| Path | Owner | On forgeos update |
| --- | --- | --- |
| CLAUDE.md, instructions/, templates/ | ForgeOS | replaced |
| project/*.md | you | never touched |
| your application code, .env, package.json | you | never touched |
| forgeos.json | shared | only forgeosVersion is rewritten |
Record project decisions in project/, not in the instruction files — edits
there are reported as conflicts on update and kept, but they are not where
decisions belong.
The incremental rule
This is the rule ForgeOS exists to enforce, and the one most often broken.
Claude implements the smallest independently complete slice, then stops.
Recognising a CRUD pattern is not permission to build the CRUD. Asked to "create the Users page", Claude must not produce listing + create + edit + delete + details + import + export + bulk + permissions. It builds:
Users listing
+ search
+ filters
+ pagination
+ sorting
+ mock data
+ loading / empty / error states
+ tests
→ STOPThen you ask for the next slice — "connect it to the API", "add create user" —
one at a time. Backends slice the same way: list, then create, then
update, then delete, each complete with validation, authorisation, error
handling and tests.
Claude must stop after each logical slice unless you explicitly ask it to
continue. Finishing a slice and starting the next unasked is the most common
way this process fails. The full statement is in
.claude/instructions/00-core/incremental-development.md, and the stop is step
21 of .claude/instructions/09-workflow/feature-workflow.md.
Commands
| Command | Does | Writes? |
| --- | --- | --- |
| forgeos create [name] | new project + Engineering OS | yes |
| forgeos init | install the OS into an existing project | adds only |
| forgeos doctor | health check with actionable fixes | no |
| forgeos status | configuration and recorded progress | no |
| forgeos update | update managed files, keep your edits | managed only |
| forgeos version | print the version | no |
| forgeos help [cmd] | help for a command | no |
Global flags: -v, --version, --verbose, --no-color, -h, --help. They go
before the command (forgeos --verbose create app), as with git and
npm.
Full reference: docs/commands.md.
forgeos create
Runs the interactive wizard by default. Flags answer questions up front; --yes
skips the wizard and uses the profile defaults.
forgeos create # wizard asks everything, including the name
forgeos create my-app # wizard asks the rest
forgeos create my-app --yes # no prompts
forgeos create my-app --dry-run # show the plan, write nothing
forgeos create my-app --profile frontend-next --styling tailwind --yesStack flags: --profile --type --frontend --backend --backend-arch --database
--auth --styling --testing --package-manager. Behaviour flags: --no-git,
--no-engineering-os, --dry-run, --force, --yes.
create refuses a non-empty directory (exit 6) and never deletes anything;
--force writes into one while leaving existing files alone.
forgeos init
For a project that already exists. It inspects first, reports the evidence, lets you confirm or correct it, and then adds what is missing.
cd existing-project
forgeos init # inspect, confirm, install
forgeos init --yes # accept what was detected
forgeos init --dry-run # show what would change
forgeos init --yes --backend nestjs # correct a detected valueDetects: project name, React/Next, Spring Boot (Maven and Gradle), NestJS,
Express, gateway-versus-monolith layout, PostgreSQL/MySQL/MongoDB, package
manager, test framework, git, existing tests, existing .claude, existing
forgeos.json.
Never overwrites a file ForgeOS did not write. A hand-written
.claude/CLAUDE.md survives; so does .claude/settings.local.json and
anything else of yours in that directory. Re-running is a no-op.
forgeos doctor
Read-only health check across ten groups: installation, Engineering OS, project state, git, frontend, backend, tests, environment, security, structure.
forgeos doctor
forgeos doctor --all # include checks that do not apply
forgeos doctor --strict # fail on warnings too
forgeos doctor --json # machine-readableEngineering OS
✓ .claude/ — Found.
✓ CLAUDE.md — Present, 84 lines.
✓ Instruction files — All 87 present and non-empty.
⚠ Local modifications — 1 managed file(s) edited locally: …
What to do:
⚠ Local modifications: ForgeOS-managed files are replaced on update. Move
project-specific notes into .claude/project/ instead.Every warning and error carries a fix. Exit 0 healthy or warnings only, 1 errors, 4 nothing installed. It never modifies the project.
forgeos status
Read-only. Shows the configuration, the recorded progress, and git state.
forgeos status
forgeos status --jsonIt never infers progress. Anything not written down in
.claude/project/current-progress.md is reported as not recorded rather than
guessed.
forgeos update
Brings ForgeOS-managed files up to the installed CLI version.
forgeos update --dry-run # see what would change
forgeos update # update, keeping your edits
forgeos update --save-incoming # also write new versions as *.forgeos-new
forgeos update --force # replace your edits too
forgeos update --prune # remove files no longer part of the OSA managed file you edited is kept and reported, never silently replaced.
--save-incoming writes the new version beside it so you can diff and merge.
Downgrades are refused (exit 6) unless --force.
Profiles
A profile presets the stack. Pick one with --profile, or let the wizard ask.
| Profile | Stack | Instruction files installed |
| --- | --- | --- |
| fullstack-java | React + Vite · Spring Boot · Gateway + Eureka · PostgreSQL | 78 |
| frontend-react | React + Vite, no backend | 61 |
| frontend-next | Next.js, no backend | 61 |
| backend-java | Spring Boot, no frontend | 54 |
| backend-node | NestJS or Express, no frontend | 52 |
| custom | nothing preset — every choice is yours | varies |
Profiles decide which instructions are relevant. A backend-only project gets no
02-design/ or 03-frontend/; a monolith gets no gateway files; a project with
no database gets no database.md or database-security.md. An absent section
means the subject does not apply, not that something is missing.
A flag that contradicts the profile is rejected rather than silently applied:
$ forgeos create app --profile frontend-react --backend spring-boot
✗ --backend spring-boot contradicts profile "frontend-react", which is none.
→ Use --profile custom to choose freely, or drop --backend.Aliases work: --profile next, --profile java, --profile express, and value
aliases like --frontend react, --database postgres, --backend-arch eureka.
Details: docs/profiles.md.
The wizard
forgeos create and forgeos init run an interactive wizard unless --yes is
passed or there is no terminal.
It asks the profile first, then only what that profile leaves open. Choosing
fullstack-java skips type, frontend, backend, architecture and database — they
are already decided — and asks about styling, auth, testing and package manager.
Choosing custom asks everything. backend-node narrows the backend question
to NestJS and Express.
Questions you have already answered with a flag are skipped. Irrelevant questions are never asked: a frontend project is not asked about databases. Answers are validated as you go — an unusable project name is re-asked with the reason and a suggestion — and a review summary is shown before anything is written. Declining it, or pressing Ctrl+C, exits 130 having written nothing.
In forgeos init the wizard preselects what was detected, so confirming is one
keystroke per question and correcting is still possible.
Generated project
my-project/
├── forgeos.json the recorded configuration
└── .claude/ the Engineering OSforgeos.json records only what applies to the project:
{
"forgeosVersion": "0.1.0",
"projectName": "my-project",
"projectType": "fullstack",
"profile": "fullstack-java",
"frontend": "react-vite",
"styling": "css",
"backend": "spring-boot",
"backendArchitecture": "api-gateway-eureka-general-service",
"database": "postgresql",
"auth": "jwt",
"packageManager": "npm",
"testing": { "frontend": "vitest", "e2e": "playwright", "backend": "junit" }
}ForgeOS does not scaffold application code. It generates no package.json,
no Vite config, no Spring project, no README.md and no .env.example. It sets
up the rules and the configuration; you and Claude build the application. See
Limitations.
Conventions the OS encodes
These are project defaults, written into the instruction files and recorded in
.claude/project/project-context.md, where you can change them:
- All endpoints use POST, including reads, lists and searches.
- List and search payloads are always
{ page, limit, search: { …all filters… } }. Every filter goes insidesearch— never as a sibling ofpage/limit.sortmay be a sibling. - Default page size is 10, for tables and for select options. Selects with many values are searchable and server-paginated, not fetched whole.
- Never the browser's
alert,confirmorprompt— use the project's alert hook and alert dialog. - Check error handling on every change, and check dependents before deleting or renaming anything.
- Backend authorisation is authoritative; hiding a button is UX, not security.
Exit codes
| Code | Meaning |
| --- | --- |
| 0 | success (or warnings only, for doctor) |
| 1 | failure — errors found, or an unreadable forgeos.json |
| 2 | usage — unknown command, unknown flag, missing argument |
| 3 | validation — bad project name, bad flag value, contradictory flag |
| 4 | not found — no ForgeOS installation in this directory |
| 5 | reserved (not implemented) |
| 6 | conflict — non-empty directory, version downgrade, corrupt config |
| 130 | cancelled — Ctrl+C, or the wizard's confirmation declined |
Scripts may branch on these; they are pinned by a test.
Documentation
- docs/commands.md — every command, flag and exit code
- docs/profiles.md — profiles, precedence, validation
- docs/engineering-os.md — the instruction system
- docs/troubleshooting.md — common problems
- CONTRIBUTING.md — development and contribution
- CHANGELOG.md — release history
Development
git clone https://github.com/surajheadsup/forgeos.git
cd forgeos
npm install
npm run build
npm link # makes `forgeos` available globally from this checkout
forgeos --versionnpm link is per Node version; after switching with nvm, run it again.
| Script | Does |
| --- | --- |
| npm run build | compile TypeScript to dist/ |
| npm run typecheck | type-check without emitting |
| npm test | build, then run the full suite |
| npm run test:watch | watch mode |
| npm run test:coverage | suite with coverage |
| npm run clean | remove dist/ |
See CONTRIBUTING.md for the layout, conventions and how to add a command, a profile or an instruction file.
Testing
npm test639 tests in 26 files. Coverage is 96.7% of statements and 90% of branches.
Every filesystem test runs in a mkdtemp directory and asserts the real
filesystem is untouched. The suite covers CLI parsing, help, version, all five
project commands, the wizard (through an injectable prompter), validation,
profiles, template generation, .claude installation, existing-project
initialisation, forgeos.json validity, overwrite protection, idempotency,
error handling and the exit-code contract.
It also verifies the Engineering OS itself: every required file exists and is
non-empty, every cross-reference between instruction files resolves, the
required-file lists match what is on disk, and CLAUDE.md correctly references
the instruction system.
Troubleshooting
forgeos: command not found — the global link is per Node version. Run
npm link in the checkout again, or npm install -g @surajheadsup/forgeos.
the compiled CLI was not found — run npm run build.
Directory x already exists and is not empty (exit 6) — use a different
name, --force to write into it, or forgeos init if it is an existing
project.
--backend x contradicts profile y (exit 3) — the profile fixes that
choice. Drop the flag or use --profile custom.
The wizard did not run — it needs a terminal and no --yes. Piped or CI
sessions fall back to flags and defaults.
doctor warns about a project it just created — .gitignore and
.env.example are not generated; the project state files are not filled in yet.
All three are expected on a new project.
More: docs/troubleshooting.md.
Limitations
Honest list, as of 0.1.0:
- No application scaffolding. No
package.json, framework config,README.mdor.env.exampleis generated. - Not published to npm. Install from a clone until the first release.
- Detection covers React, Next.js, Spring Boot, NestJS and Express only.
Vue, Angular, Svelte, Django, Rails, Go and .NET are not recognised, and
monorepo layouts (
apps/*,packages/*) are not searched. - No three-way merge on update — conflicts are kept and reported, with
--save-incomingto diff by hand. updateis not transactional; a mid-run failure leaves partial writes. Git is the safety net..gitignorecoverage is checked by pattern, not by asking git, so an already-tracked.envis not detected.- No linter;
tsc --strictis the only static gate.
Versioning
Semantic versioning. forgeos.json records the version that installed a
project, and forgeos doctor reports drift between it and the installed CLI.
forgeos update moves managed files to the current version and rewrites that
field.
Pre-1.0.0, minor versions may change the instruction set. update keeps your
edits in all cases.
License
MIT. See LICENSE.
