forgeo-cli 0.6.0__tar.gz → 0.7.1__tar.gz

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 (80) hide show
  1. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/CHANGELOG.md +41 -1
  2. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/PKG-INFO +79 -32
  3. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/README.md +78 -31
  4. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/docs/agent-contract.md +24 -11
  5. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/docs/backlog.md +6 -6
  6. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/docs/cli-reference.md +61 -36
  7. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/docs/configuration.md +54 -34
  8. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/docs/getting-started.md +10 -0
  9. forgeo_cli-0.7.1/docs/img/demo.gif +0 -0
  10. forgeo_cli-0.7.1/docs/img/og.png +0 -0
  11. forgeo_cli-0.7.1/docs/index.md +67 -0
  12. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/docs/web-console-api.md +6 -5
  13. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/install.sh +1 -1
  14. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/pyproject.toml +1 -1
  15. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/__init__.py +1 -1
  16. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/agent.py +8 -3
  17. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/backlog.py +6 -10
  18. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/central.py +92 -97
  19. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/cli.py +123 -55
  20. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/config.py +3 -1
  21. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/daemon.py +2 -3
  22. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/daemon_control.py +79 -43
  23. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/forgeo.py +132 -30
  24. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/models.py +14 -1
  25. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/notify.py +29 -22
  26. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/runs.py +31 -12
  27. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/setup.py +4 -1
  28. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/update.py +1 -7
  29. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/validate.py +21 -0
  30. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/web/central/central.js +1 -0
  31. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/conftest.py +15 -0
  32. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_agent.py +16 -0
  33. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_backlog.py +0 -54
  34. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_cli.py +187 -4
  35. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_factory.py +136 -0
  36. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_install.py +1 -1
  37. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_models.py +17 -0
  38. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_update.py +0 -5
  39. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_web.py +5 -1
  40. forgeo_cli-0.6.0/docs/index.md +0 -130
  41. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/.github/workflows/ci.yml +0 -0
  42. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/.gitignore +0 -0
  43. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/CONTRIBUTING.md +0 -0
  44. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/LICENSE +0 -0
  45. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/config/nginx-forgeo.conf +0 -0
  46. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/docs/img/console.png +0 -0
  47. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/docs/img/logo.png +0 -0
  48. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/docs/img/title.svg +0 -0
  49. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/forgeo.spec +0 -0
  50. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/mkdocs.yml +0 -0
  51. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/scripts/__init__.py +0 -0
  52. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/scripts/render_homebrew_formula.py +0 -0
  53. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/__main__.py +0 -0
  54. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/backlog_http.py +0 -0
  55. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/git.py +0 -0
  56. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/instances.py +0 -0
  57. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/io.py +0 -0
  58. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/oauth.py +0 -0
  59. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/paths.py +0 -0
  60. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/web/central/central.css +0 -0
  61. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/web/central/index.html +0 -0
  62. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/web/central/instance.html +0 -0
  63. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/web/central/login.html +0 -0
  64. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/web/style.css +0 -0
  65. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/src/forgeo/web_common.py +0 -0
  66. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_backlog_http.py +0 -0
  67. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_daemon.py +0 -0
  68. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_git.py +0 -0
  69. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_instances.py +0 -0
  70. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_io.py +0 -0
  71. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_oauth.py +0 -0
  72. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_paths.py +0 -0
  73. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_remote_backlog_cycle.py +0 -0
  74. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_render_homebrew.py +0 -0
  75. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_runs.py +0 -0
  76. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_setup.py +0 -0
  77. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_web_common.py +0 -0
  78. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/tests/test_web_lock.py +0 -0
  79. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/www/404.html +0 -0
  80. {forgeo_cli-0.6.0 → forgeo_cli-0.7.1}/www/index.html +0 -0
