@ipul-labs/forge 1.21.2 → 1.35.0

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 (298) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -78
  3. package/dist/apple-touch-icon.png +0 -0
  4. package/dist/assets/index-BmEuPeOG.js +27 -0
  5. package/dist/assets/index-CSH1OQYQ.css +1 -0
  6. package/dist/boot-check.js +98 -0
  7. package/dist/favicon.svg +8 -0
  8. package/dist/icon-192.png +0 -0
  9. package/dist/icon-512.png +0 -0
  10. package/dist/icon.svg +12 -0
  11. package/dist/index.html +33 -0
  12. package/dist/manifest.webmanifest +18 -0
  13. package/dist/theme-init.js +11 -0
  14. package/lib/bin/cli/analyze.d.ts.map +1 -1
  15. package/lib/bin/cli/analyze.js +3 -44
  16. package/lib/bin/cli/analyze.js.map +1 -1
  17. package/lib/bin/cli/apply.d.ts.map +1 -1
  18. package/lib/bin/cli/apply.js +2 -20
  19. package/lib/bin/cli/apply.js.map +1 -1
  20. package/lib/bin/cli/cifix.d.ts.map +1 -1
  21. package/lib/bin/cli/cifix.js +4 -28
  22. package/lib/bin/cli/cifix.js.map +1 -1
  23. package/lib/bin/cli/close.d.ts.map +1 -1
  24. package/lib/bin/cli/close.js +2 -33
  25. package/lib/bin/cli/close.js.map +1 -1
  26. package/lib/bin/cli/createIssue.d.ts.map +1 -1
  27. package/lib/bin/cli/createIssue.js +3 -12
  28. package/lib/bin/cli/createIssue.js.map +1 -1
  29. package/lib/bin/cli/doctor.d.ts.map +1 -1
  30. package/lib/bin/cli/doctor.js +3 -4
  31. package/lib/bin/cli/doctor.js.map +1 -1
  32. package/lib/bin/cli/init.js +1 -10
  33. package/lib/bin/cli/init.js.map +1 -1
  34. package/lib/bin/cli/issue.d.ts.map +1 -1
  35. package/lib/bin/cli/issue.js +3 -12
  36. package/lib/bin/cli/issue.js.map +1 -1
  37. package/lib/bin/cli/issues.d.ts.map +1 -1
  38. package/lib/bin/cli/issues.js +3 -12
  39. package/lib/bin/cli/issues.js.map +1 -1
  40. package/lib/bin/cli/merge.d.ts.map +1 -1
  41. package/lib/bin/cli/merge.js +4 -20
  42. package/lib/bin/cli/merge.js.map +1 -1
  43. package/lib/bin/cli/refine.d.ts.map +1 -1
  44. package/lib/bin/cli/refine.js +2 -26
  45. package/lib/bin/cli/refine.js.map +1 -1
  46. package/lib/bin/cli/repl.d.ts.map +1 -1
  47. package/lib/bin/cli/repl.js +4 -13
  48. package/lib/bin/cli/repl.js.map +1 -1
  49. package/lib/bin/cli/repos.d.ts.map +1 -1
  50. package/lib/bin/cli/repos.js +1 -11
  51. package/lib/bin/cli/repos.js.map +1 -1
  52. package/lib/bin/cli/resetPassword.d.ts +21 -0
  53. package/lib/bin/cli/resetPassword.d.ts.map +1 -0
  54. package/lib/bin/cli/resetPassword.js +69 -0
  55. package/lib/bin/cli/resetPassword.js.map +1 -0
  56. package/lib/bin/cli/resolution.d.ts.map +1 -1
  57. package/lib/bin/cli/resolution.js +2 -19
  58. package/lib/bin/cli/resolution.js.map +1 -1
  59. package/lib/bin/cli/serverClient.d.ts +2 -0
  60. package/lib/bin/cli/serverClient.d.ts.map +1 -1
  61. package/lib/bin/cli/serverClient.js +8 -4
  62. package/lib/bin/cli/serverClient.js.map +1 -1
  63. package/lib/bin/cli/session.d.ts.map +1 -1
  64. package/lib/bin/cli/session.js.map +1 -1
  65. package/lib/bin/cli/sessionStore.d.ts +1 -1
  66. package/lib/bin/cli/sessionStore.js +2 -2
  67. package/lib/bin/cli/sessionStore.js.map +1 -1
  68. package/lib/bin/cli/ship.d.ts.map +1 -1
  69. package/lib/bin/cli/ship.js +15 -23
  70. package/lib/bin/cli/ship.js.map +1 -1
  71. package/lib/bin/cli/update.d.ts.map +1 -1
  72. package/lib/bin/cli/update.js +34 -28
  73. package/lib/bin/cli/update.js.map +1 -1
  74. package/lib/bin/cli/updatePlan.d.ts +30 -0
  75. package/lib/bin/cli/updatePlan.d.ts.map +1 -0
  76. package/lib/bin/cli/updatePlan.js +50 -0
  77. package/lib/bin/cli/updatePlan.js.map +1 -0
  78. package/lib/bin/cli/utils.d.ts +3 -0
  79. package/lib/bin/cli/utils.d.ts.map +1 -1
  80. package/lib/bin/cli/utils.js +7 -23
  81. package/lib/bin/cli/utils.js.map +1 -1
  82. package/lib/bin/cli/validate.d.ts.map +1 -1
  83. package/lib/bin/cli/validate.js +3 -25
  84. package/lib/bin/cli/validate.js.map +1 -1
  85. package/lib/bin/cli/watch.d.ts.map +1 -1
  86. package/lib/bin/cli/watch.js +3 -12
  87. package/lib/bin/cli/watch.js.map +1 -1
  88. package/lib/bin/forge-agent.js +10 -22
  89. package/lib/bin/forge-agent.js.map +1 -1
  90. package/lib/server/app.d.ts +24 -0
  91. package/lib/server/app.d.ts.map +1 -0
  92. package/lib/server/app.js +58 -0
  93. package/lib/server/app.js.map +1 -0
  94. package/lib/server/forge/analyses/analysisStore.d.ts +53 -0
  95. package/lib/server/forge/analyses/analysisStore.d.ts.map +1 -0
  96. package/lib/server/forge/analyses/analysisStore.js +77 -0
  97. package/lib/server/forge/analyses/analysisStore.js.map +1 -0
  98. package/lib/server/forge/auth/apiTokens.d.ts +34 -0
  99. package/lib/server/forge/auth/apiTokens.d.ts.map +1 -0
  100. package/lib/server/forge/auth/apiTokens.js +44 -0
  101. package/lib/server/forge/auth/apiTokens.js.map +1 -0
  102. package/lib/server/forge/auth/auditLog.d.ts +36 -0
  103. package/lib/server/forge/auth/auditLog.d.ts.map +1 -0
  104. package/lib/server/forge/auth/auditLog.js +56 -0
  105. package/lib/server/forge/auth/auditLog.js.map +1 -0
  106. package/lib/server/forge/auth/authConfig.d.ts +13 -0
  107. package/lib/server/forge/auth/authConfig.d.ts.map +1 -0
  108. package/lib/server/forge/auth/authConfig.js +37 -0
  109. package/lib/server/forge/auth/authConfig.js.map +1 -0
  110. package/lib/server/forge/auth/createAuth.d.ts +130 -0
  111. package/lib/server/forge/auth/createAuth.d.ts.map +1 -0
  112. package/lib/server/forge/auth/createAuth.js +387 -0
  113. package/lib/server/forge/auth/createAuth.js.map +1 -0
  114. package/lib/server/forge/auth/middleware.d.ts +10 -0
  115. package/lib/server/forge/auth/middleware.d.ts.map +1 -0
  116. package/lib/server/forge/auth/middleware.js +22 -0
  117. package/lib/server/forge/auth/middleware.js.map +1 -0
  118. package/lib/server/forge/auth/oidc.d.ts +38 -0
  119. package/lib/server/forge/auth/oidc.d.ts.map +1 -0
  120. package/lib/server/forge/auth/oidc.js +63 -0
  121. package/lib/server/forge/auth/oidc.js.map +1 -0
  122. package/lib/server/forge/auth/passwords.d.ts +7 -0
  123. package/lib/server/forge/auth/passwords.d.ts.map +1 -0
  124. package/lib/server/forge/auth/passwords.js +28 -0
  125. package/lib/server/forge/auth/passwords.js.map +1 -0
  126. package/lib/server/forge/auth/resetPassword.d.ts +14 -0
  127. package/lib/server/forge/auth/resetPassword.d.ts.map +1 -0
  128. package/lib/server/forge/auth/resetPassword.js +29 -0
  129. package/lib/server/forge/auth/resetPassword.js.map +1 -0
  130. package/lib/server/forge/auth/roles.d.ts +7 -0
  131. package/lib/server/forge/auth/roles.d.ts.map +1 -0
  132. package/lib/server/forge/auth/roles.js +15 -0
  133. package/lib/server/forge/auth/roles.js.map +1 -0
  134. package/lib/server/forge/auth/sessions.d.ts +27 -0
  135. package/lib/server/forge/auth/sessions.d.ts.map +1 -0
  136. package/lib/server/forge/auth/sessions.js +37 -0
  137. package/lib/server/forge/auth/sessions.js.map +1 -0
  138. package/lib/server/forge/auth/testHarness.d.ts +104 -0
  139. package/lib/server/forge/auth/testHarness.d.ts.map +1 -0
  140. package/lib/server/forge/auth/testHarness.js +53 -0
  141. package/lib/server/forge/auth/testHarness.js.map +1 -0
  142. package/lib/server/forge/auth/tokenHash.d.ts +3 -0
  143. package/lib/server/forge/auth/tokenHash.d.ts.map +1 -0
  144. package/lib/server/forge/auth/tokenHash.js +4 -0
  145. package/lib/server/forge/auth/tokenHash.js.map +1 -0
  146. package/lib/server/forge/auth/users.d.ts +51 -0
  147. package/lib/server/forge/auth/users.d.ts.map +1 -0
  148. package/lib/server/forge/auth/users.js +118 -0
  149. package/lib/server/forge/auth/users.js.map +1 -0
  150. package/lib/server/forge/core/ForgeAgent.d.ts +58 -1
  151. package/lib/server/forge/core/ForgeAgent.d.ts.map +1 -1
  152. package/lib/server/forge/core/ForgeAgent.js +280 -32
  153. package/lib/server/forge/core/ForgeAgent.js.map +1 -1
  154. package/lib/server/forge/core/agentClient.d.ts +7 -5
  155. package/lib/server/forge/core/agentClient.d.ts.map +1 -1
  156. package/lib/server/forge/core/agentClient.js +11 -15
  157. package/lib/server/forge/core/agentClient.js.map +1 -1
  158. package/lib/server/forge/core/agentMode.d.ts +38 -0
  159. package/lib/server/forge/core/agentMode.d.ts.map +1 -0
  160. package/lib/server/forge/core/agentMode.js +43 -0
  161. package/lib/server/forge/core/agentMode.js.map +1 -0
  162. package/lib/server/forge/core/claudeClient.d.ts +63 -0
  163. package/lib/server/forge/core/claudeClient.d.ts.map +1 -1
  164. package/lib/server/forge/core/claudeClient.js +142 -50
  165. package/lib/server/forge/core/claudeClient.js.map +1 -1
  166. package/lib/server/forge/core/configStore.d.ts +12 -1
  167. package/lib/server/forge/core/configStore.d.ts.map +1 -1
  168. package/lib/server/forge/core/configStore.js +39 -2
  169. package/lib/server/forge/core/configStore.js.map +1 -1
  170. package/lib/server/forge/core/dependencyPaths.d.ts +19 -0
  171. package/lib/server/forge/core/dependencyPaths.d.ts.map +1 -0
  172. package/lib/server/forge/core/dependencyPaths.js +32 -0
  173. package/lib/server/forge/core/dependencyPaths.js.map +1 -0
  174. package/lib/server/forge/core/evidence.d.ts +43 -0
  175. package/lib/server/forge/core/evidence.d.ts.map +1 -0
  176. package/lib/server/forge/core/evidence.js +108 -0
  177. package/lib/server/forge/core/evidence.js.map +1 -0
  178. package/lib/server/forge/core/jobs.d.ts +2 -0
  179. package/lib/server/forge/core/jobs.d.ts.map +1 -1
  180. package/lib/server/forge/core/jobs.js +8 -0
  181. package/lib/server/forge/core/jobs.js.map +1 -1
  182. package/lib/server/forge/core/localRepo.d.ts +48 -7
  183. package/lib/server/forge/core/localRepo.d.ts.map +1 -1
  184. package/lib/server/forge/core/localRepo.js +123 -69
  185. package/lib/server/forge/core/localRepo.js.map +1 -1
  186. package/lib/server/forge/core/prompts.d.ts +20 -0
  187. package/lib/server/forge/core/prompts.d.ts.map +1 -1
  188. package/lib/server/forge/core/prompts.js +59 -0
  189. package/lib/server/forge/core/prompts.js.map +1 -1
  190. package/lib/server/forge/core/providers/azuredevops.d.ts +4 -2
  191. package/lib/server/forge/core/providers/azuredevops.d.ts.map +1 -1
  192. package/lib/server/forge/core/providers/azuredevops.js +12 -2
  193. package/lib/server/forge/core/providers/azuredevops.js.map +1 -1
  194. package/lib/server/forge/core/providers/base.d.ts +29 -4
  195. package/lib/server/forge/core/providers/base.d.ts.map +1 -1
  196. package/lib/server/forge/core/providers/base.js +21 -3
  197. package/lib/server/forge/core/providers/base.js.map +1 -1
  198. package/lib/server/forge/core/providers/github.d.ts +7 -7
  199. package/lib/server/forge/core/providers/github.d.ts.map +1 -1
  200. package/lib/server/forge/core/providers/github.js +13 -4
  201. package/lib/server/forge/core/providers/github.js.map +1 -1
  202. package/lib/server/forge/core/providers/gitlab.d.ts +20 -3
  203. package/lib/server/forge/core/providers/gitlab.d.ts.map +1 -1
  204. package/lib/server/forge/core/providers/gitlab.js +65 -5
  205. package/lib/server/forge/core/providers/gitlab.js.map +1 -1
  206. package/lib/server/forge/core/providers/types.d.ts +20 -0
  207. package/lib/server/forge/core/providers/types.d.ts.map +1 -1
  208. package/lib/server/forge/core/secretBox.d.ts +17 -0
  209. package/lib/server/forge/core/secretBox.d.ts.map +1 -0
  210. package/lib/server/forge/core/secretBox.js +74 -0
  211. package/lib/server/forge/core/secretBox.js.map +1 -0
  212. package/lib/server/forge/core/types.d.ts +8 -1
  213. package/lib/server/forge/core/types.d.ts.map +1 -1
  214. package/lib/server/forge/core/validator/clone.d.ts +5 -4
  215. package/lib/server/forge/core/validator/clone.d.ts.map +1 -1
  216. package/lib/server/forge/core/validator/clone.js +6 -86
  217. package/lib/server/forge/core/validator/clone.js.map +1 -1
  218. package/lib/server/forge/core/validator/cmd.d.ts.map +1 -1
  219. package/lib/server/forge/core/validator/cmd.js +4 -1
  220. package/lib/server/forge/core/validator/cmd.js.map +1 -1
  221. package/lib/server/forge/core/validator/projectType.d.ts.map +1 -1
  222. package/lib/server/forge/core/validator/projectType.js +2 -1
  223. package/lib/server/forge/core/validator/projectType.js.map +1 -1
  224. package/lib/server/forge/core/validator/runners/node.d.ts.map +1 -1
  225. package/lib/server/forge/core/validator/runners/node.js +6 -2
  226. package/lib/server/forge/core/validator/runners/node.js.map +1 -1
  227. package/lib/server/forge/core/validator.d.ts.map +1 -1
  228. package/lib/server/forge/core/validator.js +28 -22
  229. package/lib/server/forge/core/validator.js.map +1 -1
  230. package/lib/server/forge/core/workspaces.d.ts +70 -0
  231. package/lib/server/forge/core/workspaces.d.ts.map +1 -0
  232. package/lib/server/forge/core/workspaces.js +348 -0
  233. package/lib/server/forge/core/workspaces.js.map +1 -0
  234. package/lib/server/forge/db/database.d.ts +22 -0
  235. package/lib/server/forge/db/database.d.ts.map +1 -0
  236. package/lib/server/forge/db/database.js +71 -0
  237. package/lib/server/forge/db/database.js.map +1 -0
  238. package/lib/server/forge/db/migrations.d.ts +11 -0
  239. package/lib/server/forge/db/migrations.d.ts.map +1 -0
  240. package/lib/server/forge/db/migrations.js +87 -0
  241. package/lib/server/forge/db/migrations.js.map +1 -0
  242. package/lib/server/forge/routes.d.ts.map +1 -1
  243. package/lib/server/forge/routes.js +413 -163
  244. package/lib/server/forge/routes.js.map +1 -1
  245. package/lib/server/forge/sse.d.ts +10 -0
  246. package/lib/server/forge/sse.d.ts.map +1 -0
  247. package/lib/server/forge/sse.js +22 -0
  248. package/lib/server/forge/sse.js.map +1 -0
  249. package/lib/server/spa.d.ts +12 -0
  250. package/lib/server/spa.d.ts.map +1 -0
  251. package/lib/server/spa.js +23 -0
  252. package/lib/server/spa.js.map +1 -0
  253. package/lib/server.js +9 -24
  254. package/lib/server.js.map +1 -1
  255. package/lib/shared/events.d.ts +3 -0
  256. package/lib/shared/events.d.ts.map +1 -1
  257. package/lib/shared/events.js +3 -0
  258. package/lib/shared/events.js.map +1 -1
  259. package/lib/shared/packageRoot.d.ts +11 -0
  260. package/lib/shared/packageRoot.d.ts.map +1 -0
  261. package/lib/shared/packageRoot.js +23 -0
  262. package/lib/shared/packageRoot.js.map +1 -0
  263. package/lib/shared/project.d.ts +3 -0
  264. package/lib/shared/project.d.ts.map +1 -0
  265. package/lib/shared/project.js +3 -0
  266. package/lib/shared/project.js.map +1 -0
  267. package/package.json +24 -9
  268. package/lib/bin/cli/improve.d.ts +0 -2
  269. package/lib/bin/cli/improve.d.ts.map +0 -1
  270. package/lib/bin/cli/improve.js +0 -189
  271. package/lib/bin/cli/improve.js.map +0 -1
  272. package/lib/bin/cli/stats.d.ts +0 -2
  273. package/lib/bin/cli/stats.d.ts.map +0 -1
  274. package/lib/bin/cli/stats.js +0 -78
  275. package/lib/bin/cli/stats.js.map +0 -1
  276. package/lib/server/forge/core/k8s.d.ts +0 -18
  277. package/lib/server/forge/core/k8s.d.ts.map +0 -1
  278. package/lib/server/forge/core/k8s.js +0 -49
  279. package/lib/server/forge/core/k8s.js.map +0 -1
  280. package/lib/server/forge/core/openclawClient.d.ts +0 -61
  281. package/lib/server/forge/core/openclawClient.d.ts.map +0 -1
  282. package/lib/server/forge/core/openclawClient.js +0 -111
  283. package/lib/server/forge/core/openclawClient.js.map +0 -1
  284. package/lib/server/forge/core/quotaClient.d.ts +0 -48
  285. package/lib/server/forge/core/quotaClient.d.ts.map +0 -1
  286. package/lib/server/forge/core/quotaClient.js +0 -88
  287. package/lib/server/forge/core/quotaClient.js.map +0 -1
  288. package/lib/server/forge/core/selfImprove.d.ts +0 -43
  289. package/lib/server/forge/core/selfImprove.d.ts.map +0 -1
  290. package/lib/server/forge/core/selfImprove.js +0 -372
  291. package/lib/server/forge/core/selfImprove.js.map +0 -1
  292. package/lib/server/forge/core/telemetry.d.ts +0 -100
  293. package/lib/server/forge/core/telemetry.d.ts.map +0 -1
  294. package/lib/server/forge/core/telemetry.js +0 -273
  295. package/lib/server/forge/core/telemetry.js.map +0 -1
  296. package/scripts/fix-shebang.cjs +0 -11
  297. package/scripts/inject-readme.cjs +0 -23
  298. package/scripts/local-rollout.sh +0 -134
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ipul-labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -12,7 +12,7 @@ Built on: Claude Code CLI · GitLab / GitHub / Azure DevOps · Kubernetes
12
12
 
