A web platform for creating AI-toolchain projects. Describe your project — agent-planforge and scaffoldkit do the rest.
Live: project-forge.opentriologue.ai
project-forge resolves generated planforge artifacts via planforge-index.json when available and falls back to legacy root paths for older planforge installations.
- Describe — Fill in a form (or use the ✨ AI magic fill)
- Review — Browse generated tasks, architecture overview, and file tree
- Confirm — Create a GitHub repo with the scaffold pushed
- Build — Clone and hand off to your agent
AI is optional. Without it, project-forge uses deterministic intake mapping plus agent-planforge heuristics. If a local or hosted AI provider is configured, project-forge also uses it server-side to enrich intake and review scaffold fit after scaffoldkit runs.
Also available as a REST API for agents — see the API section below.
project-forge talks to a single dependency: the agent-planforge HTTP service, which runs both the planforge CLI and scaffoldkit in its own container and returns the scaffolded project as a tarball over HTTP (per ADR-0002). Docker Compose wires it in automatically; nothing to install on the host.
git clone https://github.com/LanNguyenSi/project-forge.git
cd project-forge
cp .env.example .env
# Fill in required values (see below)
make deploy| Variable | Description |
|---|---|
NEXTAUTH_SECRET |
Random secret (openssl rand -hex 32) |
NEXTAUTH_URL |
Public URL (e.g. https://project-forge.example.com) |
DATABASE_URL |
SQLite path (e.g. file:/data/project-forge.db) |
PLANFORGE_URL |
URL of the planforge HTTP service (defaults to http://planforge:8223 in compose). |
PLANFORGE_SERVICE_TOKEN |
Shared bearer token for the planforge HTTP service. Generate with openssl rand -hex 32. Same value in both app and planforge containers. |
Publishing a repo uses each user's own GitHub Personal Access Token (PAT), added in the dashboard, not a platform-wide token. There is no server-level
GITHUB_TOKENorGITHUB_OWNERenv var. For OAuth sign-in, set the optionalGITHUB_ID/GITHUB_SECRETbelow.
| Variable | Description |
|---|---|
OPENAI_API_KEY |
Enables AI magic fill (OpenAI GPT-4o-mini) |
GROQ_API_KEY |
Enables AI magic fill (Groq, preferred — free) |
LOCAL_AI_BASE_URL |
Enables a local OpenAI-compatible model endpoint for AI magic fill and server-side intake enrichment |
LOCAL_AI_MODEL |
Model name for the local AI endpoint |
LOCAL_AI_API_KEY |
Optional API key for the local AI endpoint |
GITHUB_ID |
GitHub OAuth app Client ID |
GITHUB_SECRET |
GitHub OAuth app Client Secret |
ALLOWED_GITHUB_LOGINS |
Comma-separated allowlist of GitHub logins permitted to register via the project-pilot broker. Unset/empty = accept any. |
FORGE_TEMP_DIR |
Directory for temporary build artifacts (defaults to /tmp/project-forge) |
The root docker-compose.yml ships two services:
app— the project-forge Next.js runtime.planforge: the agent-planforge HTTP service (per ADR-0002). Built from the siblingagent-planforgecheckout viacontext: ../agent-planforge(seedocker-compose.yml). Runs both the planforge CLI and scaffoldkit in-container. Internal-only, no Traefik labels, no published ports.appreaches it via the sharedtraefikdocker network athttp://planforge:8223.
Both services need PLANFORGE_SERVICE_TOKEN in .env. Compose propagates it; mismatched values cause app to get 401s from planforge.
Token rotation (manual, v1):
cd /root/git/project-forge
NEW_TOKEN=$(openssl rand -hex 32)
sed -i "s/^PLANFORGE_SERVICE_TOKEN=.*/PLANFORGE_SERVICE_TOKEN=$NEW_TOKEN/" .env
docker compose up -d --build # rebuild both so the new token is live simultaneouslyA token store + in-place rotation is a follow-up (see ADR-0002).
All endpoints require an API token generated in the dashboard, passed via the X-API-Key header.
Rate limit: 10 project publishes per user per day. Only publish and the one-shot POST /api/v1/projects count against it; generate, preview, and the project list/delete endpoints are unmetered. The quota is counted per user, across all of that user's tokens.
List all projects for the authenticated user.
curl https://project-forge.opentriologue.ai/api/v1/projects \
-H "X-API-Key: pf_your_token_here"Soft-delete a project by its id (the id field returned by GET /api/v1/projects), passed as a query parameter.
curl -X DELETE "https://project-forge.opentriologue.ai/api/v1/projects?id=clx..." \
-H "X-API-Key: pf_your_token_here"Generate a project scaffold without publishing it. Returns a sessionId (a UUID) used by preview and publish. A session expires one hour after it is generated.
curl -X POST https://project-forge.opentriologue.ai/api/v1/generate \
-H "X-API-Key: pf_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"projectName": "my-cli-tool",
"summary": "A CLI that syncs agent memory via Git",
"features": ["push memory files", "pull and merge", "conflict resolution"],
"constraints": ["TypeScript only", "no external databases"],
"targetUsers": ["developers", "AI agents"]
}'Response:
{
"ok": true,
"sessionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"preview": { "...": "file tree, tasks, architecture overview" }
}Fetch the generated preview (file tree, tasks, architecture) for a given sessionId (the value returned by generate).
curl "https://project-forge.opentriologue.ai/api/v1/preview?sessionId=f47ac10b-58cc-4372-a567-0e02b2c3d479" \
-H "X-API-Key: pf_your_token_here"Finalize a previewed project and create the GitHub repository. Requires a GitHub PAT configured in your dashboard, and counts against your daily publish quota.
curl -X POST https://project-forge.opentriologue.ai/api/v1/publish \
-H "X-API-Key: pf_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "sessionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479" }'Response:
{
"ok": true,
"result": {
"repoUrl": "https://github.com/your-username/my-cli-tool",
"cloneUrl": "https://github.com/your-username/my-cli-tool.git",
"projectName": "my-cli-tool"
}
}One-shot create: generate, scaffold, create the GitHub repository, and push in a single call, skipping the separate preview step. Requires a GitHub PAT configured in your dashboard, and counts against your daily publish quota. The request body is the same shape as generate.
curl -X POST https://project-forge.opentriologue.ai/api/v1/projects \
-H "X-API-Key: pf_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"projectName": "my-cli-tool",
"summary": "A CLI that syncs agent memory via Git",
"features": ["push memory files", "pull and merge"]
}'Returns the same { ok, result: { repoUrl, cloneUrl, projectName } } shape as publish.
Full API documentation: project-forge.opentriologue.ai/docs
- Frontend: Next.js 15 + TypeScript + Tailwind CSS
- Auth: next-auth (email/password + GitHub OAuth)
- Database: SQLite via Prisma (API tokens, users)
- Planning + Scaffolding: agent-planforge HTTP service (bundles scaffoldkit in its own container; project-forge is Node-only)
- AI: Local OpenAI-compatible endpoint, Groq (llama-3.3-70b-versatile), or OpenAI (gpt-4o-mini)
- Deploy: Docker + Traefik
npm install
npm run devMIT