@@ -7,6 +7,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.1] - 2026-08-17
11
+
12
+ ### Added
13
+
14
+ - An animated demo GIF in the README, showing Forgeo running a backlog task
15
+ end to end, plus an Open Graph social-preview image for the docs site.
16
+
17
+ ### Changed
18
+
19
+ - The default agent prompt (used by `forgeo init`) now names `AGENTS.md` and
20
+ `CONTEXT.md` explicitly when telling the agent to keep project overview and
21
+ conventions up to date.
22
+
23
+ ## [0.7.0] - 2026-08-16
24
+
25
+ ### Added
26
+
27
+ - `task_context` config key: a path to a file (e.g. `CONTEXT.md`) whose
28
+ contents are prepended to every agent instruction — tasks and refactoring
29
+ runs alike — before the task description. The agent gets the high-level
30
+ project overview instead of only the isolated task; the file is re-read on
31
+ every run, so the agent's own updates are picked up on the next cycle. A
32
+ missing or unreadable file never fails a cycle: it is logged, `forgeo
33
+ validate` reports it as a warning, and the run proceeds with the bare
34
+ instruction.
35
+ - The default agent prompt (used by `forgeo init`) now tells the agent to
36
+ read `AGENTS.md` (and `CONTEXT.md` if present) at the start of the session
37
+ and to keep them updated when a change materially affects the project
38
+ overview.
39
+
40
+ - `forgeo run --task <id>` runs exactly one specific `OPEN` task by id and
41
+ exits, instead of letting `forgeo once` pick the oldest one — for triage:
42
+ rerun a `FAILED` task (after reopening it) or try a risky task now. It
43
+ shares the same per-forgeo lock as the daemon and `forgeo once`, so it
44
+ never overlaps them; it refuses with a clear error when the task does not
45
+ exist or is not `OPEN`, and while another daemon/`once`/`run` holds the
46
+ lock.
47
+
10
48
  ## [0.6.0] - 2026-08-14
11
49
 
12
50
  ### Added
@@ -283,7 +321,9 @@ Initial release of the scheduled, agent-driven software forgeo.
283
321
  overlapping-run skipping.
284
322
  - Dogfooding docs removed; local configs kept out of the repository.
285
323
 
286
- [Unreleased]: https://github.com/lucaGazzola/forgeo/compare/v0.6.0...HEAD
324
+ [Unreleased]: https://github.com/lucaGazzola/forgeo/compare/v0.7.1...HEAD
325
+ [0.7.1]: https://github.com/lucaGazzola/forgeo/compare/v0.7.0...v0.7.1
326
+ [0.7.0]: https://github.com/lucaGazzola/forgeo/compare/v0.6.0...v0.7.0
287
327
  [0.6.0]: https://github.com/lucaGazzola/forgeo/compare/v0.5.0...v0.6.0
288
328
  [0.5.0]: https://github.com/lucaGazzola/forgeo/compare/v0.4.0...v0.5.0
289
329
  [0.4.0]: https://github.com/lucaGazzola/forgeo/compare/v0.3.0...v0.4.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: forgeo-cli
3
- Version: 0.6.0
3
+ Version: 0.7.1
4
4
  Summary: A scheduled software forgeo: executes backlog tasks on main, refactors when idle, and writes BLOCKER.md when it needs human input.
5
5
  Project-URL: Homepage, https://forgeo.org
6
6
  Project-URL: Documentation, https://forgeo.org
