← All posts

How I Built ContextForge - Giving Your AI a Complete Project Briefing Before Every Session

Every AI debug session starts with a bottleneck: explaining the current state of the project. ContextForge automates that briefing — pulling git history, server logs, and BugCapture reports into a single structured prompt you paste into any AI.

View on GitHub

Every AI debug session starts the same way.

You open the chat, and before you can describe the actual problem, you have to explain everything else: what the project is, what changed recently, what the logs are saying, what you already tried. Five minutes of context-setting before you even get to the question.

The AI doesn’t know any of this. It starts from zero every time. And if you skip the context, you get generic answers that don’t account for the specific state your project is in right now.

ContextForge solves this by automating the briefing. It pulls together everything the AI needs to know — git diff, server logs, BugCapture reports, config files — and assembles it into a single structured prompt. You open a session, hit Generate, and paste. The AI is immediately oriented.

What the problem actually looks like

Here’s a concrete version of the problem. You have a PHP application running on a remote server. Something broke overnight. The symptoms are in the Apache error log. The likely cause is in the last three commits. There’s also a BugCapture report from when you recorded the bug this morning.

Before ContextForge, you’d:

  1. SSH into the server, run tail -n 100 /var/log/apache2/error.log, copy the relevant lines
  2. Open the local project, run git log --oneline -5, run git diff --stat HEAD
  3. Open the BugCapture report from ~/bugcapture-output/
  4. Paste all of this into the chat, formatted manually

That’s maybe 10 minutes if you’re practiced. And you do it every session.

ContextForge makes it one click.

The briefing format

The output is a Markdown document that follows a consistent structure:

# AI Briefing — Fix checkout form

**Date**: July 4, 2026, 10:23 AM
**Scope**: 🐛 Bug fix
**Server**: staging-server
**Project**: /var/www/myapp

---

## Git context

**Status**

M src/Checkout.php M src/Cart.php


**Last 5 commits**

a1b2c3d Fix cart total calculation e4f5a6b Add discount code support …


## Server error log (last 60 lines)

**/var/log/apache2/error.log**

[error] PHP Fatal error: Call to undefined method …


## Recorded bug (BugCapture)

**Bug**: Checkout form freezes after entering promo code
**Screenshot**: [embedded]
...

## Objective

Analyze the context above and propose a solution for: Fix checkout form

The AI reads this and immediately knows: what the project is, what changed, what broke, and what the goal is. No back-and-forth to establish context.

The architecture

ContextForge is a Node.js HTTP server on port 4328. It has four main capabilities:

1. Git context (gitContext)

For local projects, it runs three git commands in parallel:

  • git status --short — uncommitted changes at a glance
  • git log --oneline -5 — recent commit history
  • git diff --stat HEAD — what files changed and by how much

All three are run with execFile with a 10-second timeout, so a slow or broken repo doesn’t block anything.

2. Remote log fetching via SSH

For servers defined in ~/.config/machina/servers.json, ContextForge opens an SSH connection using ssh2 and runs tail -n N on each configured log path. It supports both password and key-based auth.

The server config looks like this:

[
  {
    "id": "staging",
    "label": "Staging Server",
    "host": "192.168.1.100",
    "port": 22,
    "username": "deploy",
    "auth": "key",
    "keyFile": "~/.ssh/id_rsa",
    "logPaths": ["/var/log/apache2/error.log"]
  }
]

The same file is shared with BugCapture. You configure your servers once, and every tool in Machina picks them up.

3. Project type detection

When you give ContextForge a local or remote path, it scans for fingerprint files to detect the project type: configuration.php for Joomla, wp-config.php for WordPress, artisan + composer.json for Laravel, package.json for Node.js. Based on the detected type, it suggests the relevant log paths automatically.

For remote projects, this all happens over SSH in a single compound command — no multiple round trips:

cd /var/www/myapp
TYPE=generic
[ -f configuration.php ] && TYPE=joomla
[ -f wp-config.php ] && TYPE=wordpress
...
for p in /var/log/apache2/error.log /var/log/nginx/error.log ...; do
  [ -f "$p" ] && echo "$p"
done

One SSH connection, one command, structured output parsed client-side.

4. BugCapture integration

ContextForge reads ~/bugcapture-output/ for .md files produced by BugCapture, sorted by modification date (most recent first). It strips base64 image data from the embedded content before including it in the briefing — the AI gets the text description and screenshot context without the prompt bloating to 50,000 characters.

function truncateBugCapture(content) {
  const idx = content.indexOf('data:image');
  if (idx === -1) return content;
  const before = content.lastIndexOf('\n', idx);
  return content.slice(0, before > 0 ? before : idx).trim()
    + '\n\n[...base64 images omitted...]';
}

The UI

The frontend is a single index.html served by the Express server. It has three panels:

Server panel — pick a configured SSH connection or leave blank for local-only. When you select a server, it scans the remote project path and populates the log path dropdown automatically.

Local panel — point it at a local git repository. On scan, it detects the project type, finds config files, and suggests log paths.

BugCapture panel — shows the 10 most recent .md reports from the BugCapture output directory, sorted by date. One click attaches it to the briefing.

The Generate button assembles all selected inputs and displays the full Markdown briefing in a textarea. One click copies it to clipboard.

What I learned

The main design decision was how to handle the remote SSH connection. I considered having the frontend talk directly to a WebSocket that streams the log, but that adds complexity and makes the architecture harder to reason about. Instead, ContextForge does everything server-side and returns a single JSON payload. The UI is stateless with respect to the server — it just formats and displays what the API returns.

The project type detection was more useful than I expected. On Joomla, the error log path is buried in configuration.php as $log_path. Detecting the project type and parsing that field automatically means you never have to hunt for where Joomla logs errors — ContextForge finds it.

The BugCapture integration came together easily because both tools use the same output format. ContextForge reads BugCapture’s .md files, and the briefing it generates is also a .md file. Everything in Machina passes Markdown between tools, which means any tool’s output can be another tool’s input.

The workflow it enables

The full Machina workflow for a bug session:

  1. BugCapture — screen-record the bug, get a .md with screenshot + transcribed description
  2. ContextForge — one click generates a briefing: git diff + server logs + BugCapture report
  3. PromptBoard — paste the briefing, add visual structure, export a final structured prompt

The AI receives a complete briefing instead of a single question. In practice, this means the first response is usually the actionable one — you don’t spend two or three turns establishing what you already knew.


ContextForge is part of Machina — a free, open-source suite of AI developer tools.
View on GitHub

Stay in the loop

New tools, workflows, and AI dev insights

Monthly digest of what was built, what was learned, and what's next.

No spam · Unsubscribe anytime