forq is a spec-driven software-delivery framework for OpenCode, Claude Code and GitHub Copilot, built on OpenSpec.
It installs a team of agents, workflows, skills and rules, plus a custom OpenSpec schema, into any repository, in the native format of each AI tool you choose. Every behaviour change then follows the same audited path, whichever tool a developer uses:
/forq-propose → proposal → specs → design → security review → tasks (planning)
── human review of the specs ──
/forq-apply → implement → security audit → independent QA → fix loops (delivery)
or /forq-apply-quick → implement → audit / QA only when triggered (small changes)
/forq-archive → delta specs merged into openspec/specs/ (living specs)
Specs, not chat history, are the contract:
- Each
### Requirement:is a functional or non-functional requirement. - Each
#### Scenario:is an acceptance criterion. QA traces every scenario to implementation and test evidence before a change can be delivered.
- Node.js
>= 20.19 - Git
- At least one of: OpenCode, Claude Code, or GitHub Copilot in VS Code or the Copilot CLI
- OpenSpec CLI:
npm install -g @fission-ai/openspec@latest
forq is not published to a registry. Install it straight from GitHub, pinned to a release tag:
npm install -g github:Workaholic01/DevForq#v0.4.0This needs read access to the repository. Git must be able to authenticate, for example through Git Credential Manager or an SSH key.
Other ways to run it:
- One-off, without a global install:
npx github:Workaholic01/DevForq#v0.4.0 init - Upgrade the CLI: run the same
npm install -gcommand with the new tag. - Check the installed version:
npm ls -g devforq. The npm package is calleddevforq, but the command isforq. Don't install the unrelatedforqpackage from the npm registry. Releases up to and includingv0.3.0were published as@twoday/forq, so for those usenpm ls -g @twoday/forq. Uninstall that name before you install a later release.
To work on forq itself, clone the repository and run npm link instead.
cd /path/to/your-project
forq init # asks which tools, in a terminal
forq init --tools claude,copilot # Claude Code and GitHub Copilot
forq init --tools all # OpenCode, Claude Code and GitHub Copilot--toolstakes a comma-separated list ofopencode,claudeandcopilot, orall. Unknown IDs are rejected before anything is written.- Without
--tools, in an interactive terminal,forq initlists the tools and asks you to pick one or more (numbers or names, comma-separated,afor all). An empty answer cancels without writing anything. - Without
--toolsand without a terminal (CI, scripts), it installs foropencodeand says so.
init does the following:
- Runs
openspec init --tools <the same tools>ifopenspec/does not exist yet (opencode,claude,github-copilot; with--no-copilot-cloudwhen Copilot is included). This adds OpenSpec's own/opsx-*commands and skills. - Renders the forq agents and workflows natively for every chosen tool (see Repository layout after install).
- Installs the forq workflows and skills once, in
.claude/skills/, which every supported tool reads. - Installs the
forqOpenSpec schema intoopenspec/schemas/forq/and makes it the default inopenspec/config.yaml. - Writes the framework block, with all engineering rules inlined, and the
project block into
AGENTS.md, between<!-- forq:… -->markers. Any other content is preserved. - Merges the safety rules into each tool's own configuration, never
loosening existing settings:
- OpenCode:
opencode.jsondeniesgit push,git commit,git reset --hard,git clean -fand reading.envand secrets files. - Claude Code: the same rules as
permissions.denyin.claude/settings.json, and aCLAUDE.mdblock that imports@AGENTS.md. - Files that are not plain JSON (for example JSONC with comments) are left unchanged; forq prints the snippet to merge by hand.
- OpenCode:
- Creates
.forq/knowledge/and.forq/docs-cache/INDEX.md, writes.forq/manifest.json, and adds.forq/backups/to.gitignore. - Detects the technology stack (
.forq/stack.json) and enables the matching documentation MCP servers for every chosen tool. See Documentation, MCP servers and token efficiency.
| Flag | Description |
|---|---|
--tools <ids|all> |
Tools to install for (opencode, claude, copilot) |
--target, -t <path> |
Target repository (default: current directory) |
--dry-run |
Preview changes without writing |
--force |
Overwrite conflicting framework-owned files |
--skip-openspec |
Don't call the OpenSpec CLI (offline or test installs) |
--no-mcp |
Don't configure any MCP servers |
Verify the install:
forq validate # shared files, each installed tool's files, markers, forq schema
forq doctor # plus versions, enforcement matrix, knowledge, stack skills, specs, git stateEvery forq workflow runs as the forq orchestrator agent. It delegates to
the specialist agents and never writes production code itself.
| Tool | How to run a workflow |
|---|---|
| OpenCode | Start opencode and run /forq-onboard, /forq-propose <requirement>, and so on. The commands run on the forq agent. |
| Claude Code | Start claude and run /forq-onboard, /forq-propose <requirement>, and so on. Each workflow skill runs in the forq subagent (context: fork). |
| GitHub Copilot (VS Code or CLI) | Pick the forq agent in the agent picker (CLI: /agent), then run /forq-propose <requirement>, and so on. If you run a workflow from another agent, the workflow tells it to act as the orchestrator. |
| Copilot cloud agent | Not installed by forq. Print its MCP settings with forq mcp add <id> --print --tool copilot-cloud. |
Evidence-based discovery of the repository. Generates:
- Project knowledge in
.forq/knowledge/:PROJECT_PROFILE,TECHNOLOGY_STACK,ARCHITECTURE,REPOSITORY_MAP,COMMANDS,CONVENTIONS,TESTING_STRATEGY,INTEGRATIONS,DOC_SOURCESandONBOARDING_REPORT. - Stack skills:
.claude/skills/stack-<tech>/SKILL.md, which the developer, security and QA agents load on demand, in every tool. - OpenSpec context: a concise
context:inopenspec/config.yaml, which OpenSpec injects into every artifact. - Baseline specs in
openspec/specs/<capability>/spec.md. These describe how the key capabilities behave today, each backed by evidence, so that the first change can useMODIFIEDdeltas. - The project block in
AGENTS.md.
Run /forq-refresh later, after the stack, commands or structure change. It
also reports spec drift: code that changed outside forq.
Planning only. Creates openspec/changes/<change>/ with the forq schema:
| Artifact | Author | Contents |
|---|---|---|
proposal.md |
requirements-analyst |
Why, current behaviour (with evidence), scope, capabilities, impact, Architecture Assessment, Readiness |
specs/**/spec.md |
requirements-analyst |
Delta specs: ADDED / MODIFIED / REMOVED requirements with WHEN/THEN scenarios |
design.md |
solution-architect |
Full design, or a recorded NOT_REQUIRED decision |
security-review.md |
security-analyst |
OWASP-mapped design review, or NOT_REQUIRED |
tasks.md |
solution-architect |
Checklist. Every task names the scenarios it covers and how it is verified |
It then runs openspec validate --strict, checks that every scenario is
covered by a task, and stops. With no requirement, it asks what to build
or fix and creates nothing. Review and edit the artifacts as much as you like.
Running this command approves the specs. It then:
- Re-validates the change and records approval (
delivery/01-approval.md). software-developerworks throughtasks.md, ticking tasks as it goes.security-analystaudits the real diff (delivery/04-security-audit-<n>.md).qa-engineertraces every scenario to code and tests, and runs validation (delivery/05-qa-<n>.md).- If security returns VULNERABLE or QA returns FAIL, the findings go back to
the developer. There are at most three fix cycles (
delivery/06-fix-<n>.md). - The coordinator checks the
forq-completion-gatesskill and writesdelivery/99-delivery-report.md, which contains:- a final status of
DELIVERED,DELIVERED_WITH_RISKS,BLOCKEDorFAILED - a suggested commit message
- a final status of
forq never commits, pushes, merges or deploys.
The lightweight alternative for small, low-risk changes. Planning
(/forq-propose) and the human review are the same; delivery is shorter:
- Eligibility check. It refuses, before changing anything, when the
proposal says ARCHITECTURE_REQUIRED, Readiness or design is BLOCKED, or the
security review is VULNERABLE, BLOCKED or requires spec or design changes.
Use
/forq-applyfor those. software-developerimplementstasks.md, runs focused validation, and maps every scenario to a test. Failing validation stops the run: there are no fix cycles.- Security audit, only if triggered: dependency manifests or lock files, CI/CD, containers or infrastructure, database migrations, auth, sessions, crypto, secrets or security configuration, more than 15 changed files, or a SECURE_WITH_RISKS design review.
- QA review, only if triggered: a scenario without a test, changes outside the proposal's Impact areas, more than 5 scenarios, more than 10 changed files, or the audit ran.
- The coordinator always checks tasks, unrelated changes and secrets, and
writes
delivery/99-delivery-report.mdwith the statusDELIVERED_QUICK, a table of every gate (RUN or SKIPPED) and every trigger with its evidence.
/forq-archive accepts DELIVERED_QUICK after showing the skipped gates and
asking you to confirm. If a quick run is blocked, run /forq-apply <change>
for the full loop.
Verifies the delivery report, the task completion and the spec validity. It
then runs openspec archive <change> --yes, which:
- merges the deltas into
openspec/specs/ - moves the change, including its
delivery/audit trail, toopenspec/changes/archive/YYYY-MM-DD-<change>/
| Agent | Role | Writes | Purpose |
|---|---|---|---|
forq |
primary | openspec/, project knowledge, stack skills, AGENTS.md |
Orchestrates the workflow and enforces gates |
requirements-analyst |
subagent | change folder only | Proposal and delta specs |
solution-architect |
subagent | change folder only | Design and tasks |
security-analyst |
subagent | change folder only | Design review and implementation audit |
software-developer |
subagent | source and tests | Implements tasks and fixes findings |
qa-engineer |
subagent | change folder only | Independent verification |
docs-researcher |
subagent | docs cache, docs-brief.md |
Version-specific documentation lookups through the MCP servers |
File bundles. OpenCode limits each agent's writes to its folders. Claude Code and Copilot cannot, so there the read-only specialists get no file-write tools at all. They return their artifacts as file bundles:
=== forq-file: openspec/changes/add-csv-export/delivery/05-qa-1.md (from: qa-engineer) ===
<content>
=== forq-end ===
The orchestrator writes a bundled file only when its path is inside the declaring agent's scope, and records any rejected path in the delivery report.
OpenSpec's generic /opsx-* commands remain available. Use /forq-* for
delivery work, because only the forq commands enforce the security and QA
gates.
Each safety gate is either HARD (a native permission or tool allowlist the
tool enforces) or ADVISORY (instructions only). forq doctor prints the
same matrix for the tools a project has installed, with the reason for each
advisory gate.
| Gate | OpenCode | Claude Code | GitHub Copilot |
|---|---|---|---|
| No history-changing git commands | HARD | HARD | ADVISORY |
| No secret reads | HARD | HARD | ADVISORY |
| Read-only roles cannot edit files | HARD | HARD | HARD |
| Orchestrator write scope | HARD | ADVISORY | ADVISORY |
| Per-agent shell limits | HARD | ADVISORY | ADVISORY |
| Agent-specific MCP access | HARD | HARD | ADVISORY |
Notes:
- Shell deny rules are string matches in every tool (
git -C . pushslips through). Enable branch protection on the remote: it is the real control against unwanted pushes and history rewrites. - Add a
CODEOWNERSentry for.claude/,.github/agents/,.opencode/,opencode.jsonandAGENTS.md(this covers.claude/skills/, which every tool loads as instructions), so changes to agent definitions get reviewed. - Copilot cannot read deny rules from the repository, so keep secrets out of the working tree.
- Claude Code has no allow exceptions (deny always wins), so
.env.exampleis denied there too, while OpenCode still allows it. This is stricter, and intended. - Every forq agent keeps a shell in Claude Code and Copilot: QA and security
freely, the analysts and
docs-researcherwith allow lists that are instructions only there. A shell could still write files. QA's diff review and the orchestrator's coordinator review are there to catch that. - Read-only specialists cannot hand work to an agent that can write: in
Claude Code they get no
Agenttool (they return a## Docs Requestto the orchestrator instead), and in Copilot theiragentslist names onlydocs-researcher.
forq init runs forq detect. This is a deterministic, zero-token scan of
manifests and files that writes .forq/stack.json. forq then enables
documentation MCP servers that match the detected stack.
| Server | Kind | Enabled | Used by |
|---|---|---|---|
docs-mslearn: Microsoft Learn (maxTokenBudget=2000) |
docs | automatically for .NET, Azure, PowerShell and SQL | docs-researcher |
docs-context7: Context7 library docs |
docs | automatically for non-Microsoft libraries | docs-researcher |
docs-svelte |
docs | automatically for Svelte | docs-researcher |
docs-aws, docs-terraform, docs-ghgrep |
docs | opt-in; these run locally | docs-researcher |
tool-playwright |
tool | opt-in | qa-engineer |
tool-nextjs, tool-angular |
tool | opt-in | software-developer (+ QA for Next.js) |
tool-azure (single tool, read-only) |
tool | opt-in | software-developer, security-analyst |
forq detect # refresh .forq/stack.json
forq mcp list # catalog with installed / recommended status
forq mcp add tool-playwright
forq mcp remove docs-ghgrep
forq mcp add docs-context7 --print --tool copilot-cloud # print only, writes nothingforq mcp add and remove update every installed tool. Servers forq does not
manage are never touched.
| Tool | Where the servers go | Secret syntax | Scoping |
|---|---|---|---|
| OpenCode | opencode.json mcp |
{env:X} |
docs-* / tool-* denied globally, allowed per agent |
| Claude Code | inline mcpServers on the agents that use them; no .mcp.json |
${X} |
per agent |
| GitHub Copilot | .vscode/mcp.json servers, plus mcp-servers on the agents (Copilot CLI) |
${env:X} / ${X} |
forq agents list only their servers in tools; in VS Code other agents can see the servers (forq doctor reports this) |
| Copilot cloud agent | printed with --print --tool copilot-cloud, pasted into repository settings |
$COPILOT_MCP_X |
n/a |
The setup keeps token use down in several ways:
- Scoped tool schemas. MCP tool definitions are loaded only into the agents that need them, never into the orchestrator or the analysts.
- Isolated research. All documentation lookups run inside
docs-researcher's own context. It returns a brief of 40 lines or fewer, with citations. Raw pages never reach the implementing agents. - Lookup ladder (the docs-and-tokens rule):
- repository code
- project knowledge
- docs cache
- installed package sources (
.d.ts, NuGet XML docs,node_modules/next/dist/docs) - MCP servers
- official site
- Shared cache. Briefs are stored version-stamped in
.forq/docs-cache/, with anINDEX.md. Commit it, so the team and future changes reuse it./forq-refreshprunes entries for upgraded versions. - One brief per change.
/forq-proposemakes a single batched research call intodelivery/docs-brief.md. The architect, developer and QA all read that file. - Documentation routing. Onboarding writes
DOC_SOURCES.md, which records each library's Context7 ID, so lookups skipresolve-library-id.
Optional settings:
- Set
CONTEXT7_API_KEYfor higher Context7 rate limits, then runforq update. forq only ever writes a reference to the variable, never its value. - OpenCode: run
docs-researcheron a cheaper model with"agent": { "docs-researcher": { "model": "<provider/model>" } }inopencode.json.
With --tools all:
AGENTS.md framework block (rules inlined) + project block shared
.claude/skills/ forq-onboard, forq-propose, forq-apply, shared
forq-apply-quick, forq-archive, forq-refresh
(workflows),
forq-onboarding, forq-completion-gates,
stack-* (generated by onboarding)
openspec/
config.yaml schema: forq + project context
schemas/forq/ forq schema + templates shared
specs/ living specs
changes/<change>/ in-flight change + delivery/ records
changes/archive/ delivered changes
.forq/
manifest.json tools, every forq file and its owner, MCP servers
stack.json detected stack (forq detect)
knowledge/ generated by /forq-onboard (incl. DOC_SOURCES.md)
docs-cache/ distilled documentation briefs + INDEX.md
.opencode/agents/*.md forq agents with permission maps opencode
.opencode/commands/forq-*.md routing commands opencode
opencode.json safety permissions, MCP servers (merged) opencode
.claude/agents/*.md forq agents with tools and inline MCP servers claude
.claude/settings.json permissions.deny (merged) claude
CLAUDE.md @AGENTS.md import block (merged) claude
.github/agents/*.agent.md forq custom agents copilot
.vscode/mcp.json MCP servers (merged) copilot
OpenCode, Claude Code, VS Code Copilot and the Copilot CLI all read skills
from .claude/skills/. Installing every forq skill there once means no tool
discovers the same skill twice, and a stack skill written in one tool is used
by all of them. The folder name is historical; it is not Claude-only.
forq lives in the repository, so a team shares it through git.
The person who ran forq init commits everything in the layout above.
Only .forq/backups/ stays out, and init adds it to .gitignore.
forq doctor lists anything that is not committed yet.
Every other developer:
- Installs the requirements and, optionally, sets
CONTEXT7_API_KEY. - Installs the CLI, using the tag that matches the
versionin.forq/manifest.json. For example, version0.4.0meansnpm install -g github:Workaholic01/DevForq#v0.4.0. The agents and workflows work without the CLI, butvalidate,doctor,updateandmcpneed it. - Clones the project and runs
forq validate. Do not runforq init. It refuses to run when a manifest already exists. - Opens the project in any installed tool. The
/forq-*workflows are available straight away. There is no need to run/forq-onboardagain, because the project knowledge is already committed.
Team conventions:
- One person runs
forq updateandopenspec update, then commits the result. Everyone else pulls.forq doctorwarns when someone's CLI version differs from the installed one. - Don't edit forq-managed files such as
.claude/agents/*.mdor.opencode/agents/*.mddirectly.forq updateoverwrites them, and its backups are gitignored. Put customisations whereupdatepreserves them: your own entries inopencode.jsonand.claude/settings.json, theAGENTS.mdproject block,CLAUDE.mdoutside the forq block, project knowledge andstack-*skills. - Commit
.forq/docs-cache/andopenspec/changes/, including thedelivery/records, so that research and the audit trail are shared.
forq update # back up, re-render every installed tool, remove stale files, re-merge settings
openspec update # refresh OpenSpec's own generated skills/commandsforq update re-renders exactly the tools recorded in the manifest and adds
none. It preserves:
- project knowledge and the docs cache
stack-*skillsopenspec/config.yaml,specs/andchanges/- the
AGENTS.mdproject block and your own content inCLAUDE.md
0.4 moves shared project data out of .opencode/, so every tool can use it.
In each project, one person runs:
npm uninstall -g @twoday/forq # only if you still have the old package name
npm install -g github:Workaholic01/DevForq#v0.4.0
forq update --dry-run # prints every planned move, changes nothing
forq updateforq update sees the 0.3 manifest, treats the project as OpenCode-only, and:
-
Backs up every managed file and every file it is about to move to
.forq/backups/<timestamp>/. -
Moves, without overwriting anything:
.opencode/project-knowledge/*to.forq/knowledge/.opencode/docs-cache/*to.forq/docs-cache/.opencode/skills/stack-*to.claude/skills/
If a destination file already exists with different content, both files are kept and the path is printed for you to resolve.
-
Re-renders the OpenCode agents and commands, and installs the workflows and skills in
.claude/skills/. -
Removes the forq-installed
.opencode/rules/*.mdand.opencode/skills/forq-*files, and only forq's.opencode/rules/*.mdentry fromopencode.jsoninstructions. The rules now live in theAGENTS.mdframework block. Files forq did not install, such as your own.opencode/rules/team.md, are kept and reported. -
Writes manifest v2 with
tools: ["opencode"].
Every file operation is checked to stay inside the repository, also through symbolic links and junctions; such paths are refused and reported. Only regular files under forq's own folders are ever removed.
Then run /forq-refresh so project knowledge stops mentioning the old paths.
Changing the installed tools after install (forq tools add|remove) is
planned in the multi-tool-followup change and not available in 0.4.
Rollback: reinstall the 0.3.1 CLI
(npm install -g github:Workaholic01/DevForq#v0.3.1) and copy the files from
.forq/backups/<timestamp>/ back into place, or simply discard the changes
with git before committing.
Run forq init in the repository. It copies
.claude/project-knowledge/*.md to .forq/knowledge/. Then run
/forq-refresh so the knowledge gains OpenSpec context and baseline specs, or
run /forq-onboard for a full re-discovery. Remove .claude/framework.json,
.claude/project-knowledge/ and the old CLAUDE.md blocks once you are
satisfied.
bin/forq.js CLI entry point
scripts/ install, update, migrate, validate, doctor,
detect-stack, mcp, OpenSpec adapter
scripts/source.js parses and validates the neutral source
scripts/render/ shared, opencode, claude and copilot renderers
framework/agents/ neutral agent definitions (role, writes, shell, delegates, mcp)
framework/workflows/ the /forq-* workflows
framework/skills/ procedure skills
framework/rules/ engineering rules (inlined into AGENTS.md)
framework/policy.json global shell and read denies
framework/openspec/ the forq OpenSpec schema
framework/mcp/catalog.json stack signals and the neutral MCP server catalog
framework/templates/ AGENTS.md blocks
tests/ node:test suite
openspec/ plans for forq's own changes (not shipped)
npm testThe design is recorded in docs/adr/0001-multi-tool-rendering.md. forq's own
changes are planned with forq's schema in openspec/. See AGENTS.md for
how.
Users install forq from git tags, so a release is a tagged commit:
- Bump
versioninpackage.json(for example to0.4.1). - Change the tag in this README's install commands to the new one
(
#v0.4.1), then commit. - Run
npm test. - Tag and push:
git tag v0.4.1, thengit push origin main --tags.
The tag must match package.json. forq init and forq update record that
version in each project's .forq/manifest.json, and forq doctor compares
it with the installed CLI. Never move a published tag.
MIT