@oomerevren/tryforge 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +107 -13
  2. package/README.md +172 -232
  3. package/dist/cli/src/adapters/agents-md.js +24 -0
  4. package/dist/cli/src/adapters/base.js +99 -0
  5. package/dist/cli/src/adapters/claude.js +43 -14
  6. package/dist/cli/src/adapters/codex.js +18 -17
  7. package/dist/cli/src/adapters/cursor.js +44 -30
  8. package/dist/cli/src/adapters/dsh.js +28 -30
  9. package/dist/cli/src/adapters/generic.js +10 -7
  10. package/dist/cli/src/adapters/opencode.js +23 -23
  11. package/dist/cli/src/adapters/types.js +12 -9
  12. package/dist/cli/src/adapters/windsurf.js +48 -28
  13. package/dist/cli/src/commands/add-external.js +111 -0
  14. package/dist/cli/src/commands/audit.js +68 -30
  15. package/dist/cli/src/commands/init.js +2 -2
  16. package/dist/cli/src/commands/install.js +90 -15
  17. package/dist/cli/src/commands/pack.js +119 -0
  18. package/dist/cli/src/commands/sync.js +181 -0
  19. package/dist/cli/src/commands/test.js +72 -0
  20. package/dist/cli/src/commands/tui.js +191 -0
  21. package/dist/cli/src/commands/update.js +4 -4
  22. package/dist/cli/src/commands/verify.js +62 -0
  23. package/dist/cli/src/core/fsutil.js +37 -0
  24. package/dist/cli/src/core/installer.js +9 -9
  25. package/dist/cli/src/core/lock.js +97 -10
  26. package/dist/cli/src/core/merge.js +108 -0
  27. package/dist/cli/src/core/plugin.js +2 -2
  28. package/dist/cli/src/core/project.js +136 -4
  29. package/dist/cli/src/core/registry.js +9 -9
  30. package/dist/cli/src/core/scan.js +159 -0
  31. package/dist/cli/src/core/semver.js +7 -7
  32. package/dist/cli/src/core/sign.js +2 -2
  33. package/dist/cli/src/core/sources.js +171 -0
  34. package/dist/cli/src/index.js +83 -16
  35. package/dist/index.cjs +359 -0
  36. package/dist/scripts/build-registry.js +2 -4
  37. package/dist/scripts/publish-verified.js +17 -9
  38. package/dist/scripts/seed-registry-13lite.js +5 -5
  39. package/dist/scripts/seed-registry.js +4 -4
  40. package/dist/scripts/verify-npm-mcps.js +6 -4
  41. package/package.json +15 -6
package/README.md CHANGED
@@ -1,107 +1,54 @@
1
- # Forge — The Homebrew for AI Agents
1
+ # Forge — The Universal Package Manager for AI Agent Context, Skills & MCPs
2
+
3
+ > **Stop manually copying `.cursorrules` and `mcp.json` across 5 different AI editors. One command to rule them all.**
4
+
5
+ <div align="center">
2
6
 
