FlowImage is a Codex image feedback loop for UI work.
It lets Codex publish screenshots to a browser/iPad canvas, lets a human draw or edit on that canvas, then lets Codex collect the returned PNG results before making code changes.
The MVP is intentionally small:
- Codex publishes one or more PNG screenshots through
flow_image_publish. - FlowImage creates a session with short View, Edit, and Owner links.
- The Edit link opens a canvas where a human can draw, erase, zoom, and save results.
- Codex collects ready merged PNG results through
flow_image_sync. - Codex modifies code only after explicit user confirmation.
FlowImage is accountless. Permissions are capability links:
View Link: read-only.Edit Link: can draw and submit canvas results.Owner Link: can manage retention and copy View/Edit links.Owner Token: stored locally by the Codex bridge so Codex can upload screenshots and collect results.
Do not post Edit or Owner links publicly. Anyone with an Edit Link can change that session. Anyone with an Owner Link can change retention and share links.
flow-image/
├─ .agents/plugins/marketplace.json
├─ apps/
│ ├─ backend/ # Express + SQLite FlowImage server
│ ├─ mcp-bridge/ # MCP tools used by Codex
│ └─ web/ # Browser/iPad canvas frontend
├─ plugins/
│ └─ flow-image/ # Codex plugin package
│ ├─ .codex-plugin/plugin.json
│ ├─ .mcp.json
│ ├─ scripts/
│ └─ skills/
└─ package.json
Server state is stored in SQLite at:
apps/backend/data/flowimage.sqlite
PNG files live under:
apps/backend/data/files/
- Node.js 22+
- pnpm 11+
- Codex with plugin and MCP support
- A reachable FlowImage server:
- official hosted server, or
- your self-hosted server, or
- a local/LAN dev server
This repository is designed to be shared as a standalone GitHub repo.
On another computer, keep a local clone because the Codex plugin package is thin and starts the MCP bridge from this repo:
FLOWIMAGE_REPO_URL="https://github.com/<github-owner>/flow-image"
FLOWIMAGE_REPO_DIR="$HOME/.flowimage/flow-image-repo"
mkdir -p "$(dirname "$FLOWIMAGE_REPO_DIR")"
git clone "$FLOWIMAGE_REPO_URL" "$FLOWIMAGE_REPO_DIR"
cd "$FLOWIMAGE_REPO_DIR"
corepack pnpm@11.7.0 install --frozen-lockfile
codex plugin marketplace add "$FLOWIMAGE_REPO_DIR/.agents/plugins/marketplace.json"
codex plugin add flow-image@flow-image-localThen configure the FlowImage server URL from Codex with FlowImage Settings, or write the config file.
macOS/Linux:
mkdir -p ~/.flowimage
cat > ~/.flowimage/config.json <<'JSON'
{
"server_url": "https://flow-image.liujinhang.com"
}
JSON
chmod 600 ~/.flowimage/config.jsonWindows PowerShell:
New-Item -ItemType Directory -Force "$env:USERPROFILE\\.flowimage" | Out-Null
'{ "server_url": "https://flow-image.liujinhang.com" }' |
Set-Content -Encoding UTF8 "$env:USERPROFILE\\.flowimage\\config.json"For a LAN dev server, use your server machine IP instead:
{
"server_url": "http://192.168.2.72:3939"
}Verify:
codex plugin list --marketplace flow-image-local
node "$FLOWIMAGE_REPO_DIR/plugins/flow-image/scripts/settings-server.mjs" --print-configRestart Codex or open a new Codex thread after installation.
If you are an AI coding agent installing FlowImage for a user, follow this exact flow.
Assumptions:
- The user gives you the GitHub repo URL.
- The user gives you the FlowImage server URL, or asks you to use the default hosted server.
- Do not ask for a pair code. FlowImage no longer uses pair codes.
- Prefer plugin installation over naked
codex mcp add.
Set variables. macOS/Linux:
FLOWIMAGE_REPO_URL="https://github.com/<github-owner>/flow-image"
FLOWIMAGE_SERVER_URL="https://flow-image.liujinhang.com"
FLOWIMAGE_REPO_DIR="$HOME/.flowimage/flow-image-repo"Windows PowerShell:
$env:FLOWIMAGE_REPO_URL = "https://github.com/<github-owner>/flow-image"
$env:FLOWIMAGE_SERVER_URL = "https://flow-image.liujinhang.com"
$env:FLOWIMAGE_REPO_DIR = "$env:USERPROFILE\\.flowimage\\flow-image-repo"One-block install command for macOS/Linux agents:
FLOWIMAGE_REPO_URL="https://github.com/<github-owner>/flow-image" \
FLOWIMAGE_SERVER_URL="https://flow-image.liujinhang.com" \
FLOWIMAGE_REPO_DIR="$HOME/.flowimage/flow-image-repo" \
bash <<'FLOWIMAGE_INSTALL'
set -euo pipefail
: "${FLOWIMAGE_REPO_URL:?FLOWIMAGE_REPO_URL is required}"
: "${FLOWIMAGE_SERVER_URL:?FLOWIMAGE_SERVER_URL is required}"
: "${FLOWIMAGE_REPO_DIR:?FLOWIMAGE_REPO_DIR is required}"
if [ -d "$FLOWIMAGE_REPO_DIR/.git" ]; then
git -C "$FLOWIMAGE_REPO_DIR" fetch origin main
git -C "$FLOWIMAGE_REPO_DIR" checkout main
git -C "$FLOWIMAGE_REPO_DIR" pull --ff-only origin main
else
mkdir -p "$(dirname "$FLOWIMAGE_REPO_DIR")"
git clone "$FLOWIMAGE_REPO_URL" "$FLOWIMAGE_REPO_DIR"
fi
cd "$FLOWIMAGE_REPO_DIR"
corepack pnpm@11.7.0 install --frozen-lockfile
codex plugin marketplace add "$FLOWIMAGE_REPO_DIR/.agents/plugins/marketplace.json"
codex plugin add flow-image@flow-image-local
mkdir -p "$HOME/.flowimage"
cat > "$HOME/.flowimage/config.json" <<JSON
{
"server_url": "$FLOWIMAGE_SERVER_URL"
}
JSON
chmod 600 "$HOME/.flowimage/config.json"
node scripts/configure-plugin-mcp.mjs "$FLOWIMAGE_REPO_DIR"
codex plugin list --marketplace flow-image-local
node "$FLOWIMAGE_REPO_DIR/plugins/flow-image/scripts/settings-server.mjs" --print-config
node "$FLOWIMAGE_REPO_DIR/apps/mcp-bridge/src/index.mjs" < /dev/null
FLOWIMAGE_INSTALLOne-block install command for Windows PowerShell agents:
$ErrorActionPreference = "Stop"
$env:FLOWIMAGE_REPO_URL = "https://github.com/<github-owner>/flow-image"
$env:FLOWIMAGE_SERVER_URL = "https://flow-image.liujinhang.com"
$env:FLOWIMAGE_REPO_DIR = "$env:USERPROFILE\\.flowimage\\flow-image-repo"
if (Test-Path "$env:FLOWIMAGE_REPO_DIR\\.git") {
git -C $env:FLOWIMAGE_REPO_DIR fetch origin main
git -C $env:FLOWIMAGE_REPO_DIR checkout main
git -C $env:FLOWIMAGE_REPO_DIR pull --ff-only origin main
} else {
New-Item -ItemType Directory -Force (Split-Path $env:FLOWIMAGE_REPO_DIR) | Out-Null
git clone $env:FLOWIMAGE_REPO_URL $env:FLOWIMAGE_REPO_DIR
}
Set-Location $env:FLOWIMAGE_REPO_DIR
corepack pnpm@11.7.0 install --frozen-lockfile
codex plugin marketplace add "$env:FLOWIMAGE_REPO_DIR\\.agents\\plugins\\marketplace.json"
codex plugin add flow-image@flow-image-local
New-Item -ItemType Directory -Force "$env:USERPROFILE\\.flowimage" | Out-Null
"{ `"server_url`": `"$env:FLOWIMAGE_SERVER_URL`" }" |
Set-Content -Encoding UTF8 "$env:USERPROFILE\\.flowimage\\config.json"
node scripts/configure-plugin-mcp.mjs $env:FLOWIMAGE_REPO_DIR
codex plugin list --marketplace flow-image-local
node "$env:FLOWIMAGE_REPO_DIR\\plugins\\flow-image\\scripts\\settings-server.mjs" --print-config
node "$env:FLOWIMAGE_REPO_DIR\\apps\\mcp-bridge\\src\\index.mjs" < $nullInstall the marketplace and plugin:
git clone "$FLOWIMAGE_REPO_URL" "$FLOWIMAGE_REPO_DIR"
cd "$FLOWIMAGE_REPO_DIR"
corepack pnpm@11.7.0 install --frozen-lockfile
codex plugin marketplace add "$FLOWIMAGE_REPO_DIR/.agents/plugins/marketplace.json"
codex plugin add flow-image@flow-image-localWrite local config:
mkdir -p ~/.flowimage
cat > ~/.flowimage/config.json <<JSON
{
"server_url": "$FLOWIMAGE_SERVER_URL"
}
JSON
chmod 600 ~/.flowimage/config.jsonVerify installation:
codex plugin list --marketplace flow-image-local
node "$FLOWIMAGE_REPO_DIR/plugins/flow-image/scripts/settings-server.mjs" --print-config
node "$FLOWIMAGE_REPO_DIR/apps/mcp-bridge/src/index.mjs" < /dev/nullExpected:
flow-imageappears incodex plugin list.- The printed config contains the selected
server_url. - A new Codex thread exposes the FlowImage skill and bundled
flow_imageMCP tools.
Then tell the user:
FlowImage is installed. Restart Codex or open a new thread, then ask Codex to publish screenshots with FlowImage.
Instead of writing ~/.flowimage/config.json manually, you can open the plugin settings page:
node <flow-image-repo>/plugins/flow-image/scripts/settings-server.mjs --openThe settings page writes:
~/.flowimage/config.json
Only server_url is required.
After installation and configuration, ask Codex to publish screenshots:
Use FlowImage to publish screenshots of the current UI.
Codex should call:
flow_image_publish
FlowImage returns:
- View Link
- Edit Link
- Owner Link
session_id
Open the Edit Link on iPad/Web, draw on the canvas, and save or use Realtime mode.
Then ask Codex to collect results:
Collect the latest FlowImage results.
Codex should call:
flow_image_sync
Important workflow rule:
After collecting results, Codex should show or summarize the returned images first.
Codex should not modify application code until the user explicitly confirms.
Example confirmation:
确认,按这些结果修改。
Install dependencies:
corepack pnpm@11.7.0 install
cp .env.example .envStart the dev server for LAN/iPad use:
corepack pnpm@11.7.0 dev:backendThe default dev bind host is 0.0.0.0. The backend prints a usable FlowImage public URL, such as:
FlowImage public URL http://192.168.2.72:3939Use that URL in each Codex computer's FlowImage config:
{
"server_url": "http://<server-lan-ip>:3939"
}If you need to force a specific public URL:
BIND_HOST=0.0.0.0 PUBLIC_BASE_URL=http://<server-lan-ip>:3939 corepack pnpm@11.7.0 dev:backendWindows PowerShell:
$env:BIND_HOST = "0.0.0.0"
$env:PUBLIC_BASE_URL = "http://<server-lan-ip>:3939"
corepack pnpm@11.7.0 dev:backendFor local-only testing, explicitly bind localhost:
BIND_HOST=127.0.0.1 PUBLIC_BASE_URL=http://127.0.0.1:3939 corepack pnpm@11.7.0 dev:backendWindows PowerShell:
$env:BIND_HOST = "127.0.0.1"
$env:PUBLIC_BASE_URL = "http://127.0.0.1:3939"
corepack pnpm@11.7.0 dev:backendBrowsers only allow writing PNG images to the system clipboard in a secure context, usually HTTPS or localhost. For iPad/LAN use, run FlowImage over HTTPS with a locally trusted certificate.
Recommended local certificate flow:
corepack pnpm@11.7.0 cert:localInstall mkcert first if it is missing. On macOS you can use Homebrew; on Windows you can use Winget, Chocolatey, or Scoop.
The script creates:
.certs/flowimage.pem
.certs/flowimage-key.pem
Start the HTTPS server:
PUBLIC_BASE_URL=https://<server-lan-ip>:3939 corepack pnpm@11.7.0 dev:httpsWindows PowerShell:
$env:PUBLIC_BASE_URL = "https://<server-lan-ip>:3939"
corepack pnpm@11.7.0 dev:httpsThen configure each Codex computer with:
{
"server_url": "https://<server-lan-ip>:3939"
}For iPad, install and trust the mkcert Root CA:
mkcert -CAROOTCopy rootCA.pem from that directory to the iPad, install the profile, then enable full trust in:
Settings -> General -> About -> Certificate Trust Settings
The certificate generated by cert:local includes the current LAN IP, localhost, 127.0.0.1, and ::1.
On plain HTTP LAN URLs, the Copy Image button automatically downloads a PNG instead of showing an HTTPS error. On HTTPS deployments, the same button writes the PNG to the system clipboard when the browser allows it.
For development, you can bypass plugin installation and register the MCP bridge directly:
codex mcp add flow_image \
--env FLOWIMAGE_SERVER_URL=http://127.0.0.1:3939 \
-- node <flow-image-repo>/apps/mcp-bridge/src/index.mjsThis is useful while editing the bridge. For normal distribution, prefer the Codex plugin install path.
Recommended: make flow-image/ its own standalone GitHub repository.
cd /path/to/flow-image
git init
git add .
git commit -m "Package FlowImage Codex plugin"
git branch -M main
git remote add origin git@github.com:<github-owner>/flow-image.git
git push -u origin mainAnother computer can then install it with:
codex plugin marketplace add https://github.com/<github-owner>/flow-image --ref main
codex plugin add flow-image@flow-image-localIf the repo is private, make sure the target computer has GitHub credentials that can clone it.
- Product/UI name:
FlowImage - Codex plugin name:
flow-image - Local Codex MCP alias:
flow_image - Package/slug name:
flow-image - Future MCP Registry name:
net.like-water/flow-image
- Start a FlowImage server.
- Install the Codex plugin.
- Configure
~/.flowimage/config.json. - Ask Codex to call
flow_image_publish. - Open the returned Edit Link on iPad/Web.
- Draw, erase, zoom, submit, or use Realtime save.
- Open the View Link on another browser to confirm sync.
- Ask Codex to call
flow_image_sync. - Inspect the returned images/review URL.
- Tell Codex explicitly:
确认,按这些结果修改.
corepack pnpm@11.7.0 test
corepack pnpm@11.7.0 dev:check
git diff --checkdev:check checks localhost and the detected LAN URL by default. For production hosts or CI jobs that only bind localhost, set FLOWIMAGE_CHECK_LAN=0.
If the plugin is installed but tools do not appear:
- Restart Codex or open a new thread.
- Check that the plugin is installed:
codex plugin list --marketplace flow-image-local- Check config:
cat ~/.flowimage/config.json- Check server reachability:
curl -i "$(node -e 'console.log(JSON.parse(require("fs").readFileSync(process.env.HOME + "/.flowimage/config.json", "utf8")).server_url)')/"- If another bare MCP server named
flow_imagewas registered before, remove it:
codex mcp remove flow_imageThen restart Codex.