@@ -64,6 +64,10 @@ Description-Content-Type: text/markdown
64
64
  [![CI](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml/badge.svg)](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
65
65
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
66
66
 
67
+ <div align="center">
68
+ <img src="docs/img/demo.gif" alt="Forgeo running a backlog task end to end" width="720">
69
+ </div>
70
+
67
71
  **Forgeo is a software factory for your coding-agent.**
68
72
  You're already working with an AI coding agent, prompting it task by task
69
73
  or giving it a goal. Forgeo organizes your work in a structured way with
@@ -83,50 +87,93 @@ agent CLI.
83
87
 
84
88
  The full walkthrough is in [Getting started](docs/getting-started.md).
85
89
 
86
- ```bash
87
- # 1. Install (any one of these)
90
+ ### 1. Install the CLI
88
91
 
89
- # Homebrew (macOS / Linux)
92
+ Pick any one installer (no root needed; re-running it upgrades Forgeo).
93
+
94
+ ```bash
95
+ # Homebrew (macOS / Linux): prebuilt binary, no Python required
90
96
  brew install lucaGazzola/forgeo/forgeo
91
97
 
92
- # or: the one-liner (prebuilt binary, no Python required)
98
+ # One-liner (Linux / macOS / Windows): prebuilt binary, falls back to pip
93
99
  curl -fsSL https://forgeo.org/install.sh | bash
94
100
 
95
- # or: pipx
101
+ # pip (Python 3.11+)
96
102
  pipx install forgeo-cli
103
+ ```
97
104
 
98
- # 2. Create your Forgeo (guided wizard, run from your project root)
99
- forgeo init
105
+ ### 2. Create your Forgeo
100
106
 
101
- # 3. Start Forgeo (detached in the background; exits immediately)
102
- forgeo start # every interval_minutes, implement the oldest OPEN task (dependencies first)
103
- forgeo stop # stop the daemon again
107
+ ```bash
108
+ forgeo init
104
109
  ```
105
110
 
106
- `forgeo init` writes `forgeo.yaml` and a `.forgeo/` folder for the backlog
107
- and logs. Fill the backlog with plain JSON tasks (see
108
- [Backlog format](docs/backlog.md)) or add them from the web console while
109
- it runs, Forgeo does the rest. Open the dashboard with `forgeo web` (default <http://0.0.0.0:8790>), or keep it always-on with `forgeo web -d` (stop it with `forgeo web stop`, check it with `forgeo web status`):
111
+ Guided wizard, run from your project root. Writes `forgeo.yaml` (the
112
+ config) and a `.forgeo/` folder for the backlog, logs and blocker files.
113
+
114
+ The base flow is then three steps: fill the backlog, check the
115
+ configuration, start the daemon.
116
+
117
+ ### 3. Fill the backlog
118
+
119
+ ```bash
120
+ # Either: edit the backlog file by hand — a plain JSON task list (see
121
+ # Backlog format), created on first use:
122
+ # .forgeo/backlog.json
123
+
124
+ # Or: add tasks from the web console once your forgeo is registered
125
+ # (first `forgeo start` registers it automatically):
126
+ forgeo web # dashboard at http://0.0.0.0:8790, or keep it on with `forgeo web -d`
127
+ ```
110
128
 
111
129
  ![Forgeo web console](docs/img/console.png)
112
130
 
113
- By default the dashboard is open to anyone who can reach the port. On a
114
- shared host, protect it with bearer-token auth: `forgeo web --token`
115
- generates a token (printed once, saved to `~/.config/forgeo/web.toml`) and
116
- requires `Authorization: Bearer <token>` on every `/api/*` route — see
117
- [Web console & HTTP API](docs/web-console-api.md).
118
-
119
- One-off commands: `forgeo once` (single cycle), `forgeo status` (summary),
120
- `forgeo validate` (read-only dry run before starting), `forgeo stop`,
121
- `forgeo restart`, every command is in the
122
- [CLI reference](docs/cli-reference.md).
123
-
124
- You can run several factories at once, one per repository, each config is
125
- fully independent (own backlog, logs, locks). Register each `forgeo.yaml`
126
- in the instance registry with `forgeo instance add NAME --config PATH`,
127
- manage any of them by name with `forgeo start/status/stop --name NAME`,
128
- list them all with `forgeo list`, and get one aggregate overview with the
129
- central dashboard, `forgeo web`.
131
+ ### 4. Check the configuration
132
+
133
+ ```bash
134
+ forgeo validate
135
+ ```
136
+
137
+ Read-only dry run before the first start: verifies `forgeo.yaml`, the git
138
+ repo, branch and remote, that the backlog parses (fetching it once when it
139
+ is an HTTP endpoint), the agent command, and the lock state. Never invokes
140
+ the agent and writes nothing.
141
+
142
+ ### 5. Start the daemon
143
+
144
+ ```bash
145
+ forgeo start
146
+ ```
147
+
148
+ Starts the daemon **detached in the background** and exits. Every
149
+ `interval_minutes` it runs one cycle: pick the oldest `OPEN` task whose
150
+ dependencies are all `COMPLETED`, run your coding agent on it, commit the
151
+ result. When the backlog is empty, the same agent runs a refactoring pass
152
+ over the codebase instead.
153
+
154
+ ### Day-to-day commands
155
+
156
+ ```bash
157
+ forgeo status # Config, backlog counts, next runnable task, daemon running?, last outcome
158
+ forgeo once # Run exactly one cycle in the foreground, no daemon left behind
159
+ forgeo run --task SELF-012 # Run one specific OPEN task now (triage)
160
+ forgeo stop # Stop the background daemon
161
+ forgeo restart # Stop and start again (re-reads forgeo.yaml after edits)
162
+ forgeo web # Dashboard: every instance's backlog, run history and logs
163
+ ```
164
+
165
+ `forgeo web` defaults to an open dashboard on `http://0.0.0.0:8790`; on a
166
+ shared host protect it with `forgeo web --token` (requires
167
+ `Authorization: Bearer <token>` on every `/api/*` route — see
168
+ [Web console & HTTP API](docs/web-console-api.md)).
169
+
170
+ ### Multiple repositories (instances)
171
+
172
+ Run several factories at once, one per repository; each config is fully
173
+ independent (own backlog, logs, locks). Register each `forgeo.yaml` with
174
+ `forgeo instance add NAME --config PATH`, manage any of them by name with
175
+ `forgeo start/status/stop --name NAME`, list them all with `forgeo list`,
176
+ and get one aggregate overview with the central dashboard, `forgeo web`.
130
177
 
131
178
  ## Documentation
132
179
 
@@ -10,6 +10,10 @@
10
10
  [![CI](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml/badge.svg)](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
11
11
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
12
12
 
13
+ <div align="center">
14
+ <img src="docs/img/demo.gif" alt="Forgeo running a backlog task end to end" width="720">
15
+ </div>
16
+
13
17
  **Forgeo is a software factory for your coding-agent.**
14
18
  You're already working with an AI coding agent, prompting it task by task
15
19
  or giving it a goal. Forgeo organizes your work in a structured way with
@@ -29,50 +33,93 @@ agent CLI.
29
33
 
30
34
  The full walkthrough is in [Getting started](docs/getting-started.md).
31
35
 
32
- ```bash
33
- # 1. Install (any one of these)
36
+ ### 1. Install the CLI
34
37
 
35
- # Homebrew (macOS / Linux)
38
+ Pick any one installer (no root needed; re-running it upgrades Forgeo).
39
+
40
+ ```bash
41
+ # Homebrew (macOS / Linux): prebuilt binary, no Python required
36
42
  brew install lucaGazzola/forgeo/forgeo
37
43
 
38
- # or: the one-liner (prebuilt binary, no Python required)
44
+ # One-liner (Linux / macOS / Windows): prebuilt binary, falls back to pip
39
45
  curl -fsSL https://forgeo.org/install.sh | bash
40
46
 
41
- # or: pipx
47
+ # pip (Python 3.11+)
42
48
  pipx install forgeo-cli
49
+ ```
43
50
 
44
- # 2. Create your Forgeo (guided wizard, run from your project root)
45
- forgeo init
51
+ ### 2. Create your Forgeo
46
52
 
47
- # 3. Start Forgeo (detached in the background; exits immediately)
48
- forgeo start # every interval_minutes, implement the oldest OPEN task (dependencies first)
49
- forgeo stop # stop the daemon again
53
+ ```bash
54
+ forgeo init
50
55
  ```
51
56
 
52
- `forgeo init` writes `forgeo.yaml` and a `.forgeo/` folder for the backlog
53
- and logs. Fill the backlog with plain JSON tasks (see
54
- [Backlog format](docs/backlog.md)) or add them from the web console while
55
- it runs, Forgeo does the rest. Open the dashboard with `forgeo web` (default <http://0.0.0.0:8790>), or keep it always-on with `forgeo web -d` (stop it with `forgeo web stop`, check it with `forgeo web status`):
57
+ Guided wizard, run from your project root. Writes `forgeo.yaml` (the
58
+ config) and a `.forgeo/` folder for the backlog, logs and blocker files.
59
+
60
+ The base flow is then three steps: fill the backlog, check the
61
+ configuration, start the daemon.
62
+
63
+ ### 3. Fill the backlog
64
+
65
+ ```bash
66
+ # Either: edit the backlog file by hand — a plain JSON task list (see
67
+ # Backlog format), created on first use:
68
+ # .forgeo/backlog.json
69
+
70
+ # Or: add tasks from the web console once your forgeo is registered
71
+ # (first `forgeo start` registers it automatically):
72
+ forgeo web # dashboard at http://0.0.0.0:8790, or keep it on with `forgeo web -d`
73
+ ```
56
74
 
57
75
  ![Forgeo web console](docs/img/console.png)
58
76
 
59
- By default the dashboard is open to anyone who can reach the port. On a
60
- shared host, protect it with bearer-token auth: `forgeo web --token`
61
- generates a token (printed once, saved to `~/.config/forgeo/web.toml`) and
62
- requires `Authorization: Bearer <token>` on every `/api/*` route — see
63
- [Web console & HTTP API](docs/web-console-api.md).
64
-
65
- One-off commands: `forgeo once` (single cycle), `forgeo status` (summary),
66
- `forgeo validate` (read-only dry run before starting), `forgeo stop`,
67
- `forgeo restart`, every command is in the
68
- [CLI reference](docs/cli-reference.md).
69
-
70
- You can run several factories at once, one per repository, each config is
71
- fully independent (own backlog, logs, locks). Register each `forgeo.yaml`
72
- in the instance registry with `forgeo instance add NAME --config PATH`,
73
- manage any of them by name with `forgeo start/status/stop --name NAME`,
74
- list them all with `forgeo list`, and get one aggregate overview with the
75
- central dashboard, `forgeo web`.
77
+ ### 4. Check the configuration
78
+
79
+ ```bash
80
+ forgeo validate
81
+ ```
82
+
83
+ Read-only dry run before the first start: verifies `forgeo.yaml`, the git
84
+ repo, branch and remote, that the backlog parses (fetching it once when it
85
+ is an HTTP endpoint), the agent command, and the lock state. Never invokes
86
+ the agent and writes nothing.
87
+
88
+ ### 5. Start the daemon
89
+
90
+ ```bash
91
+ forgeo start
92
+ ```
93
+
94
+ Starts the daemon **detached in the background** and exits. Every
95
+ `interval_minutes` it runs one cycle: pick the oldest `OPEN` task whose
96
+ dependencies are all `COMPLETED`, run your coding agent on it, commit the
97
+ result. When the backlog is empty, the same agent runs a refactoring pass
98
+ over the codebase instead.
99
+
100
+ ### Day-to-day commands
101
+
102
+ ```bash
103
+ forgeo status # Config, backlog counts, next runnable task, daemon running?, last outcome
104
+ forgeo once # Run exactly one cycle in the foreground, no daemon left behind
105
+ forgeo run --task SELF-012 # Run one specific OPEN task now (triage)
106
+ forgeo stop # Stop the background daemon
107
+ forgeo restart # Stop and start again (re-reads forgeo.yaml after edits)
108
+ forgeo web # Dashboard: every instance's backlog, run history and logs
109
+ ```
110
+
111
+ `forgeo web` defaults to an open dashboard on `http://0.0.0.0:8790`; on a
112
+ shared host protect it with `forgeo web --token` (requires
113
+ `Authorization: Bearer <token>` on every `/api/*` route — see
114
+ [Web console & HTTP API](docs/web-console-api.md)).
115
+
116
+ ### Multiple repositories (instances)
117
+
118
+ Run several factories at once, one per repository; each config is fully
119
+ independent (own backlog, logs, locks). Register each `forgeo.yaml` with
120
+ `forgeo instance add NAME --config PATH`, manage any of them by name with
121
+ `forgeo start/status/stop --name NAME`, list them all with `forgeo list`,
122
+ and get one aggregate overview with the central dashboard, `forgeo web`.
76
123
 
77
124
  ## Documentation
78
125
 
@@ -19,18 +19,28 @@ the process environment is augmented as follows:
19
19
 
20
20
  | Variable | Meaning |
21
21
  | --- | --- |
22
- | `FORGEO_TASK` | The full instruction for this run: title, blank line, description, and an "Acceptance criteria:" list when present. |
23
- | `FORGEO_REPO` | The absolute path of the repository. |
24
- | `FORGEO_BRANCH` | The branch everything is committed to (default `main`). |
25
- | *every `agent_env` key* | Any extra variables from `agent_env` in the config. |
26
- | *inherited environment* | The daemon's own environment. |
22
+ | <span style="white-space: nowrap">`FORGEO_TASK`</span> | The full instruction for this run: the project context when `task_context` is configured, then title, blank line, description, and an "Acceptance criteria:" list when present. |
23
+ | <span style="white-space: nowrap">`FORGEO_REPO`</span> | The absolute path of the repository. |
24
+ | <span style="white-space: nowrap">`FORGEO_BRANCH`</span> | The branch everything is committed to (default `main`). |
25
+ | <span style="white-space: nowrap">*every `agent_env` key*</span> | Any extra variables from `agent_env` in the config. |
26
+ | <span style="white-space: nowrap">*inherited environment*</span> | The daemon's own environment. |
27
27
 
28
28
  `FORGEO_*` variables are set unconditionally and take precedence over both the
29
29
  inherited environment and `agent_env`.
30
30
 
31
+ ### The task is not the whole picture
32
+
33
+ A task description is isolated by design: it describes one unit of work, not
34
+ the project. When `task_context` is set (see
35
+ [Configuration](configuration.md#task_context)), Forgeo prepends the contents
36
+ of that file — the high-level project overview — to `FORGEO_TASK` before the
37
+ task, under a `# Project context` heading, followed by the task under a
38
+ `# Task` heading. The file is re-read on every run, so an agent's own updates
39
+ to it are seen by the next cycle.
40
+
31
41
  For a refactoring run (empty backlog) the same contract applies: the refactor
32
- prompt arrives as `FORGEO_TASK` with the task id `REFACTOR` and title
33
- "Refactoring pass".
42
+ prompt arrives as `FORGEO_TASK` (with the context prepended when configured),
43
+ with the task id `REFACTOR` and title "Refactoring pass".
34
44
 
35
45
  ## Exit codes
36
46
 
@@ -38,10 +48,10 @@ The exit code decides the outcome of the run:
38
48
 
39
49
  | Exit code | Outcome | What happens |
40
50
  | --- | --- | --- |
41
- | `0` | **SUCCESS** | Everything is committed (`git add -A && git commit`) with the message `<title> (#<id>)`, pushed when a remote is set, and the task is marked `COMPLETED`. |
42
- | `no_changes_exit_code` (default `3`) | **SUCCESS, no changes** | The agent explicitly reports the task needs **no code change**: the task is marked `COMPLETED` without a commit (and the run record notes why). Only accepted when the working tree is clean. |
43
- | `blocked_exit_code` (default `2`) | **BLOCKED** | The agent needs a human decision. Partial work is committed as `<title> [partial]`, the agent's reason is persisted on the task (`blocker_reason`), optional Telegram and/or webhook notifications are sent, and the task is marked `BLOCKED`. `BLOCKER.md` is rendered from the backlog's `BLOCKED` tasks on the next cycle — real per-task reasons, never generic text — and disappears once the last one is resolved (reopen it from the web console). |
44
- | anything else | **ERROR** | Changes are discarded (`git reset --hard` + `git clean -fd`), the failure is logged, and the task is marked `FAILED`. |
51
+ | <span style="white-space: nowrap">`0`</span> | **SUCCESS** | Everything is committed (`git add -A && git commit`) with the message `<title> (#<id>)`, pushed when a remote is set, and the task is marked `COMPLETED`. |
52
+ | <span style="white-space: nowrap">`no_changes_exit_code` (default `3`)</span> | **SUCCESS, no changes** | The agent explicitly reports the task needs **no code change**: the task is marked `COMPLETED` without a commit (and the run record notes why). Only accepted when the working tree is clean. |
53
+ | <span style="white-space: nowrap">`blocked_exit_code` (default `2`)</span> | **BLOCKED** | The agent needs a human decision. Partial work is committed as `<title> [partial]`, the agent's reason is persisted on the task (`blocker_reason`), optional Telegram and/or webhook notifications are sent, and the task is marked `BLOCKED`. `BLOCKER.md` is rendered from the backlog's `BLOCKED` tasks on the next cycle — real per-task reasons, never generic text — and disappears once the last one is resolved (reopen it from the web console). |
54
+ | <span style="white-space: nowrap">anything else</span> | **ERROR** | Changes are discarded (`git reset --hard` + `git clean -fd`), the failure is logged, and the task is marked `FAILED`. |
45
55
 
46
56
  The blocked exit code is configurable via `blocked_exit_code` in
47
57
  [forgeo.yaml](configuration.md), and the no-change exit code via
@@ -125,6 +135,9 @@ agent_command: >
125
135
  Make the code changes requested below and nothing else. Do NOT run
126
136
  git commit, git push, or git add -A — Forgeo commits your work.
127
137
  Verify with the test suite where applicable.
138
+ Read AGENTS.md at the start of the session, and CONTEXT.md if present;
139
+ if your change materially affects the project overview or conventions,
140
+ update AGENTS.md and CONTEXT.md accordingly.
128
141
  $FORGEO_TASK"
129
142
  ```
130
143
 
@@ -80,10 +80,10 @@ cheap/fast model and hard ones to a frontier model:
80
80
 
81
81
  | Status | Meaning |
82
82
  | --- | --- |
83
- | `OPEN` | To be picked by Forgeo. |
84
- | `BLOCKED` | Waiting on a human decision; Forgeo pauses while any task is blocked. |
85
- | `COMPLETED` | The agent finished and the work was committed (and pushed). |
86
- | `FAILED` | The agent errored; changes were discarded and the reason is recorded in `failure_reason`. |
83
+ | <span style="white-space: nowrap">`OPEN`</span> | To be picked by Forgeo. |
84
+ | <span style="white-space: nowrap">`BLOCKED`</span> | Waiting on a human decision; Forgeo pauses while any task is blocked. |
85
+ | <span style="white-space: nowrap">`COMPLETED`</span> | The agent finished and the work was committed (and pushed). |
86
+ | <span style="white-space: nowrap">`FAILED`</span> | The agent errored; changes were discarded and the reason is recorded in `failure_reason`. |
87
87
 
88
88
  ## Retrying a failed task
89
89
 
@@ -298,8 +298,8 @@ then treats that endpoint exactly like the file:
298
298
 
299
299
  | When | Request |
300
300
  | --- | --- |
301
- | Every read | `GET <url>` returns the whole document |
302
- | Every write | `POST <url>` sends the whole document back |
301
+ | <span style="white-space: nowrap">Every read</span> | `GET <url>` returns the whole document |
302
+ | <span style="white-space: nowrap">Every write</span> | `POST <url>` sends the whole document back |
303
303
 
304
304
  ```yaml
305
305
  backlog: https://api.example.com/api/forgeo/backlog
@@ -1,7 +1,7 @@
1
1
  # CLI reference
2
2
 
3
3
  All commands read `forgeo.yaml` from the current directory; pass
4
- `--config <file>` to use a different one. `start`, `once`, `status`,
4
+ `--config <file>` to use a different one. `start`, `once`, `run`, `status`,
5
5
  `validate`, `stop` and `restart` also accept `--name <instance>` to resolve
6
6
  the config from the **instance registry** — see [`forgeo instance`](#forgeo-instance)
7
7
  below.
@@ -20,8 +20,8 @@ Guided first-time setup: interactively write a `forgeo.yaml`.
20
20
 
21
21
  | Flag | Description |
22
22
  | --- | --- |
23
- | `--config <file>` | Where to write the config (default `forgeo.yaml`). |
24
- | `--force` | Overwrite an existing config file. |
23
+ | <span style="white-space: nowrap">`--config <file>`</span> | Where to write the config (default `forgeo.yaml`). |
24
+ | <span style="white-space: nowrap">`--force`</span> | Overwrite an existing config file. |
25
25
 
26
26
  Exit codes:
27
27
 
@@ -41,10 +41,10 @@ foreground instead, interruptible with Ctrl-C.
41
41
 
42
42
  | Flag | Description |
43
43
  | --- | --- |
44
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
45
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
46
- | `--interval-minutes <n>` | Override the schedule interval from the config for this run. |
47
- | `-f`, `--foreground` | Run the daemon in the foreground instead of starting it detached. |
44
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
45
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
46
+ | <span style="white-space: nowrap">`--interval-minutes <n>`</span> | Override the schedule interval from the config for this run. |
47
+ | <span style="white-space: nowrap">`-f`, `--foreground`</span> | Run the daemon in the foreground instead of starting it detached. |
48
48
 
49
49
  The daemon wakes every `interval_minutes` and runs one cycle. When no config
50
50
  exists, `forgeo start` offers the guided setup. A second `start` (or `once`)
@@ -81,8 +81,8 @@ Run exactly **one cycle** and exit; no daemon needed.
81
81
 
82
82
  | Flag | Description |
83
83
  | --- | --- |
84
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
85
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
84
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
85
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
86
86
 
87
87
  `forgeo once` shares the run lock with the daemon, so it never overlaps a
88
88
  running `forgeo start` — useful to test a config or process a backlog without
@@ -92,13 +92,38 @@ Outcomes a cycle can produce:
92
92
 
93
93
  | Outcome | Meaning |
94
94
  | --- | --- |
95
- | `task` | A task ran and finished. |
96
- | `refactor` | A refactoring pass ran (backlog was empty). |
97
- | `blocked` | A `BLOCKED` task exists; `BLOCKER.md` re-rendered from the backlog; paused. |
98
- | `paused` | A blocker file exists; nothing ran. |
99
- | `dirty` | The working tree was dirty; the task was not started. |
100
- | `skipped` | A previous run was still in progress (daemon only). |
101
- | `error` | A cycle crashed (daemon only). |
95
+ | <span style="white-space: nowrap">`task`</span> | A task ran and finished. |
96
+ | <span style="white-space: nowrap">`refactor`</span> | A refactoring pass ran (backlog was empty). |
97
+ | <span style="white-space: nowrap">`blocked`</span> | A `BLOCKED` task exists; `BLOCKER.md` re-rendered from the backlog; paused. |
98
+ | <span style="white-space: nowrap">`paused`</span> | A blocker file exists; nothing ran. |
99
+ | <span style="white-space: nowrap">`dirty`</span> | The working tree was dirty; the task was not started. |
100
+ | <span style="white-space: nowrap">`skipped`</span> | A previous run was still in progress (daemon only). |
101
+ | <span style="white-space: nowrap">`error`</span> | A cycle crashed (daemon only). |
102
+
103
+ ## `forgeo run`
104
+
105
+ Run exactly **one specific task** by id and exit — no daemon, no waiting for
106
+ the backlog order. Use it for triage: rerun a `FAILED` task immediately
107
+ (after reopening it), or try a risky task right now instead of letting the
108
+ scheduler pick it later.
109
+
110
+ ```bash
111
+ forgeo run --task SELF-012
112
+ ```
113
+
114
+ | Flag | Description |
115
+ | --- | --- |
116
+ | <span style="white-space: nowrap">`--task <id>`</span> | Id of the `OPEN` task to run. **Required.** |
117
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
118
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
119
+
120
+ `forgeo run` shares the per-forgeo run lock with the daemon and `forgeo once`,
121
+ so it never overlaps them — it refuses (exit `1`) while the lock is held. It
122
+ also refuses (exit `1`) with a clear message when the task does not exist in
123
+ the backlog or its status is not `OPEN` (a `FAILED` task must be reopened
124
+ first, e.g. from the web console or by editing the backlog). On success it
125
+ prints `Cycle finished: <outcome>` and records the run in `runs.jsonl` like
126
+ any other task run.
102
127
 
103
128
  ## `forgeo status`
104
129
 
@@ -106,8 +131,8 @@ Print a read-only summary of Forgeo. Never starts an agent.
106
131
 
107
132
  | Flag | Description |
108
133
  | --- | --- |
109
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
110
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
134
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
135
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
111
136
 
112
137
  Output:
113
138
 
@@ -144,8 +169,8 @@ while a daemon is active.
144
169
 
145
170
  | Flag | Description |
146
171
  | --- | --- |
147
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
148
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
172
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
173
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
149
174
 
150
175
  It validates, reporting **all** problems at once:
151
176
 
@@ -187,9 +212,9 @@ first).
187
212
 
188
213
  | Flag | Description |
189
214
  | --- | --- |
190
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
191
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
192
- | `--timeout <seconds>` | How long to wait for the daemon to exit (default `600`). |
215
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
216
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
217
+ | <span style="white-space: nowrap">`--timeout <seconds>`</span> | How long to wait for the daemon to exit (default `600`). |
193
218
 
194
219
  Exit code is `0` on success, `1` when Forgeo is not running, the lock
195
220
  records a dead PID, or the daemon did not exit within the timeout.
@@ -210,17 +235,17 @@ values while running so its lock files are never detached from the config.
210
235
 
211
236
  | Flag | Description |
212
237
  | --- | --- |
213
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
214
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
215
- | `--timeout <seconds>` | How long to wait for the old daemon to exit (default `600`). |
238
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
239
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
240
+ | <span style="white-space: nowrap">`--timeout <seconds>`</span> | How long to wait for the old daemon to exit (default `600`). |
216
241
 
217
242
  On success it prints the new daemon PID and interval.
218
243
 
219
244
  ### `--config` vs `--name`
220
245
 
221
- On `start`, `once`, `status`, `validate`, `stop` and `restart`, `--name`
222
- resolves the `forgeo.yaml` from the instance registry instead of reading
223
- `--config`. The two flags are mutually exclusive — passing both is an
246
+ On `start`, `once`, `run`, `status`, `validate`, `stop` and `restart`,
247
+ `--name` resolves the `forgeo.yaml` from the instance registry instead of
248
+ reading `--config`. The two flags are mutually exclusive — passing both is an
224
249
  argparse error. An unknown instance name prints a clear error and exits
225
250
  non-zero.
226
251
 
@@ -244,7 +269,7 @@ differs from `config.name`.
244
269
 
245
270
  | Flag | Description |
246
271
  | --- | --- |
247
- | `--config <file>` | Path to the `forgeo.yaml` to register. **Required.** |
272
+ | <span style="white-space: nowrap">`--config <file>`</span> | Path to the `forgeo.yaml` to register. **Required.** |
248
273
 
249
274
  - The name must match `^[a-zA-Z0-9._-]+$`; invalid or duplicate names are
250
275
  rejected with a clear error (exit `1`).
@@ -273,11 +298,11 @@ running.
273
298
 
274
299
  | Flag | Description |
275
300
  | --- | --- |
276
- | `--host <address>` | Bind address (default `0.0.0.0`). |
277
- | `--port <port>` | Bind port (default `8790`). |
278
- | `-d`, `--detach` | Start the dashboard in the background and return once it binds. |
279
- | `--token [TOKEN]` | Require a bearer token on every `/api/*` route (see below). |
280
- | `--timeout <seconds>` | How long to wait for the dashboard to bind when detached (default `30`). |
301
+ | <span style="white-space: nowrap">`--host <address>`</span> | Bind address (default `0.0.0.0`). |
302
+ | <span style="white-space: nowrap">`--port <port>`</span> | Bind port (default `8790`). |
303
+ | <span style="white-space: nowrap">`-d`, `--detach`</span> | Start the dashboard in the background and return once it binds. |
304
+ | <span style="white-space: nowrap">`--token [TOKEN]`</span> | Require a bearer token on every `/api/*` route (see below). |
305
+ | <span style="white-space: nowrap">`--timeout <seconds>`</span> | How long to wait for the dashboard to bind when detached (default `30`). |
281
306
 
282
307
  Without `-d` the dashboard runs in the foreground; interrupt it with Ctrl-C
283
308
  or stop it from another terminal with `forgeo web stop`.
@@ -322,7 +347,7 @@ Stop the running dashboard gracefully (SIGTERM) and wait for it to exit.
322
347
 
323
348
  | Flag | Description |
324
349
  | --- | --- |
325
- | `--timeout <seconds>` | How long to wait for the dashboard to exit (default `30`). |
350
+ | <span style="white-space: nowrap">`--timeout <seconds>`</span> | How long to wait for the dashboard to exit (default `30`). |
326
351
 
327
352
  Exit code is `0` on success, `1` when the dashboard is not running, the lock
328
353
  records a dead PID, or it did not exit within the timeout. The lock file is