3
7
  [![CI](https://github.com/oomerevren-beep/forge/actions/workflows/ci.yml/badge.svg)](https://github.com/oomerevren-beep/forge/actions)
4
8
  [![npm version](https://img.shields.io/npm/v/tryforge?label=npm&color=CB3837)](https://www.npmjs.com/package/tryforge)
5
9
  [![npm downloads](https://img.shields.io/npm/dw/tryforge?label=downloads)](https://www.npmjs.com/package/tryforge)
6
10
  [![license MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
- [![registry](https://img.shields.io/badge/registry-250%20packages-green.svg)](registry/index.json)
11
+ [![registry](https://img.shields.io/badge/registry-21%20verified%20packages-green.svg)](registry/index.json)
8
12
  [![GitHub stars](https://img.shields.io/github/stars/oomerevren-beep/forge?style=social)](https://github.com/oomerevren-beep/forge)
9
13
 
10
- > **One CLI to install skills, MCPs, plugins, agents on any harness.**
11
-
12
- `brew` is for system packages. `forge` is for AI agent packages. One command, every harness — no more `git clone + cp SKILL.md` four times for four tools.
14
+ <br>
13
15
 
14
16
  ```bash
15
- # macOS / Linux
16
- curl -fsSL https://raw.githubusercontent.com/oomerevren-beep/forge/main/install.sh | sh
17
- # Windows PowerShell
18
- irm https://raw.githubusercontent.com/oomerevren-beep/forge/main/install.ps1 | iex
19
- # or, with Node 22+
20
- npm i -g tryforge
17
+ npx -y tryforge doctor
18
+ forge add agent-security-auditor
21
19
  ```
22
20
 
23
- ```bash
24
- forge doctor # detect your harnesses
25
- forge add pdf/extract # skill → all harnesses at once
26
- forge add mcp/filesystem # MCP server → auto mcp.json
27
- ```
28
-
29
- **Star to get notified at v1.0** — questions in [Discussions](https://github.com/oomerevren-beep/forge/discussions).
21
+ <br>
30
22
 
31
- <p align="center">
32
- <img src="docs/assets/og.png" alt="Forge — The Homebrew for AI Agents" width="640" />
33
- </p>
34
- <p align="center">
35
- <img src="docs/assets/demo.gif" alt="forge demo — doctor, search, add, list in seconds" width="640" />
36
- <br><em>7-second wow: <code>forge doctor → search → add → list</code></em>
37
- </p>
38
-
39
- ---
23
+ <em>3-second wow: `forge add agent-security-auditor` writes rules to Cursor, Claude, Codex, Windsurf — simultaneously.</em>
40
24
 
41
- ## Table of Contents
42
-
43
- - [Why Forge?](#why-forge)
44
- - [Features](#features)
45
- - [Install](#install)
46
- - [Quick Start](#quick-start)
47
- - [Team Sync — `forge install`](#team-sync--forge-install)
48
- - [Create a Package](#create-a-package)
49
- - [How it Works](#how-it-works)
50
- - [Comparison](#comparison)
51
- - [Registry — 250 Packages](#registry--250-packages)
52
- - [Architecture](#architecture)
53
- - [Docs](#docs)
54
- - [Roadmap](#roadmap)
55
- - [Contributing](#contributing)
56
- - [FAQ](#faq)
57
- - [License](#license)
25
+ </div>
58
26
 
59
27
  ---
60
28
 
61
29
  ## Why Forge?
62
30
 
63
- 2026: everything is a skill, plugin, or MCP but installing one is still stone age. Every harness has its own folder, no versioning, no update path.
64
-
65
- - `obra/superpowers` — **~280k stars** — install is still manual `git clone + cp`
66
- - `deepseek-harness` — **~208k stars, ~2 days to 100k** — proved "Everything is a Plugin", but DeepSeek-only
67
- - `anthropics/skills` — **~173k stars** — Claude-only
68
- - `mcp-registry` — MCP-only, no skills or agents
69
-
70
- Result: a developer using Claude Code + Codex + OpenCode + Cursor installs the **same package 4 times by hand**. No `update`, no `forge.toml`, no team sync.
71
-
72
- **Forge fixes it:** 6 package types × 7 harnesses × one CLI. Like `brew` unified system packages, `forge` unifies agent packages. Viral loop: creators promote `forge add me` to distribute their own work.
73
-
74
- | Type | Example | What it does |
75
- |------|---------|--------------|
76
- | `skill` | `anthropics/plan` | `SKILL.md` capability (Anthropic standard) |
77
- | `mcp` | `mcp/filesystem` | Model Context Protocol server |
78
- | `plugin` | `dsh/desktop` | Harness extension |
79
- | `agent` | `agency/frontend` | Subagent definition |
80
- | `command` | `cmd/plan` | Slash command `/plan` |
81
- | `hook` | `hook/pre-tool` | Lifecycle hook |
31
+ You're using Claude Code + Codex + OpenCode + Cursor. You want the same security rules, MCP servers, and skills everywhere. Today you:
82
32
 
83
- ---
33
+ 1. `git clone` a repo
34
+ 2. Copy `SKILL.md` to 4 different folders
35
+ 3. Manually paste the same rules into `.cursorrules`, `CLAUDE.md`, `.windsurfrules`
36
+ 4. Repeat for every new skill, every update
84
37
 
85
- ## Features
38
+ **Forge fixes it.** One command → every editor. Deterministic `forge.toml` → your whole team ships the same AI context.
86
39
 
87
- - **Universal — 6 types, one registry.** Skills + MCPs + plugins + agents + commands + hooks in one place.
88
- - **Multi-harness — 7 adapters today.** One file per harness, so adding Antigravity, Droid, or Copilot is a single PR. Symlink (junction on Windows) preferred, copy fallback.
89
- - **Team sync — `forge.toml` + `forge.lock`.** Like `package.json` for agents. `forge install` / `forge install --frozen` for CI.
90
- - **Search in <200ms.** Offline scored `search.json` + typed index, no API key.
91
- - **Git-native registry.** Every package is a GitHub repo. Forkable, private registry ready. No central DB.
92
- - **Safe by default.** `sha256`-verified tarballs or hard fail (no silent fallback); mock content only with explicit `--mock`; `forge audit` flags unverified installs; `forge doctor` health check; Windows/Linux/macOS.
40
+ <div align="center">
93
41
 
94
- Supported harnesses (`forge doctor` detects all of them):
42
+ | | Manual Setup | Forge |
43
+ |---|---|---|
44
+ | Multi-editor support | ❌ Copy-paste × 4 | ✅ One command |
45
+ | Version pinning | ❌ None | ✅ `forge.lock` + SHA-256 |
46
+ | Security audit | ❌ Zero | ✅ AST scanner (HIGH = refuse) |
47
+ | Team sync | ❌ Out of sync | ✅ `forge sync` |
48
+ | Updates | ❌ Manual | ✅ `forge update` |
49
+ | Zero-install | ❌ | ✅ `npx -y tryforge` |
95
50
 
96
- | Harness | Status |
97
- |---------|:------:|
98
- | Claude Code | ✅ |
99
- | Codex | ✅ |
100
- | OpenCode | ✅ |
101
- | Cursor | ✅ |
102
- | DeepSeek (dsh) | ⚠️ (community/untested) |
103
- | Windsurf | ✅ |
104
- | Generic (any other) | ✅ |
51
+ </div>
105
52
 
106
53
  ---
107
54
 
@@ -114,238 +61,229 @@ curl -fsSL https://raw.githubusercontent.com/oomerevren-beep/forge/main/install.
114
61
  # Windows PowerShell
115
62
  irm https://raw.githubusercontent.com/oomerevren-beep/forge/main/install.ps1 | iex
116
63
 
117
- # via npm (Node 22+)
64
+ # Or with Node 22+
118
65
  npm i -g tryforge
119
66
  ```
120
67
 
121
- Requires Node 22+ (TypeScript). Details and troubleshooting: [docs/INSTALL.md](docs/INSTALL.md).
68
+ ```bash
69
+ npx -y tryforge doctor # zero-install — no global install needed
70
+ ```
122
71
 
123
72
  ---
124
73
 
125
- ## Quick Start
126
-
127
- 60 seconds, copy-paste:
74
+ ## Quick Start (60 seconds)
128
75
 
129
76
  ```bash
130
- npm i -g tryforge # or: curl -fsSL https://raw.githubusercontent.com/oomerevren-beep/forge/main/install.sh | sh
131
- forge doctor # detect your harnesses (7 checked)
132
- forge add anthropics/plan # install latest → all harnesses at once
133
- ```
77
+ # 1. Initialize your project
78
+ npx forge init
134
79
 
135
- More once you're in:
80
+ # 2. Add the packages you want
81
+ forge add github:my-org/agent-security
82
+ forge add pdf/merge
83
+ forge add mcp/filesystem
136
84
 
137
- ```bash
138
- forge search plan # find packages (try: pdf, mcp, agent)
139
- forge list # installed, with versions
140
- forge info mcp/github # detail + versions + engines
141
- forge outdated # what can be updated
142
- forge update # update all (or: forge update mcp/github)
143
- forge remove obra/superpowers
85
+ # 3. Sync every editor
86
+ npx forge sync
144
87
  ```
145
88
 
146
- ```bash
147
- # version pinning
148
- forge add anthropics/plan@1.1.0
149
- forge add anthropics/plan@^1.2.0
89
+ Done. Cursor, Claude Code, Codex, OpenCode, Windsurf, DSH — all share the same context.
150
90
 
151
- # dry run — see what would happen
152
- forge add anthropics/plan --dry-run
91
+ ---
153
92
 
154
- # mock content for packages with no verified tarball yet (explicit opt-in)
155
- forge add skill/pdf --mock
156
- forge install --mock # same opt-in for project installs
157
- forge update mcp/github --mock
158
- ```
93
+ ## Supported Harnesses
159
94
 
160
- ---
95
+ | Harness | Status | Rule Format |
96
+ |---------|:------:|-------------|
97
+ | Claude Code | ✅ | `CLAUDE.md` merged blocks |
98
+ | Cursor | ✅ | `.cursor/rules/*.mdc` |
99
+ | OpenCode | ✅ | `AGENTS.md` shared blocks |
100
+ | Codex | ✅ | `AGENTS.md` shared blocks |
101
+ | Windsurf | ✅ | `.windsurfrules` merged |
102
+ | DSH | ⚠️ | `AGENTS.md` (community) |
103
+ | Generic | ✅ | `.forge/` fallback |
161
104
 
162
- ## Team Sync — `forge install`
105
+ ---
163
106
 
164
- Add `forge.toml` to your project, everyone gets the same set with one command.
107
+ ## Team Sync — `forge.toml`
165
108
 
166
109
  ```toml
167
- # my-project/forge.toml
110
+ # forge.toml — single source of truth for your project's AI context
168
111
  [project]
169
112
  name = "my-app"
170
- version = "0.1.0"
113
+ version = "1.0.0"
171
114
 
172
115
  [dependencies]
173
- "anthropics/plan" = "^1.2.0"
174
- "mcp/filesystem" = "^1.0.0"
175
- "obra/superpowers" = "^3.0.0"
176
- "skill/pdf" = "^1.0.0"
177
- ```
116
+ "agent-pr-reviewer" = "^1.2.0"
117
+ "mcp-filesystem" = "^1.0.0"
178
118
 
179
- ```bash
180
- forge install # installs all, writes forge.lock
181
- forge install --frozen # CI: exact versions from lock (like npm ci)
182
- forge outdated # shows 1.1.0 → 1.2.0 etc.
183
- forge update # bumps to latest within semver
184
- ```
119
+ [skills.team-rules]
120
+ source = "github:my-org/team-skills"
121
+ ref = "main"
185
122
 
186
- Lockfile `forge.lock` is `[[packages]]` TOML — commit it. `~/.forge/config.toml` holds user defaults (registry URL, default harnesses). Worked example: [examples/team-sync/](examples/team-sync/).
123
+ [agents.developer]
124
+ model = "claude-3-7-sonnet"
125
+ system_prompt = "Senior engineer. TDD. No shortcuts."
187
126
 
188
- ---
127
+ [mcp.servers.postgres]
128
+ command = "npx"
129
+ args = ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/db"]
189
130
 
190
- ## Create a Package
131
+ [permissions]
132
+ denied_paths = [".env*", "id_rsa*", "./secrets"]
133
+ allow_network = false
134
+ ```
191
135
 
192
136
  ```bash
193
- forge init my-skill --type skill --yes # → SKILL.md + forge.toml
194
- forge init my-mcp --type mcp --yes # → MCP template + [mcp] config
195
- forge init my-agent --type agent --yes # → agent.md template
196
- # types: skill | mcp | plugin | agent | command | hook
197
-
198
- cat forge.toml
199
- # [package] name="my-skill" version="0.1.0" type="skill" ...
200
-
201
- forge publish # (v0.2) validates → tarball → GitHub Release → registry PR
137
+ # Everyone on the team runs:
138
+ git pull
139
+ npx forge sync
140
+ # That's it identical AI context across every editor
202
141
  ```
203
142
 
204
- Until `publish` lands, open a PR adding `registry/packages/<slug>.json` (see `schema/forge.schema.json`), then `npm run registry:build`. Minimal working example: [examples/minimal-skill/](examples/minimal-skill/).
205
-
206
143
  ---
207
144
 
208
- ## How it Works
145
+ ## Security
209
146
 
210
- ```
211
- forge add anthropics/plan
212
- → resolve ^1.2.0 → tarball URL + sha256 (from local/bundled registry/index.json; CDN in v0.3)
213
- → download to ~/.forge/cache/tarballs/ → verify sha256 (hard fail on mismatch) → extract to ~/.forge/packages/anthropics-plan@1.2.0/
214
- → adapter: symlink/copy to all 7 harnesses (Claude/Codex/OpenCode/Cursor/DSH/Windsurf/Generic)
215
- → if MCP: backup mcp.json → inject server entry
216
- ```
147
+ Forge is **fail-closed** by default:
217
148
 
218
- Add a harness = one file in `cli/src/adapters/`. See `docs/ADAPTERS.md`.
149
+ - **sha256 verification** every package is hash-pinned; mismatch = exit 1
150
+ - **Static scanner** — 19 rules (shell-danger, prompt-inject, perm-violation); HIGH blocks install
151
+ - **`forge audit`** — flags mock/unverified installs (exit 1 on high-severity)
152
+ - **`forge.toml` [permissions]** — denied paths enforced per-project
219
153
 
220
- ```
221
- ~/.forge/
222
- config.toml # user config
223
- packages/<slug>@<ver>/ # extracted content
224
- cache/tarballs/ # downloaded .tar.gz
225
- links.json # {pkg, version, adapters[]} source of truth
154
+ ```bash
155
+ forge audit # scan installed packages
156
+ forge test ./my-package # pre-publish validation
157
+ forge verify ./my-package # full schema + security + adapter check
226
158
  ```
227
159
 
228
160
  ---
229
161
 
230
- ## Rekabet
231
-
232
- | | **Forge** | `npx skills` (Vercel) | `anthropics/skills` | `DSH` | `mcp-registry` |
233
- |---|---|---|---|---|---|
234
- | Türler | **6** (skill/mcp/plugin/agent/command/hook) | 1 (skill) | 1 (skill) | plugin | 1 (mcp) |
235
- | Harness | **7** (Claude/Codex/OpenCode/Cursor/DSH/Windsurf/Generic) | 75+ ajan | 1 | 1 | ~1 |
236
- | Versiyonlama | **semver + lock** | skills-lock.json | none | none | partial |
237
- | Güncelleme | `forge update` | check/update | manual | manual | manual |
238
- | Takım senkronu | **`forge.toml` + `forge.lock`** | none | none | none | none |
239
- | Arama | `<200ms` offline | `skills find` | GitHub search | none | web only |
240
- | Paket doğrulama | **sha256 + fail-closed** | none | none | none | none |
241
- | Yerel CLI | **evet** (npm i -g) | npx (her seferinde indirir) | manual | manual | — |
162
+ ## Available Packages
242
163
 
243
- Fark: Forge, her paketi sha256 ile doğrular (fail-closed), `forge.toml` ile takım senkronu yapar, offline arama yapar ve yerel CLI olarak çalışır. Vercel skills repo-agnostik çalışır ama doğrulama ve takım senkronu yok.
244
-
245
- ---
164
+ **21 verified packages** (sha256-pinned). Registry is git-native and forkable.
246
165
 
247
- ## Registry 21 Verified Packages
248
-
249
- Epoch 1d: Sadece sha256 doğrulanmış paketler listeleniyor (fail-closed).
166
+ | Category | Examples |
167
+ |----------|----------|
168
+ | Skills | `cmd/plan`, `cmd/review`, `obra/superpowers` |
169
+ | MCP Servers | `mcp/filesystem`, `mcp/github`, `mcp/postgres`, `mcp/memory`, `mcp/sequential-thinking` |
170
+ | Agents | `agency/frontend`, `agency/backend` |
171
+ | PDF Tools | `pdf/merge`, `pdf/split`, `pdf/forms`, `pdf/ocr`, `pdf/extract`, `pdf/compress`, `pdf/convert`, `pdf/tables` |
250
172
 
251
173
  ```bash
252
- forge search mcp # 5 results
253
- forge search pdf # 8 results
254
- forge search --type skill plan # filtered
255
- forge info pdf/compress # versions, engines, sha
174
+ forge search pdf
175
+ forge search mcp
176
+ forge info mcp/github
256
177
  ```
257
178
 
258
- Stats: **9 skills, 5 MCPs, 5 agents, 2 commands.** Tümü verified (sha256 pinned).
259
-
260
- ```bash
261
- npm run registry:build # index + search + stats + --check in CI
262
- ```
179
+ ---
263
180
 
264
- Düzenli güncelleme: Yeni paketler eklemek için `registry/packages/<slug>.json` oluşturun → `npm run registry:build -- --check`.
181
+ ## Commands
182
+
183
+ | Command | What it does |
184
+ |---------|-------------|
185
+ | `forge add <pkg>` | Install to all harnesses (registry, GitHub, local) |
186
+ | `forge remove <pkg>` | Uninstall from all harnesses |
187
+ | `forge install` | Install all `[dependencies]` from `forge.toml` |
188
+ | `forge install --frozen` | CI mode: exact from `forge.lock` |
189
+ | `forge sync` | One-command team sync (skills + rules + MCP + roles) |
190
+ | `forge init <name>` | Scaffold a new package |
191
+ | `forge test <pkg>` | Validate against adapter matrix (dry-run) |
192
+ | `forge pack` | Build verified tarball |
193
+ | `forge verify <pkg>` | Schema + security + adapter check |
194
+ | `forge audit` | Scan installed packages (fail-closed) |
195
+ | `forge doctor` | Health check harnesses + store |
196
+ | `forge search <query>` | Fuzzy search (<200ms, offline) |
197
+ | `forge list` | List installed packages |
198
+ | `forge outdated` | Show packages with newer versions |
199
+ | `forge update` | Update all (or one) to latest |
200
+ | `forge tui` | Interactive terminal dashboard |
265
201
 
266
202
  ---
267
203
 
268
204
  ## Architecture
269
205
 
270
206
  ```
271
- CLI (TypeScript v0.1 → Rust v0.2)
207
+ CLI (TypeScript)
272
208
  ├─ registry client (index.json + semver)
273
- ├─ store (~/.forge/packages/ + links.json + cache)
274
- ├─ adapters (detect/install/list — 1 file per harness)
275
- └─ commands (add/remove/list/search/info/doctor/init/install/update/outdated/audit)
209
+ ├─ store (~/.forge/ + links.json + cache)
210
+ ├─ adapters (1 file per harness — symlink or copy)
211
+ ├─ core (merge engine, security scanner, lock, sources)
212
+ └─ commands (add/remove/sync/audit/test/pack/verify/tui)
276
213
  ```
277
214
 
278
- Full diagram and crate layout in `docs/ARCHITECTURE.md`. Tech choices: `commander` + `smol-toml` + `tsx` (no `bun` on Windows), `tsc` emit to `dist/` for `npm pack`.
215
+ **v0.1 v0.2 v1.0:**
216
+ - **v0.1** (now): 7 harnesses, 21 verified packages, full CLI
217
+ - **v0.2**: `forge publish`, Rust rewrite for `cargo install`
218
+ - **v1.0**: Team registry, `brew install forge`, `winget`
219
+
220
+ See [docs/ROADMAP.md](docs/ROADMAP.md).
279
221
 
280
222
  ---
281
223
 
282
- ## Docs
224
+ ## Add a Package
283
225
 
284
- - [Install](docs/INSTALL.md) — npm / curl / source, verification
285
- - [Examples](examples/) minimal skill + team sync, copy-paste
286
- - [Vision](docs/VISION.md) why now, why 100k
287
- - [PRD](docs/PRD.md) users, stories, commands, harness matrix
288
- - [Architecture](docs/ARCHITECTURE.md) — components, security, perf
289
- - [Package Spec](docs/SPEC.md) `forge.toml` fields per type
290
- - [Registry](docs/REGISTRY.md) — index schema, publish, fork
291
- - [Adapters](docs/ADAPTERS.md) — add a harness in one file
292
- - [Roadmap](docs/ROADMAP.md) v0.1 v1.0
293
- - [Changelog](CHANGELOG.md) — release history
226
+ ```bash
227
+ # 1. Create your package
228
+ forge init my-skill --type skill --yes
229
+ # Edit SKILL.md + forge.toml
230
+
231
+ # 2. Verify it
232
+ forge verify .
233
+
234
+ # 3. Publish (v0.2: tarball + GitHub Release + registry PR)
235
+ ```
236
+
237
+ Until `publish` lands, open a PR adding `registry/packages/<slug>.json` + run `npm run registry:build -- --check`.
294
238
 
295
239
  ---
296
240
 
297
- ## Roadmap
241
+ ## Add a Harness
298
242
 
299
- **v0.1 Homebrew moment** (now): 7 harnesses, 21 verified packages, `add/search/list/doctor/install/init`.
300
- **v0.2 — NPM moment**: `forge publish`, deps, `cargo install`.
301
- **v0.3 — Store moment**: `forge run`, Rust binary, GUI.
302
- **v1.0 — Cloud**: team registry, `brew install forge`, `winget`.
243
+ One file: `cli/src/adapters/<name>.ts`. Implement the `Adapter` interface. Register in `adapters/index.ts`. Done.
303
244
 
304
- See `docs/ROADMAP.md`.
245
+ See [docs/ADAPTERS.md](docs/ADAPTERS.md).
305
246
 
306
247
  ---
307
248
 
308
- ## Paket Doğrulama
249
+ ## Documentation
309
250
 
310
- Forge, fail-closed paket doğrulama sağlar:
251
+ - [Install Guide](docs/INSTALL.md)
252
+ - [Package Spec](docs/SPEC.md) — `forge.toml` fields per type
253
+ - [Architecture](docs/ARCHITECTURE.md) — components, security, perf
254
+ - [Adapters](docs/ADAPTERS.md) — add a harness in one file
255
+ - [Registry](docs/REGISTRY.md) — index schema, publish, fork
256
+ - [Roadmap](docs/ROADMAP.md)
257
+ - [Examples](examples/)
311
258
 
312
- 1. **sha256 pin**: Her paket sürümü SHA-256 hash'i ile imzalanır
313
- 2. **Verify on install**: İndirme sırasında hash kontrol edilir — uyarsa exit 1
314
- 3. **Audit trail**: `forge audit` mock/tamamlanmamış kurulumları listeler
259
+ ---
315
260
 
316
- Gelecek (v0.2): Sigstore/cosign ile imzalama, verified publisher programı.
261
+ ## Badges
317
262
 
318
- - Add a package: create `registry/packages/<slug>.json` `npm run registry:build`
319
- - Add a harness: `cli/src/adapters/<name>.ts` → register in `adapters/index.ts` → `forge doctor`
320
- - PR checklist: `npm run build && npm test && npm run registry:build -- --check`
321
- - New? Start with [`good first issue`](https://github.com/oomerevren-beep/forge/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) — questions in [Discussions](https://github.com/oomerevren-beep/forge/discussions)
263
+ Add `forge` to your project:
322
264
 
323
- See `CONTRIBUTING.md`, [Code of Conduct](CODE_OF_CONDUCT.md), [Security](SECURITY.md) and `AGENTS.md`.
265
+ ```markdown
266
+ [![Managed by Forge](https://img.shields.io/badge/Agent%20Context-Forge-6366f1?style=flat-square&logo=anthropic)](https://github.com/oomerevren-beep/forge)
267
+ ```
324
268
 
325
269
  ---
326
270
 
327
271
  ## FAQ
328
272
 
329
273
  **Is this just for Claude Code?**
330
- No. 7 harnesses today, one file per new harness. The point is *universal* — same reason `brew` beat per-OS managers.
331
-
332
- **How is this different from `mcp-registry` or `skills` repos?**
333
- Those are single-type and single-harness. Forge is `brew` for *all* agent package types, on *every* harness, with versioning/lock/search.
274
+ No. 7 harnesses today, one file per new harness. The point is *universal*.
334
275
 
335
276
  **Does `install.sh` need `forge.sh` domain?**
336
- No. `curl -fsSL https://raw.githubusercontent.com/oomerevren-beep/forge/main/install.sh | sh` works today. `forge.sh` is a future vanity alias.
337
-
338
- **Are most packages mock content?**
339
- Honest answer: 245 of 250 registry entries still carry placeholder SHAs (only 5 verified so far). Forge is fail-closed — installing one without `--mock` errors out instead of silently faking it; `forge audit` flags every unverified install. Real tarballs land as maintainers verify them (tracked for Faz 13-full).
277
+ No. Works from GitHub raw today.
340
278
 
341
- **Windows symlinks?**
342
- Junction (`symlinkSync(..., 'junction')`) on dirs, fallback to `cpSync` on `EPERM`. `doctor` checks `links.json` (source of truth), not just dir scan.
279
+ **Are packages verified?**
280
+ 21 are sha256-pinned and pass the static scanner. The rest is tracked for Phase 13.
343
281
 
344
- **Why TypeScript first, not Rust?**
345
- Speed to market. v0.1 is TypeScript + `tsx`; v0.2 rewrites to Rust for single binary `cargo install`. Adapters stay cheap.
282
+ **Windows support?**
283
+ Full. Junction on dirs, file-by-file copy fallback for non-ASCII paths, PowerShell installer.
346
284
 
347
285
  **Private registry?**
348
- Yes. Fork this repo, keep `registry/` private, point `~/.forge/config.toml` `registry = "https://your-r2/index.json"`.
286
+ Yes. Fork this repo, keep `registry/` private, point `~/.forge/config.toml` to your own index.
349
287
 
350
288
  ---
351
289
 
@@ -355,7 +293,9 @@ MIT — see [LICENSE](LICENSE).
355
293
 
356
294
  ---
357
295
 
358
- <p align="center">
359
- <strong>Star this repo to get notified at launch. 21 verified packages are live at <a href="https://github.com/oomerevren-beep/forge/releases/tag/v0.1.1">v0.1.1</a>.</strong><br>
360
- <code>forge add</code> 7 places at once. <code>forge install</code> → team sync. Homebrew simple.
361
- </p>
296
+ <div align="center">
297
+
298
+ <strong>Star this repo to get notified at v1.0.</strong><br>
299
+ <code>forge add</code> → 7 places at once. <code>forge sync</code> → team sync. Homebrew simple.
300
+
301
+ </div>
@@ -0,0 +1,24 @@
1
+ // cli/src/adapters/agents-md.ts — Shared AGENTS.md rule sync (Phase 2).
2
+ //
3
+ // OpenCode, Codex, and DSH all honor the AGENTS.md project convention:
4
+ // standard system-prompt rules in one shared file. Forge merges one marked
5
+ // block per package and never touches surrounding user content.
6
+ import { join } from "path";
7
+ import { pointerBody, syncBlockFile, unsyncBlockFile, shouldSyncRules, } from "./base.js";
8
+ export function agentsMdPath(projectDir) {
9
+ return join(projectDir, "AGENTS.md");
10
+ }
11
+ export function syncAgentsMd(projectDir, pkgSlug, skillPath, meta) {
12
+ const file = agentsMdPath(projectDir);
13
+ if (!shouldSyncRules(projectDir, file))
14
+ return;
15
+ syncBlockFile(file, pkgSlug, meta?.version ?? "0.0.0", pointerBody({
16
+ slug: pkgSlug,
17
+ version: meta?.version ?? "",
18
+ description: meta?.description ?? `${pkgSlug} (installed via Forge)`,
19
+ skillPath,
20
+ }));
21
+ }
22
+ export function unsyncAgentsMd(projectDir, pkgSlug) {
23
+ unsyncBlockFile(agentsMdPath(projectDir), pkgSlug);
24
+ }
@@ -0,0 +1,99 @@
1
+ // cli/src/adapters/base.ts — Shared adapter foundation (Phase 2).
2
+ //
3
+ // Eliminates the copy-pasted project-or-home resolution, list/isInstalled
4
+ // loops, and rule-file sync shared by all file-based harness adapters.
5
+ // Adapters keep their own path quirks; everything mechanical lives here.
6
+ //
7
+ // Test hook: set FORGE_TEST_HOME to redirect home-dir resolution into a
8
+ // temp dir so adapter tests never touch the real ~/.cursor, ~/.claude, ...
9
+ import { existsSync, readFileSync, writeFileSync } from "fs";
10
+ import { join, dirname } from "path";
11
+ import { homedir } from "os";
12
+ import { installSkillFiles, uninstallSkillFiles, listDirNames, ensureDir, backupFileIfExists, } from "./types.js";
13
+ import { upsertForgeBlock, removeForgeBlock } from "../core/merge.js";
14
+ export function testHome() {
15
+ return process.env.FORGE_TEST_HOME ?? homedir();
16
+ }
17
+ /** Build the instruction body for rule files: SKILL.md/agent.md excerpt, capped. */
18
+ export function instructionBody(srcDir, fallback) {
19
+ for (const f of ["SKILL.md", "agent.md"]) {
20
+ try {
21
+ const p = join(srcDir, f);
22
+ if (existsSync(p)) {
23
+ const text = readFileSync(p, "utf-8").trim().slice(0, 2000);
24
+ if (text.length > 0)
25
+ return `${text}\n`;
26
+ }
27
+ }
28
+ catch {
29
+ /* unreadable source — use the fallback line */
30
+ }
31
+ }
32
+ return `${fallback}\n`;
33
+ }
34
+ /** Short pointer body for merged files (CLAUDE.md, AGENTS.md, .windsurfrules). */
35
+ export function pointerBody(pkg) {
36
+ const at = pkg.version ? `@${pkg.version}` : "";
37
+ return `- ${pkg.slug}${at}: ${pkg.description}\n Full instructions: ${pkg.skillPath}\n`;
38
+ }
39
+ export async function sharedList(paths) {
40
+ for (const b of paths.skillBases()) {
41
+ if (existsSync(b))
42
+ return listDirNames(b);
43
+ }
44
+ return [];
45
+ }
46
+ export async function sharedIsInstalled(paths, pkgSlug) {
47
+ return paths.skillBases().some((b) => existsSync(join(b, pkgSlug)));
48
+ }
49
+ export function sharedUninstall(paths, pkgSlug) {
50
+ for (const b of paths.skillBases())
51
+ uninstallSkillFiles(pkgSlug, b);
52
+ }
53
+ export function sharedInstall(paths, pkgSlug, srcDir) {
54
+ installSkillFiles("forge", pkgSlug, srcDir, paths.installBase());
55
+ }
56
+ const PROJECT_MARKERS = [
57
+ "forge.toml",
58
+ "package.json",
59
+ ".git",
60
+ "AGENTS.md",
61
+ "CLAUDE.md",
62
+ ".cursor",
63
+ "opencode.json",
64
+ ".codex",
65
+ ".windsurf",
66
+ ".dsh",
67
+ ];
68
+ /** True when dir looks like a project (or already holds the rule file). */
69
+ export function isProjectDir(dir) {
70
+ return PROJECT_MARKERS.some((m) => existsSync(join(dir, m)));
71
+ }
72
+ /** Merge-gate for cwd-root rule files: sync when the file exists or dir is a project. */
73
+ export function shouldSyncRules(dir, filePath) {
74
+ return existsSync(filePath) || isProjectDir(dir);
75
+ }
76
+ /** Write a fully forge-managed per-package file (e.g. .cursor/rules/<slug>.mdc).
77
+ * An existing file WITHOUT a forge marker is backed up (.bak) first so user
78
+ * content is never silently lost; files already carrying our marker for the
79
+ * same id are overwritten in place.
80
+ */
81
+ export function writeManagedFile(filePath, id, content) {
82
+ ensureDir(dirname(filePath));
83
+ if (existsSync(filePath)) {
84
+ const raw = readFileSync(filePath, "utf-8");
85
+ if (!raw.includes(`id="${id}"`))
86
+ backupFileIfExists(filePath);
87
+ }
88
+ writeFileSync(filePath, content);
89
+ }
90
+ /** Merge a forge block into a user-owned file (never touches outside content). */
91
+ export function syncBlockFile(filePath, id, version, body) {
92
+ ensureDir(dirname(filePath));
93
+ upsertForgeBlock(filePath, id, version, body);
94
+ }
95
+ /** Remove only our block; delete the file when forge created it and it is now blank. */
96
+ export function unsyncBlockFile(filePath, id) {
97
+ removeForgeBlock(filePath, id, { deleteIfEmpty: true });
98
+ }
99
+ export { upsertForgeBlock, removeForgeBlock };