You’ve got a ticket with three paragraphs of requirements and a design doc you haven’t started. Normally that’s twenty minutes of copy-pasting into a chat window before an AI assistant even has enough context to help. Here, it’s one command:
…and Claude — or any MCP-compatible AI assistant — already has direct access to the ticket, its history, and your wiki. That’s the GForge CLI with MCP support, shipped in 26.0 back in June — and we’ve been improving on it ever since. The CLI (gforge) gives you tickets, wiki, and code from your terminal; gforge mcp exposes that same access to Claude Code or any other MCP-compatible AI assistant. (If you want to follow along, here’s how to set it up.) A changelog entry doesn’t really do it justice, so here’s what it actually does, with five real examples.
1. From ticket to real analysis
We started with the most natural version of the request — no special syntax, no invoking a named command, just a plain ask.
Nothing there came from guessing — it’s the ticket’s actual fields, its one real follow-up, and a check for supporting material that turned up none. Since the spec looked implementation-ready on paper, we asked it to go a step further.
Two of the spec’s own assumptions didn’t hold up. It says the TOTP secret should be “encrypted at rest using the same mechanism as other sensitive fields” — there is no such mechanism. The two closest analogs (an OIDC client secret, an LDAP bind password) are both stored as plain, unencrypted settings today. Same story for the admin-reset requirement: “requires a reason, logged” has nothing to extend — the real audit-write helper doesn’t have a reason field at all.
Two other pieces checked out cleanly. Failed-login throttling already has a complete, reusable mechanism a failed TOTP attempt could call directly, no new code needed. And there’s a real question the ticket never raises: per-user fields like this in the codebase typically go through a lightweight settings mechanism rather than new database columns — a genuine architectural choice worth making deliberately instead of defaulting to “just add a migration.”
Then we asked for it in a form the next engineer could actually use.
That’s using Notebooks — no more writing analysis in a separate tool and linking it back to the ticket; it just lives there.
2. Keeping documentation current
Wiki search matches page names, not full text, so finding the page was a one-line lookup. Reading it turned up a real gap: the page is still at version 1, last touched August 19. Five days later, on August 24, the CLI shipped two new commands — gforge wiki tagged <tag> to list pages by tag, and gforge wiki upload to push a local directory of Markdown pages into a project wiki — plus a --file flag on copy and mirror for seeding from a tag query’s output. None of it made it into the page.
That’s exactly the kind of drift this workflow is built to catch: point Claude at the shipping ticket, and it pulls the change, reads what’s already documented, and drafts the update — in this case, a new subsection covering the two commands, with the --file flag folded into the existing examples. (We stopped short of actually publishing that update for this walkthrough — didn’t want to make a live doc change just to write a blog post about it — but everything up to that point is exactly what happened, and the gap is real.)
The same search-read-synthesize pattern is what makes this useful for open-ended work too, like pulling together a response to an RFI or trade study: search what you’ve already documented, read the relevant pages, and let Claude draft from your own material instead of a blank page.
3. From bug report to real fix
We gave Claude Code nothing but the original one-line report. No stack trace, no file to start from, no hint at where the problem lives.
It read the actual docman panel and file-organizer modal source, traced the click through to a template that was listening for an event named onOrganize while the component actually emits onOrganizer — a one-character mismatch that meant the handler was never wired up at all. It fixed the binding, and separately noticed the modal’s folder-load failure was being silently swallowed by an empty .catch(() => {}), which explained the “no console error” part of the original report — so it fixed that too, replacing it with a real error message and a clean close instead of a stuck modal.
Two real problems, found by reading code rather than guessing, from a bug report with almost nothing to go on.
4. Code review that knows your standards
Once that fix was written, we pointed a separate review pass at it — same diff, fresh context, checking it against the original ticket rather than just skimming for style.
The review confirmed both changes mapped directly back to the reported symptom, and caught one thing worth double-checking: the new error message falls back to '(unknown)' if a file has no description — reasonable, but worth confirming that’s the clearest thing to show a user in that spot.
Independent review catching a real, if minor, refinement — on a fix the same tool had just written — is the actual test of whether a review step adds anything beyond rubber-stamping.
5. Release notes, the way we’d do it internally
This one’s scoped to a GForge milestone rather than a date range: give it one, and it pulls everything closed in it, flags anything marked as a breaking change, and drafts output tailored to your audience — an internal changelog, a customer announcement, or an email. Exactly the tool we reach for at the end of a sprint or release cycle.
Where to go from here
Everything above starts with gforge login. If you want to go further, gforge apidocs downloads the complete API reference, and gforge api <endpoint> gives you raw, authenticated access to anything in it.
Full CLI documentation: next.gforge.com/project/gforge-docs/wiki