//depot/… — read + write

The whole depot,
in a browser tab.

p4-web is a lightweight web UI for Perforce — a P4V / Swarm alternative sized for individuals and small teams. Browse, blame, diff, search, review, and even edit & submit, from one FastAPI process that shells out to the p4 CLI. No database server, no build step, no framework.

p4 diff2 //you/workflow#before //you/workflow#after
·@@ your daily Perforce workflow @@
1-install P4V on every machine you might read code from
2-stand up Swarm just to link a changelist in chat
1+./run.sh # one process, ~zero setup
2+open http://127.0.0.1:8080 # log in with your p4 account
3 protections still apply — every call runs as you
CL 65134
read-only core

Everything you open P4V for

Each card is backed by the real p4 command underneath — the app is a thin, honest wrapper, so results match your CLI exactly.

p4 dirs

Depot browser

Breadcrumbs, sortable listings, and a P4V-style lazy tree sidebar synced to deep links.

p4 print

File viewer

Syntax highlighting (vendored, offline), line-number gutter, revision dropdown, line permalinks.

p4 filelog

History & graph

Full history across renames and branches, plus an SVG revision graph with integration provenance.

p4 diff2

Diff tools

Unified and side-by-side everywhere: arbitrary revision pairs, folder diffs, shelved-vs-base.

p4 annotate

Time-lapse blame

Per-line changelist + author gutter, with a slider that re-blames the file at any point in history.

p4 changes

Changelists

Filter by user, path, text, or date — an incremental local index makes description and filename search fast.

p4 grep

Search

File-name search across depots and content search within a scope; matches jump to the highlighted line.

p4 labels …

Metadata browsers

Labels, jobs with fixes, branch mappings, streams, users & groups — all under one “More” menu.

app-side

Review touches

Rendered markdown with README panels, inline file/line comments with threads, image previews, raw download.

CL 65170
write ops

My Changes: edit and submit from the browser

Each user gets a server-side workspace (p4web-<user>) with sparse sync — files appear only while you work on them.

What you can do

  • Create pending changelists and edit text files in a web editor
  • Upload new or replacement files, binary-safe
  • Mark for delete, revert, shelve / unshelve
  • Submit behind a confirmation dialog showing the full file list

Guardrails

  • You can only touch your own p4-web pending changelists
  • Every write is recorded in data/audit.log
  • Login throttling per account and per IP; API rate limits per session
  • Perforce protections apply — the server never escalates
CL 65139
run.sh

Running in under a minute

One script creates the venv, installs two dependencies, and serves.

$ git clone https://github.com/neoocean/p4-web.git && cd p4-web
$ ./run.sh
# equivalent to:
$ python3 -m venv .venv
$ .venv/bin/pip install -r requirements.txt
$ .venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8080
# then open http://127.0.0.1:8080 and log in with a Perforce account

requires: Python 3.10+ · the p4 CLI on PATH · network access to your Perforce server

no git handy? download the source as a .zip

CL 65207
sec review

Security, the boring way

Reviewed end-to-end (code review, security audit, red team) with the write-up in the repo. The core boundaries:

  • Your ticket, your permissions. Every API call runs p4 with the session’s own user and ticket — Perforce protections apply exactly as in P4V.
  • No ticket leakage. P4TICKETS points at /dev/null for every subprocess; the server’s own tickets file can never authenticate a web user.
  • Passwords are never stored. Credentials are exchanged for a p4 login ticket; you can paste a ticket instead, Swarm-style.
  • Command allowlist. The p4 wrapper only permits known commands; write operations are confined to your own p4-web changelists and audited.
  • Hardened endpoints. Streamed raw downloads and bounded upload spooling (no 100 MB buffers), per-session rate limits, secure cookies, login throttling.
CL 65160
deploy

Deploy anywhere a shell runs

Sessions persist in SQLite (data/sessions.db), so restarts don’t log anyone out. For ssl: servers, P4WEB_AUTO_TRUST=1 accepts the fingerprint on first connect.

Docker

The image bundles the p4 CLI; sessions and SSL trust live on the /data volume.

docker compose up -d

macOS · launchd

Always-on local service via a LaunchAgent plist — pairs well with a tailnet.

launchctl load com.p4web.plist

Linux · systemd

A standard unit file; edit paths, enable, done.

systemctl enable --now p4web
CL 65141
handoff

Small enough to read

app/
  main.py      FastAPI routes: auth, browse, file, diff, annotate,
               changes, comments, workspace write ops
  p4.py        p4 CLI wrapper: -G marshal parsing, path escaping,
               command allowlist, error → HTTP mapping
  sessions.py  cookie sid → {user, ticket}, SQLite-backed
  index.py     per-user changelist search index (respects protections)
static/
  index.html   login screen + app shell
  app.js       hash-routed SPA — no framework, no build
  style.css    light + dark, responsive below 768px
  vendor/      highlight.js, marked, DOMPurify (offline)

The entire stack is one Python process and a directory of static files. If something breaks, the code that broke is short enough to read over coffee — and every feature maps to a p4 command you already know.