13
13
  Everything else fills in the gaps that matter for real teams:
14
14
 
15
- - **No per-token cost** — Claude runs via the `claude` CLI using your existing Claude subscription, not API credits. Heavy use doesn't trigger a bill.
15
+ - **No per-token cost** — Claude runs via the `claude` CLI using your existing Claude subscription, not API credits. Heavy use doesn't trigger a bill. Hosted workspaces can instead save their own Anthropic API key (see [Claude billing](#claude-billing)).
16
16
  - **Multi-provider** — GitLab, GitHub, and Azure DevOps are all first-class. Switch providers with a single env var; all normalized data shapes stay the same.
17
17
  - **Self-hosted** — your code never leaves your infrastructure. The backend runs wherever you deploy it; AI calls go to Anthropic (or a local gateway via OpenClaw).
18
18
  - **Two-pass analysis keeps context focused** — Claude first identifies the 6 most relevant files, then reads only those when proposing the fix. This produces sharper diffs than dumping the whole repo into one prompt.
@@ -21,8 +21,8 @@ Everything else fills in the gaps that matter for real teams:
21
21
 
22
22
  ## How it works
23
23
 
24
- 1. **Connect** — enter your Forge token to authenticate
25
- 2. **Pick an issue** — Forge loads open issues from your project
24
+ 1. **Sign in** — with your Forge account or your company SSO
25
+ 2. **Pick an issue** — Forge loads open issues from your project. Create, edit, label (`type::` / `priority::` / `status::` / `area::`) and delete tickets right from Forge. Close and delete (in the issue's ⋯ menu) open a dialog that first shows what will be torn down (Forge branches deleted, review environments stopped) and names any open MR that blocks it; deleting also asks you to type the issue number. The preview comes from `GET /issues/:iid/footprint`
26
26
  3. **Analyze** — Claude reads the repo file tree, identifies relevant files, and proposes a targeted fix
27
27
  4. **Review** — inspect the diff file-by-file; refine with natural-language feedback if needed
28
28
  5. **Apply** — Forge creates a branch, commits all changes, and opens a merge/pull request
@@ -34,57 +34,54 @@ Everything else fills in the gaps that matter for real teams:
34
34
 
35
35
  ### Prerequisites
36
36
 
37
- - Node.js 20+
37
+ - Node.js 22.13+
38
38
  - `claude` CLI installed and authenticated (`claude auth login`)
39
39
  - Credentials for your SCM provider (see [Configuration](#configuration))
40
40
 
41
41
  ### Install
42
42
 
43
+ Forge is published on npm as [`@ipul-labs/forge`](https://www.npmjs.com/package/@ipul-labs/forge). The package includes the server, the built dashboard and the `forge` CLI.
44
+
43
45
  ```bash
44
- git clone https://gitlab.com/ipul-labs/forge.git
45
- cd forge
46
- npm install
46
+ npm install -g @ipul-labs/forge
47
47
  ```
48
48
 
49
49
  ### Configure
50
50
 
51
+ Pick a folder for this install's settings and run the setup there. It writes `.env` in that folder and your repos and code-host token to `~/.forge/config.json`:
52
+
51
53
  ```bash
52
- # Interactive setup — writes .env and ~/.forge/config.json
53
- npx forge init
54
+ mkdir forge-home && cd forge-home
55
+ forge init
54
56
  ```
55
57
 
56
- Or copy the example env and fill in the values manually:
58
+ ### Launch the dashboard
59
+
60
+ From the same folder:
57
61
 
58
62
  ```bash
59
- cp .env.example .env
60
- # fill in FORGE_TOKEN plus your provider credentials
63
+ forge start # http://localhost:5001 (--port to change)
61
64
  ```
62
65
 
63
- ### Launch the UI
66
+ Open it and create the first admin account (see [First run](#first-run)). `forge doctor` checks the Claude CLI, your config and the build if anything looks off, and `forge update` installs the latest release.
64
67
 
65
- ```bash
66
- npm run dev
67
- # opens http://localhost:5000 (frontend) with API on :5001
68
- ```
68
+ Prefer not to install globally? `npx @ipul-labs/forge init` and `npx @ipul-labs/forge start` do the same.
69
+
70
+ ### Working on Forge itself
69
71
 
70
- For production:
72
+ From a checkout of the source:
71
73
 
72
74
  ```bash
73
- npm run build:app # builds Vite SPA to dist/
74
- npm start # NODE_ENV=production node server.js
75
+ npm install
76
+ npm run dev # http://localhost:5000 (frontend) with the API on :5001
77
+ npm run build && npm start # production build, served on :5001
75
78
  ```
76
79
 
77
- ### CLI usage
80
+ `npm run test:package` packs the repo exactly as npm would, installs the tarball into an empty folder, and runs the end-to-end checks against that install.
78
81
 
79
- The `forge` CLI drives the same orchestrator from the terminal. Install globally or use `npx`:
80
-
81
- ```bash
82
- # Global install (adds `forge` to PATH)
83
- npm install -g @ipul-labs/forge
82
+ ### CLI usage
84
83
 
85
- # Or run via npx from the repo
86
- npx forge <command>
87
- ```
84
+ The `forge` CLI drives the same orchestrator from the terminal. After the global install above it is on your PATH; otherwise prefix commands with `npx @ipul-labs/forge`.
88
85
 
89
86
  #### Interactive mode
90
87
 
@@ -130,8 +127,7 @@ forge merge # Merge the MR
130
127
  forge resolution-check # Verify merged MR closes the issue
131
128
  forge close # Close the issue
132
129
  forge use group/other-repo # Switch active repo
133
- forge update # Pull latest + reinstall dependencies
134
- forge stats # View telemetry — success rates, timing, failure patterns
130
+ forge update # Install the latest release (a source checkout pulls instead)
135
131
  forge improve # Evaluate patterns and suggest improvements
136
132
  forge improve --create # Create improvement issues in the repo
137
133
  ```
@@ -144,7 +140,7 @@ forge improve --create # Create improvement issues in the repo
144
140
  --secondary <repo> Additional repo (repeatable)
145
141
  --all-repos Include every configured repo
146
142
  --model <id> Claude model override
147
- --agent <name> Agent backend: claude | openclaw
143
+ --agent <name> Agent backend: claude
148
144
  --prompt <text> Extra user prompt
149
145
  --json JSON output
150
146
  --quiet Suppress progress
@@ -158,9 +154,12 @@ forge improve --create # Create improvement issues in the repo
158
154
  forge doctor # Check prerequisites (node, claude CLI, env vars)
159
155
  forge session list # List cached sessions
160
156
  forge session clean # Remove stale session data
157
+ forge reset-password <email> # Locked out? Set a new password on the Forge host
161
158
  ```
162
159
 
163
- See [`docs/cli.md`](./docs/cli.md) for the full command reference and [`docs/cli-ship-workflow.md`](./docs/cli-ship-workflow.md) for the workflow design.
160
+ `reset-password` writes straight to the Forge database (`FORGE_DB_PATH`, default `~/.forge/forge.db`), so it works without signing in and only for someone with shell access to the host. It asks for the new password twice without echoing it (or reads one line from piped stdin), signs the account out everywhere, and records `user.password_reset` in the audit log. SSO accounts are refused; their passwords live with the identity provider.
161
+
162
+ `forge help` lists every command and its options.
164
163
 
165
164
  ---
166
165
 
@@ -170,16 +169,35 @@ See [`docs/cli.md`](./docs/cli.md) for the full command reference and [`docs/cli
170
169
 
171
170
  | Variable | Required | Description |
172
171
  |---|---|---|
173
- | `FORGE_TOKEN` | Yes | Dashboard password — also auto-fills the UI login form |
172
+ | `FORGE_TOKEN` | — | Admin credential for automation; also accepted as the remote setup code. Never sent to the browser |
174
173
  | `FORGE_REPOS` | Yes | Comma-separated repo list; first entry is the primary project |
175
174
  | `SCM_PROVIDER` | — | `gitlab` (default) · `github` · `azuredevops` |
176
- | `ANTHROPIC_API_KEY` | — | Enables live model list from Anthropic; falls back to hardcoded list |
175
+ | `ANTHROPIC_API_KEY` | — | Enables live model list from Anthropic; falls back to hardcoded list. Never used to run Claude |
177
176
  | `FORGE_MODEL` | — | Override default model (default: `claude-sonnet-4-6`) |
178
- | `K8S_CLUSTER_TOKEN` | — | K8s service account token for rollout monitoring |
179
- | `K8S_CLUSTER_SERVER` | — | K8s API server URL |
177
+ | `FORGE_AGENT_MODE` | — | `structured` (default) · `agentic` — how Claude proposes changes (see [Agent modes](#agent-modes)) |
180
178
  | `PORT` | — | HTTP server port (default: `5001`) |
181
- | `OPENCLAW_GATEWAY_URL` | — | Enables OpenClaw agent backend; point at your local Gateway |
182
- | `OPENCLAW_TOKEN` | — | Bearer token for OpenClaw Gateway auth |
179
+
180
+ ### Identity and storage
181
+
182
+ | Variable | Required | Description |
183
+ |---|---|---|
184
+ | `FORGE_DB_PATH` | — | SQLite database for members, sessions, API tokens and the audit log (default `~/.forge/forge.db`) |
185
+ | `FORGE_ENCRYPTION_KEY` | — | Base64 32-byte key used to encrypt SCM tokens at rest. Without it Forge generates `~/.forge/master.key` (`FORGE_KEY_PATH`) |
186
+ | `FORGE_OIDC_ISSUER` | — | OIDC issuer URL (Okta, Entra ID, Google Workspace, GitLab, …). Enables "Continue with SSO" |
187
+ | `FORGE_OIDC_CLIENT_ID` / `FORGE_OIDC_CLIENT_SECRET` | — | OIDC client credentials |
188
+ | `FORGE_PUBLIC_URL` | — | External URL; the OIDC redirect is `${FORGE_PUBLIC_URL}/api/forge/auth/oidc/callback` unless `FORGE_OIDC_REDIRECT_URI` is set |
189
+ | `FORGE_OIDC_NAME` | — | Label on the sign-in button (default `SSO`) |
190
+ | `FORGE_OIDC_ALLOWED_DOMAINS` | — | Comma-separated email domains allowed to sign in with SSO |
191
+ | `FORGE_OIDC_DEFAULT_ROLE` | — | Role given to new SSO members (default `viewer`) |
192
+ | `FORGE_TRUST_PROXY` | — | Express `trust proxy` setting when behind a load balancer |
193
+ | `FORGE_COOKIE_SECURE` | — | Override Secure cookies (on by default in production) |
194
+ | `FORGE_DISABLE_SERVICE_TOKEN` | — | `1` stops `FORGE_TOKEN` working as an API credential once setup is done |
195
+
196
+ ### Claude billing
197
+
198
+ By default the `claude` CLI runs on the Claude Code subscription it is logged in with, and Forge strips `ANTHROPIC_API_KEY` from its environment so an env key can't quietly switch it to API credits.
199
+
200
+ An admin can save a workspace **Anthropic API key** in Settings → Connections. Claude then runs on that account's API credits instead. This is the mode for a hosted Forge serving other teams, since a personal subscription is only for its owner's own use. The key is encrypted at rest like SCM tokens, shown back only as a hint, and clearing it returns Claude to the subscription.
183
201
 
184
202
  ### Provider credentials
185
203
 
@@ -215,7 +233,6 @@ SCM tokens can be set here **or** in the Forge Settings UI (Settings → Connect
215
233
  | Variable | Replaced by |
216
234
  |---|---|
217
235
  | `FORGE_GITLAB_PROJECT` | First entry in `FORGE_REPOS` |
218
- | `VITE_FORGE_TOKEN` | Auto-derived from `FORGE_TOKEN` |
219
236
  | `FORGE_REFINE_REPO_ACCESS` | Settings UI toggle (Settings → Defaults) |
220
237
 
221
238
  See `.env.example` for a full annotated list.
@@ -250,33 +267,14 @@ FORGE_REPOS=gitlab:ipul/web-app,github:my-org/mobile
250
267
  | Multi-file commits | Yes | Yes (Git Data API) | Yes (Pushes API) |
251
268
  | Merge / Pull Requests | Yes | Yes | Yes |
252
269
  | CI pipelines | Yes (GitLab CI) | Yes (GitHub Actions) | Yes (Azure Pipelines) |
270
+ | Pipeline history page | Yes | — | — |
253
271
  | Job log traces | Yes | Yes | Yes |
254
272
  | Server-side rebase | Yes | — | — |
273
+ | Ticket labels | Yes | Yes | Yes (Tags) |
274
+ | Delete tickets | Yes (project Owner) | — (close instead) | Yes (recycle bin) |
275
+ | Review env link on MRs | Yes (environment deployed by the MR pipeline) | — | — |
255
276
 
256
- ---
257
-
258
- ## Self-improvement
259
-
260
- Forge monitors its own performance and proposes fixes autonomously. The loop:
261
-
262
- 1. **Telemetry** — every operation records success/fail, duration, tokens, and cost to `~/.forge/telemetry/`
263
- 2. **Pattern detection** — recurring failures are grouped and classified (timeout-tuning, provider-bug, prompt-quality, validation-gap, error-handling, ux-improvement)
264
- 3. **Auto-evaluation** — runs automatically after every 25 operations (4-hour cooldown). High-severity patterns trigger issue creation.
265
- 4. **Issue creation** — files issues in the configured repo with diagnosis, evidence, and suggested fixes. Tagged `[self-improve]` with category labels.
266
- 5. **Human review** — Forge never auto-merges its own changes. All improvements go through normal MR review.
267
- 6. **Resolution** — when a self-improve issue is closed, matching telemetry failure patterns are marked as resolved. They stop appearing in `forge stats` and won't trigger duplicate diagnoses. Resolution is tied to code state, not time — patterns only clear when the fix ships.
268
-
269
- ```bash
270
- forge stats # View telemetry data
271
- forge improve # Run evaluation manually
272
- forge improve --create # Create issues for actionable patterns
273
- forge improve --ship # Create issues + analyze + propose fix + open MR
274
- forge improve --json # Pipe-friendly output
275
- ```
276
-
277
- The `--ship` flag runs the full loop: detect pattern → create issue → analyze → propose fix → open MR. All in one command. The MR goes through normal CI — you review and merge or reject.
278
-
279
- UX insights are also derived from telemetry: slow operations (>2 min avg), high token usage (>50k avg), and frequent cancellations surface as improvement suggestions.
277
+ On GitLab, the MR tab shows a **Review env ↗** link when the MR's pipeline has deployed a live environment with an external URL (e.g. a `review/mr-<iid>` job with `environment:url`). No config needed; MRs without one show nothing.
280
278
 
281
279
  ---
282
280
 
@@ -284,8 +282,13 @@ UX insights are also derived from telemetry: slow operations (>2 min avg), high
284
282
 
285
283
  Forge is designed for self-hosted deployment on trusted infrastructure. Security measures in place:
286
284
 
287
- - **Timing-safe auth** — token comparison uses `crypto.timingSafeEqual` to prevent timing attacks
288
- - **Rate limiting** — API endpoints are rate-limited (60 req/min per IP) to prevent brute-force
285
+ - **Member accounts** — each person signs in with a password (scrypt) or SSO (OIDC with PKCE). Sessions are httpOnly, SameSite cookies stored server-side as hashes, with a 12-hour idle and 7-day absolute limit. No credential ever reaches browser JavaScript or the client bundle
286
+ - **Roles** — viewer, operator, approver and admin, enforced on every API route. Merging needs approver; connections, repos and members need admin
287
+ - **Audit log** — every sign-in and every change is recorded with who, what, where and the outcome. It is append-only and visible to admins under Audit log
288
+ - **Encryption at rest** — SCM tokens in `~/.forge/config.json` are sealed with AES-256-GCM
289
+ - **CSRF protection** — cookie-authenticated writes require a custom request header
290
+ - **Brute-force protection** — accounts lock for 15 minutes after 5 failed sign-ins, and sign-in endpoints are rate-limited per IP. API calls are rate-limited per member
291
+ - **API tokens** — personal tokens for the CLI and automation, shown once, stored hashed and revocable
289
292
  - **Security headers** — Helmet middleware sets X-Frame-Options, HSTS, X-Content-Type-Options, and CSP (production)
290
293
  - **Request size limits** — JSON body capped at 1MB to prevent memory exhaustion
291
294
  - **Secret redaction** — error logs and API responses scrub tokens (`glpat-*`, `ghp_*`, `oauth2:*@`) before output
@@ -295,22 +298,41 @@ Forge is designed for self-hosted deployment on trusted infrastructure. Security
295
298
  - **No shell injection** — all subprocess calls use `spawn()` with argument arrays, never shell strings
296
299
  - **Atomic config writes** — config updates use temp file + rename to prevent corruption
297
300
 
298
- `FORGE_TOKEN` is a standalone dashboard password — never reuse an SCM token for this value.
301
+ `FORGE_TOKEN`, when set, is an admin credential for automation. Use a long random value, never reuse an SCM token, and set `FORGE_DISABLE_SERVICE_TOKEN=1` once your team uses personal API tokens.
302
+
303
+ ### First run
304
+
305
+ Open Forge and create the first admin account. On the server machine itself (`localhost`) that is all it takes. From anywhere else the form asks for a setup code, which Forge prints to its log on first start (or your `FORGE_TOKEN`, if set), so nobody can claim a fresh install that is reachable on the network. Add the rest of your team under **Members**, or turn on SSO with the `FORGE_OIDC_*` variables.
306
+
307
+ The `forge` CLI authenticates with a personal API token: create one under **Settings → API tokens** and export it as `FORGE_API_TOKEN`.
299
308
 
300
309
  ---
301
310
 
302
311
  ## Production deployment
303
312
 
313
+ On a server, install from npm and run `forge start` as a service (systemd, pm2 or similar) from the folder holding your `.env`. Put it behind your HTTPS reverse proxy and set `FORGE_PUBLIC_URL` to the address people use.
314
+
315
+ From a source checkout:
316
+
304
317
  ```bash
305
- npm run build:app # builds Vite SPA to dist/
318
+ npm run build # builds the SPA to dist/
306
319
  NODE_ENV=production tsx server.ts
307
320
  ```
308
321
 
309
- Or with Docker:
322
+ Or with Docker, from a checkout:
310
323
 
311
324
  ```bash
312
325
  docker build -t forge .
313
- docker run -p 5001:5001 --env-file .env forge
326
+ docker run -p 5001:5001 --env-file .env -v forge-data:/data forge
327
+ ```
328
+
329
+ ### Kubernetes
330
+
331
+ `manifests/forge/` holds an example Deployment, Service, ConfigMap and Secret template. Build and push the Docker image to your own registry, set `image` in `deployment.yaml`, create the secret, then:
332
+
333
+ ```bash
334
+ kubectl create namespace forge
335
+ kubectl apply -n forge -f manifests/forge/
314
336
  ```
315
337
 
316
338
  ---
@@ -339,9 +361,7 @@ server/
339
361
  core/
340
362
  ForgeAgent.ts # Orchestrates the full pipeline (analyze -> apply -> refine)
341
363
  claudeClient.ts # Shells out to the claude CLI for structured output
342
- openclawClient.ts # OpenClaw Gateway HTTP client
343
- agentClient.ts # Dispatcher: routes to claudeClient or openclawClient
344
- k8s.ts # Kubernetes client for rollout monitoring
364
+ agentClient.ts # Thin wrapper over claudeClient
345
365
  jobs.ts # Job store with SSE event buffering + replay
346
366
  providers/
347
367
  base.ts # Abstract ScmProvider — normalized shapes + interface
@@ -353,16 +373,67 @@ server/
353
373
  src/
354
374
  views/Forge/
355
375
  ForgeDashboard.tsx # Root UI component with tabbed issue/MR views
356
- api.ts # Token management + fetch helper
376
+ api.ts # Session-aware fetch helper (cookie + CSRF header)
357
377
  types.ts # Shared TypeScript types
358
378
  utils.ts # SSE helper + state utilities
359
- components/ # Analysis progress, pipeline status, diff viewer
379
+ ui.ts # Shared responsive class tokens (touch-sized actions)
380
+ components/ # Analysis progress, pipeline status, diff viewer, Sheet, Switch
381
+ shell/ # App chrome: sidebar (drawer on phones), top bar, command palette, phone tab bar
382
+ useNav.ts # Single nav definition shared by sidebar, tab bar and command palette
360
383
  hooks/
361
384
  useForgeDashboard.ts # All state, phase transitions, and API calls
362
385
  useForgeEvents.ts # SSE event bus subscription
363
386
  ```
364
387
 
365
- ### Two-pass analysis
388
+ ### Mobile layout
389
+
390
+ Below Tailwind's `md` breakpoint (768px) the dashboard adds iOS-style touches on top of the responsive shell: a bottom tab bar (Issues · Merge requests · Pipelines · Settings) on list pages, a New task button in the top bar, New Task as a bottom sheet, iOS switches, full-width 50pt primary actions, and 16px form fields so Safari doesn't zoom. The sidebar (repo picker, usage, theme, admin pages, sign-out) opens as a drawer from the top bar. It respects safe-area insets and uses `100dvh`, so it works as a home-screen web app on iPhone. Desktop layout is unchanged.
391
+
392
+ ### Install as an app (PWA)
393
+
394
+ Forge ships a web app manifest (`public/manifest.webmanifest`) and icons, so it can be installed. On iPhone open it in Safari → Share → **Add to Home Screen**; on Android/Chrome use **Install app**. It opens standalone at `/issues`. The icon source is `public/icon.svg`; regenerate the PNGs after changing it:
395
+
396
+ ```bash
397
+ for s in 180 192 512; do magick -background none -density 384 public/icon.svg -resize ${s}x${s} -strip PNG32:public/icon-$s.png; done
398
+ mv public/icon-180.png public/apple-touch-icon.png
399
+ ```
400
+
401
+ If the app bundle fails to load or throws before React mounts, `public/boot-check.js` reloads once (a stale bundle after a deploy) and then shows the error with the browser's user agent and a Reload button instead of a blank screen. In production a missing file under `/assets/` returns 404 rather than `index.html`, so a stale bundle fails visibly.
402
+
403
+ ### Agent modes
404
+
405
+ Forge can drive Claude in two ways, set by `FORGE_AGENT_MODE` (or the Settings default, or a per-request `agentMode`):
406
+
407
+ - **`structured`** (default) — the two-pass JSON pipeline below. Deterministic and schema-validated: Claude runs single-turn with tools disabled and returns complete file contents that Forge overlays onto a clone.
408
+ - **`agentic`** — Claude runs as a full Claude Code agent inside a checkout of the repo: real tools (Read/Edit/Write/Bash…), the project's own `CLAUDE.md`, and a multi-turn loop. Forge captures the resulting `git diff` instead of parsing JSON, then feeds those changes into the same apply/validate/MR pipeline. The capture never includes symlinks or dependency folders (`node_modules`, `bower_components`, `jspm_packages`, `.venv`, `__pycache__`), whatever the repo's `.gitignore` says; anything left out is noted in the run log. Higher fidelity, less determinism. Requires the `claude` backend, a single repo, and a GitLab primary — otherwise Forge logs why and falls back to structured. Pick the mode under **Settings → Defaults → Agent mode**.
409
+
410
+ Refine follows the mode too. In agentic mode a follow-up ("open it in Playwright and check it", "rename the prop") runs as the same full agent in the issue's worktree with the current proposal already applied, so it can run tests and browsers, gather evidence and edit. If it changes nothing and gathers no evidence, its reply comes back as an answer and the proposal is left as it was. In structured mode, refine only gets read-only repo access (Read/Glob/Grep), so it can't run anything. CI-fix refines always use the structured fix.
411
+
412
+ ### Rules and evidence
413
+
414
+ **Settings → Defaults → Prompt rules** is free text added to every analysis and refine prompt as "Custom rules — always follow these", in both modes. In agentic mode the target repo's `CLAUDE.md` applies as well, so repo conventions belong there and Forge-wide instructions belong in the rules.
415
+
416
+ In agentic mode a rule can also ask for proof, e.g. *"Run the e2e tests and screenshot every page you changed, at desktop and phone width."* Forge doesn't capture anything itself: the agent installs and runs what it needs (Playwright and its browsers included) and leaves the results in `.forge-evidence/` at the checkout root:
417
+
418
+ - `.forge-evidence/EVIDENCE.md` — what it ran and what it saw; images are linked by file name (`![home](home.png)`)
419
+ - PNG/JPEG/GIF/WebP screenshots next to it (nested folders are fine; up to 10 images, 10 MB each)
420
+
421
+ After the run Forge uploads the images to the GitLab project, points the write-up's links at the uploads (appending any image it didn't mention), and puts the result in the MR's **🧪 Testing** section. The folder is cleared before each run and listed in the clone's `.git/info/exclude`, so it is never committed. A failed upload is logged in the activity feed and doesn't fail the analysis. The agent's run is bounded by `cliTimeout` (10 minutes by default), so a full browser install plus a long suite may need more.
422
+
423
+ ### Workspaces
424
+
425
+ Every local checkout Forge works in lives under `~/.forge/cache` (or `FORGE_VALIDATE_CACHE`):
426
+
427
+ ```
428
+ repos/<repo>/ shallow base clone, one per repo
429
+ worktrees/<repo>/issue-<iid>/ git worktree per issue, on its forge/issue-… branch
430
+ ```
431
+
432
+ Agentic runs, refine (with repo access) and validation each lease the issue's worktree, reset it to the remote HEAD, and release it when done. Different issues never share a tree, and git work on one repo (fetch, worktree add/remove) is serialised. Ignored files such as `node_modules` survive between runs of the same issue.
433
+
434
+ **Settings → Workspaces** (admins) lists every base clone and worktree with its size, last use and whether a running job holds it, plus anything Forge doesn't own any more: clones from the old one-clone-per-repo layout ("Old-layout clone") and worktree folders git no longer knows about ("Stray folder"). You can delete one, or **Purge idle** to remove everything not in use; tick *Include base clones* to drop base clones that have no worktrees left too. A deleted workspace is simply re-created by the next job that needs it. The same actions are available as `GET /workspaces`, `DELETE /workspaces?id=<id>` and `POST /workspaces/purge` (`{"includeBases": true}`); a workspace in use answers 409.
435
+
436
+ ### Two-pass analysis (structured mode)
366
437
 
367
438
  **Pass 1** — `identifyRelevantFiles`: Claude reads the issue + file tree, returns the max-6 most relevant paths.
368
439
 
@@ -388,11 +459,13 @@ All three SCM providers implement `ScmProvider` from `providers/base.ts`. The co
388
459
  The npm package ships compiled JavaScript with TypeScript declarations — no `tsx` or TypeScript runtime needed by consumers.
389
460
 
390
461
  ```ts
391
- import forgeRouter from "@ipul-labs/forge"; // Express router
462
+ import { createApi } from "@ipul-labs/forge/app"; // Express app with auth + API
392
463
  import { ForgeAgent } from "@ipul-labs/forge/agent"; // Core pipeline class
393
464
  import { createProvider } from "@ipul-labs/forge/providers"; // SCM factory
394
465
  ```
395
466
 
467
+ The bare router (`@ipul-labs/forge`) expects the auth stack in front of it and rejects requests without a signed-in principal. Mount `createApi({ db, env: process.env, isProd })` instead, with `db` from `openDatabase`.
468
+
396
469
  ```ts
397
470
  const agent = new ForgeAgent({ project: "group/repo" });
398
471
  const result = await agent.analyzeIssue(42, (event) => console.log(event));
@@ -411,6 +484,16 @@ npm run typecheck # check both frontend + server configs
411
484
 
412
485
  ---
413
486
 
487
+ ## Contributing
488
+
489
+ The source repository is private for now. Send bug reports, ideas and security problems to support@ipullabs.com; please report security problems privately rather than in public.
490
+
491
+ ## Support
492
+
493
+ Questions or problems with Forge: support@ipullabs.com
494
+
495
+ ---
496
+
414
497
  ## License
415
498
 
416
- MIT
499
+ MIT. Forge is free to use, change and share, for personal or commercial work. The full license text is in the `LICENSE` file that ships with the package.
Binary file