- Python 59.2%
- Go 31.6%
- Makefile 3.8%
- PowerShell 3%
- Batchfile 2.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
Some checks failed
Build GUI Linux AMD64 / Build GUI Linux AMD64 (push) Has been cancelled
Build GUI Linux ARM64 / Build GUI Linux ARM64 (push) Has been cancelled
Build GUI macOS / Build GUI macOS (amd64) (push) Has been cancelled
Build GUI macOS / Build GUI macOS (arm64) (push) Has been cancelled
Build GUI Windows AMD64 / Build GUI Windows AMD64 (push) Has been cancelled
Build Installer / Build Installer (linux-amd64) (push) Has been cancelled
Build Installer / Build Installer (windows-amd64) (push) Has been cancelled
Build Installer / Build Installer (linux-arm64) (push) Has been cancelled
Build Linux AMD64 / Build Linux AMD64 (push) Has been cancelled
Build Linux ARM64 / Build Linux ARM64 (push) Has been cancelled
Build macOS / Build macOS (amd64) (push) Has been cancelled
Build macOS / Build macOS (arm64) (push) Has been cancelled
Build Windows AMD64 / Build Windows AMD64 (push) Has been cancelled
Build Windows ARM64 / Build Windows ARM64 (push) Has been cancelled
Build Installer / Release Installer Binaries (push) Has been cancelled
Add "Append '-source-code' to cloned folder names" checkbox (default: on).
When unchecked:
- Cloned folder name matches repo name exactly (api-forge, not api-forge-source-code)
- Already-cloned detection (✅) checks for the plain folder name
- Existing clones list shows folders matching bare repo names instead
of filtering by -source-code suffix
CloneWorker: add add_suffix param, folder_name calculated accordingly
|
||
| .forgejo/workflows | ||
| .github/workflows | ||
| cmd | ||
| forgejo-installer | ||
| gui | ||
| internal | ||
| .gitignore | ||
| build.bat | ||
| build.ps1 | ||
| go.mod | ||
| LICENSE | ||
| main.go | ||
| Makefile | ||
| README.md | ||
forgejo-forge
Part of the Forge Suite by @dev-boffin-io
A self-contained Git forge management suite — supports Linux (systemd & proot/Termux), Windows (amd64 & arm64), and macOS (amd64 & arm64).
Platform → Binary Mapping
| Platform | Binary installed | Source |
|---|---|---|
| Linux (systemd / proot / Termux) | Forgejo | codeberg.org/forgejo/forgejo |
| Windows 10/11 (amd64, arm64) | Gitea | dl.gitea.com / github.com/go-gitea/gitea |
| macOS (amd64, arm64) | Forgejo | codeberg.org/forgejo/forgejo |
Why Gitea on Windows? Forgejo dropped Windows support in 2024. Gitea is Forgejo's upstream project, shares the same config format (
app.ini), CLI flags, and admin commands — soforgejo-forgeworks identically on both.
macOS support The CLI and
forgejo-maininstaller build and run on macOS (amd64/arm64) using the same generic, non-systemd code path as proot/Termux (~/forge-storage/forgejo/). The GUI requires a native PyInstaller build on macOS — see Build.
Binaries
| Binary | Description |
|---|---|
forgejo-forge |
CLI — setup, start, stop, restart, status, logs, email-setup, config, uninstall |
forgejo-main |
Installer — downloads Forgejo (Linux) or Gitea (Windows) |
forgejo-forge-gui |
PyQt6 GUI frontend for forgejo-forge — includes the ⬡ Git Manager tab |
Data Paths
| Mode | Config | Data |
|---|---|---|
| systemd (Linux) | /etc/forgejo/app.ini |
/var/lib/forgejo/ |
| proot (Termux/ARM) | ~/forge-storage/forgejo/custom/conf/app.ini |
~/forge-storage/forgejo/ |
| macOS | ~/forge-storage/forgejo/custom/conf/app.ini |
~/forge-storage/forgejo/ |
| Windows | %APPDATA%\forgejo-forge\custom\conf\app.ini |
%APPDATA%\forgejo-forge\ |
Quick Start — Windows
# 1. Install Gitea binary
# Downloads from dl.gitea.com → %LOCALAPPDATA%\Programs\gitea\gitea.exe
forgejo-main install
# 2. Add the printed directory to PATH, then restart your terminal
# 3. Verify
gitea --version
# 4. Setup
forgejo-forge setup --username admin --password yourpassword
# 5. Open browser → http://localhost:3000
# 6. Stop
forgejo-forge stop
# 7. Status
forgejo-forge status
# 8. Email (optional)
forgejo-forge email-setup `
--from git@yourdomain.com `
--user yourname@gmail.com `
--passwd "xxxx xxxx xxxx xxxx"
Auto-start on login: Task Scheduler → New Task → Trigger: At log on → Action:
forgejo-forge start
Quick Start — Linux
# 1. Install Forgejo binary
forgejo-main install
# 2. Setup (proot / Termux)
forgejo-forge setup --username admin --password yourpassword
# 3. Production (systemd, requires sudo)
sudo forgejo-forge setup --username admin --password yourpassword
# 4. Email
forgejo-forge email-setup \
--from git@yourdomain.com \
--user yourname@gmail.com \
--passwd "xxxx xxxx xxxx xxxx"
# 5. Open GUI
forgejo-forge-gui
Quick Start — macOS
# 1. Install Forgejo binary → ~/forge-storage/forgejo/bin/forgejo
forgejo-main install
# 2. Setup
forgejo-forge setup --username admin --password yourpassword
# 3. Open browser → http://localhost:3000
# 4. Stop / status / logs
forgejo-forge stop
forgejo-forge status
forgejo-forge logs -f
# 5. Email (optional)
forgejo-forge email-setup \
--from git@yourdomain.com \
--user yourname@gmail.com \
--passwd "xxxx xxxx xxxx xxxx"
Auto-start on login:
launchd— create aLaunchAgentplist that runsforgejo-forge startat login.
forgejo-main — Binary Installer
Auto-detects OS and downloads the correct binary.
| OS | Binary | Download source |
|---|---|---|
| Linux amd64 | forgejo |
codeberg.org |
| Linux arm64 | forgejo |
codeberg.org |
| Linux arm | forgejo |
codeberg.org |
| macOS amd64 | forgejo |
codeberg.org |
| macOS arm64 | forgejo |
codeberg.org |
| Windows amd64 | gitea.exe |
dl.gitea.com |
| Windows arm64 | gitea.exe |
dl.gitea.com |
Install locations:
| OS | Path |
|---|---|
| Linux | /usr/local/bin/forgejo |
| macOS | ~/forge-storage/forgejo/bin/forgejo |
| Windows | %LOCALAPPDATA%\Programs\gitea\gitea.exe |
forgejo-main install # Download and install latest binary
forgejo-main update # Check and upgrade to latest version
forgejo-main upgrade # Same as update
forgejo-main uninstall # Remove the binary
forgejo-forge CLI
forgejo-forge setup [--username] [--password] [--email] [--port] [--domain] [--actions] [--push-create]
forgejo-forge start
forgejo-forge stop
forgejo-forge restart
forgejo-forge status
forgejo-forge logs [-f] [-n <lines>]
forgejo-forge email-setup [--from] [--user] [--passwd] [--smtp-addr] [--smtp-port] [--protocol]
forgejo-forge config path | sections | list | get | set | remove | raw-get | raw-set | enable-actions | enable-push-create
forgejo-forge uninstall
Auto-detects mode on every run:
- systemd — Linux with systemd; uses
/etc/forgejo/and/var/lib/forgejo/ - proot — Linux without systemd (Termux/ARM) or macOS; uses
~/forge-storage/forgejo/ - windows — Windows; uses
%APPDATA%\forgejo-forge\; process tracked via PID file
setup flags
| Flag | Default | Description |
|---|---|---|
--username |
admin |
Admin username |
--password |
(required) | Admin password |
--email |
<username>@example.com |
Admin email |
--port |
3000 |
HTTP port (auto-increments if busy) |
--domain |
— | Custom domain for ROOT_URL |
--actions |
true |
Enable Forgejo Actions (CI/CD) + local artifact storage in app.ini |
--push-create |
true |
Enable push-to-create for users and orgs (ENABLE_PUSH_CREATE_USER, ENABLE_PUSH_CREATE_ORG) |
email-setup flags
| Flag | Default | Description |
|---|---|---|
--from |
(required) | Sender address |
--user |
(required) | SMTP login |
--passwd |
(required) | SMTP password or App Password |
--smtp-addr |
smtp.gmail.com |
SMTP server |
--smtp-port |
465 |
SMTP port |
--protocol |
smtps |
smtps or smtp (STARTTLS) |
Config (app.ini)
forgejo-forge config reads and edits the app.ini written by setup, without needing to know which mode (systemd/proot/Windows) is active — it resolves the same path setup would use.
forgejo-forge config path # print resolved app.ini path
forgejo-forge config sections # list all [section] names
forgejo-forge config list <section> # list key=value pairs in a section
forgejo-forge config get <section> <key> # print one value
forgejo-forge config set <section> <key> <value> # set/add a key (creates section if needed)
forgejo-forge config remove <section> <key> # remove a key (drops section if it becomes empty)
forgejo-forge config raw-get # print the entire app.ini
forgejo-forge config raw-set # replace app.ini from stdin (writes app.ini.bak first)
forgejo-forge config enable-actions # enable [actions] + [actions.artifacts] on an existing install
forgejo-forge config enable-push-create # enable push-to-create for users and orgs on an existing install
set/remove/raw-set/enable-actions don't restart Forgejo automatically — run forgejo-forge restart afterwards for changes to take effect.
enable-actions is the same logic as setup --actions, but for an install that's already configured — it writes:
[actions]
ENABLED = true
[actions.artifacts]
STORAGE_TYPE = local
PATH = <data-dir>/artifacts
The GUI exposes this as 📝 Edit app.ini (full editor with syntax highlighting + warnings for duplicate sections / malformed lines) and Apply Now next to the Actions checkbox (runs
config enable-actionswithout re-running setup).
enable-push-create writes:
[repository]
ENABLE_PUSH_CREATE_USER = true
ENABLE_PUSH_CREATE_ORG = true
This lets users and org members create a new repository by simply pushing to a non-existent remote — no need to create it in the UI first. Enabled by default on fresh setup runs. For existing installs, run forgejo-forge config enable-push-create then forgejo-forge restart.
Forge Git Manager
The ⬡ Git tab inside forgejo-forge-gui embeds Forge Git Manager — a standalone multi-tab Git workflow GUI designed to work alongside Forgejo.
Click ⬡ Open Git Manager to launch it as a separate window. It runs inside the same Python process and shares the same Qt event loop — no extra install, no extra binary.
Tabs
| Tab | What it does |
|---|---|
| ⚙️ Git Binary | Auto-detect installed git; install via package manager if missing; shows path + version |
| 📦 Extractor | Scan a folder for bare .git repos; select one or more; extract a source ZIP for each |
| 📄 Gitignore | Generate a .gitignore by picking from language/framework templates (Python, Go, Node, etc.) — single or combined |
| 🔧 Git Init | git init a directory; optionally set the default branch name; equivalent to git init.sh |
| 🔗 Git Remote | Add or replace origin remote on an existing repo (git remote add / set-url) |
| ⬆️ Git Push | Stage all → commit with message → push to origin; handles first-push (--set-upstream) automatically |
| 📥 Source Clone | Clone any repo URL into a chosen local directory; supports SSH and HTTPS |
Typical workflow
Git Binary → verify / install git
Git Init → initialise repo in your project folder
Gitignore → generate and write .gitignore
Git Remote → point origin at your Forgejo instance
Git Push → stage + commit + push
Package layout
forge_git_manager lives at gui/forge_git_manager/ and is imported lazily on first click — it does not add any startup cost to forgejo-forge-gui.
gui/forge_git_manager/
├── app.py # ForgeGitManagerApp (QWidget) — main window, all tabs
├── theme.py # Slate-900 / amber accent stylesheet (scoped to the window)
├── workers.py # QThread workers: GitInitWorker, GitPushWorker, CloneWorker, …
├── git_config.py # git binary detection, Termux / proot / root helpers
├── gitignore_templates.py # built-in template library (~30 languages / frameworks)
└── __init__.py
Standalone use:
forge_git_managercan also be run on its own —python -m forge_git_manager— from inside thegui/directory.
Runner (CI / Forgejo Actions)
forgejo-forge runner manages a forgejo-runner / gitea-runner instance — the agent that picks up Forgejo Actions / CI jobs.
forgejo-forge runner install # download + install
forgejo-forge runner register --url <URL> --token <TOKEN> \
--uuid <UUID> --name <NAME> \
--labels ubuntu-latest:host \
[--clean]
forgejo-forge runner start
forgejo-forge runner stop
forgejo-forge runner status
forgejo-forge runner uninstall
| OS | Binary | Download source |
|---|---|---|
| Linux | forgejo-runner |
code.forgejo.org / data.forgejo.org |
| Windows / macOS | gitea-runner |
gitea.com/gitea/runner |
register flags
| Flag | Default | Description |
|---|---|---|
--url |
(required) | Forgejo/Gitea instance URL |
--token |
(required) | Registration token from Settings → Actions → Runners → Create new runner |
--uuid |
— | UUID shown on the same "Create new runner" page — use this for a clean first-time registration |
--name |
hostname | Runner display name |
--labels |
ubuntu-latest:host |
Comma-separated labels. :host runs jobs directly (no Docker required) |
--clean |
false |
Discard existing config.yml / .runner and start fresh |
--runner-bin |
auto-detect | Override path to the runner binary |
First-time registration: copy both the UUID and Token from the "Create new runner" page and pass both
--uuidand--token. A registration token binds to whatever UUID is first used with it — re-registering with a different (random) UUID while reusing the same token causesunauthenticated: unregistered runner.register(without--uuid) re-uses whatever UUID is already inconfig.yml, so it's safe to re-run.
Docker not available? (e.g. Termux/proot) Use
:hostlabels (the default) — jobs run directly on the host shell instead of inside a container.
Config lives at ~/.config/forgejo-runner/config.yml (Linux/macOS) — same data-path convention as Forgejo itself.
Windows-specific Notes
Process management
Forgejo-forge tracks Gitea via %APPDATA%\forgejo-forge\forgejo.pid.
stop/restart use this PID; if missing, falls back to taskkill /IM gitea.exe.
Logs
Pure-Go log reader (no tail needed). Follow mode polls every 500ms.
Firewall
Windows Firewall may prompt to allow Gitea network access on first start — allow it.
Auto-start (Task Scheduler)
# Run as Administrator once:
$action = New-ScheduledTaskAction -Execute "forgejo-forge.exe" -Argument "start"
$trigger = New-ScheduledTaskTrigger -AtLogOn
Register-ScheduledTask -TaskName "ForgejoForge" -Action $action -Trigger $trigger -RunLevel Highest
Build
Linux (native)
sudo apt install golang python3-venv
make all
make install && make install-installer
Cross-compile Windows from Linux
make build-windows # bin/forgejo-forge-windows-amd64.exe
make build-windows-arm64 # bin/forgejo-forge-windows-arm64.exe
make installer-windows # bin/forgejo-main-windows-amd64.exe
make installer-windows-arm64 # bin/forgejo-main-windows-arm64.exe
Windows native (requires Go)
go build -o bin\forgejo-forge.exe .
cd forgejo-installer && go build -o ..\bin\forgejo-main.exe .
Cross-compile macOS from Linux
GOOS=darwin GOARCH=amd64 go build -o bin/forgejo-forge-darwin-amd64 .
GOOS=darwin GOARCH=arm64 go build -o bin/forgejo-forge-darwin-arm64 .
cd forgejo-installer
GOOS=darwin GOARCH=amd64 go build -o ../bin/forgejo-main-darwin-amd64 .
GOOS=darwin GOARCH=arm64 go build -o ../bin/forgejo-main-darwin-arm64 .
macOS native (requires Go + Python)
brew install go python3
make all
make install && make install-installer && make install-gui
GUI on macOS: PyInstaller does not cross-compile — the
.app/binary for macOS must be built on an actual Mac (or a macOS CI runner).make gui-buildworks the same way as on Linux once run on macOS.
CI (GitHub / Forgejo Actions)
| Workflow | Builds |
|---|---|
build-linux-amd64.yml / build-linux-arm64.yml |
CLI + installer (Linux) |
build-windows-amd64.yml / build-windows-arm64.yml |
CLI + installer (Windows) |
build-macos.yml |
CLI + installer (macOS, cross-compiled) |
build-gui-linux-amd64.yml / build-gui-linux-arm64.yml |
GUI (Linux) |
build-gui-windows-amd64.yml |
GUI (Windows) |
build-gui-macos.yml |
GUI (macOS) — requires macos-latest / macos-13 GitHub-hosted runners; will hang on self-hosted-only runner setups that lack macOS runners |
build-installer.yml |
Installer-only build matrix |
Forgejo self-hosted runner compatibility:
.forgejo/workflows/pinsactions/upload-artifact(andbuild-installer.yml'sdownload-artifact) to@v3—@v4hard-fails on Forgejo/Gitea withGHESNotSupportedErrorsince it only talks to github.com's artifact API..github/workflows/uses@v4instead, since GitHub.com auto-fails any job that still uses the now-deprecated@v3artifact actions. The GUI workflows additionally tryactions/setup-python@v5first and fall back to whateverpython3/pythonis already on the runner if that action fails (common on Forgejo self-hosted ARM64/proot runners, which can't resolve the GitHub-hosted Python version manifest).Release action differs by platform — workflows are duplicated in two folders:
.github/workflows/usessoftprops/action-gh-release(works on real GitHub.com, fails on Forgejo since it requires a direct clone from github.com)..forgejo/workflows/usesactions/forgejo-release(resolved through Forgejo'sdata.forgejo.orgaction mirror, works on self-hosted Forgejo, doesn't exist on github.com). Forgejo ignores.github/workflows/entirely whenever a.forgejo/workflows/folder is present, and GitHub ignores.forgejo/workflows/entirely — so each platform only ever sees its own correct copy, with no duplicate runs. If you change a workflow, update both copies.
Project Structure
forgejo-forge/
├── main.go
├── cmd/ # CLI subcommands (setup/start/stop/restart/status/logs/email/config/uninstall)
│ ├── config.go # config path/sections/list/get/set/remove/raw-get/raw-set/enable-actions
│ ├── runner.go # runner install/register/start/stop/status/uninstall
│ ├── runner_sysproc_unix.go # detached-process attrs (Linux/macOS)
│ └── runner_sysproc_windows.go # detached-process attrs (Windows)
├── internal/
│ ├── admin/create.go # admin user create (Forgejo & Gitea compatible)
│ ├── config/ # app.ini writer, reader, mailer patcher, editor (set/remove/list key=value)
│ ├── detect/env.go # mode detection; ForgejoBin() → gitea.exe on Windows
│ ├── netutil/ # port detection, LAN IP, cloudflared
│ ├── runner/ # process management (GITEA_WORK_DIR on Windows)
│ └── svc/ # paths, status, uninstall
├── forgejo-installer/ # forgejo-main sub-project
│ └── internal/
│ ├── arch/arch.go # Linux→Forgejo, Windows→Gitea routing
│ ├── download/ # dual-source downloader (Codeberg / dl.gitea.com)
│ ├── install/ # install/uninstall binary
│ └── version/ # version fetch (Codeberg API / GitHub API)
├── gui/ # PyQt6 GUI
│ ├── forgejo-forge.py # entry point (unchanged — Makefile + CI use this path)
│ ├── requirements.txt
│ ├── forgejo-forge.png # app icon
│ ├── forge/ # forgejo-forge GUI package
│ │ ├── constants.py # Catppuccin Mocha colors, Qt stylesheet, app constants
│ │ ├── mainwindow.py # ForgejoForgeGUI — main window + all slot logic
│ │ ├── dialogs/
│ │ │ └── ini_editor.py # IniSyntaxHighlighter + IniEditorDialog
│ │ ├── tabs/ # one file per tab
│ │ │ ├── setup.py # ⚙ Setup (credentials, port, domain, actions, push-create)
│ │ │ ├── control.py # ▶ Control (start / stop / restart / uninstall)
│ │ │ ├── email.py # 📧 Email / SMTP config
│ │ │ ├── runner.py # 🏃 Runner (install, register, start, stop, status)
│ │ │ ├── logs.py # 📄 Log viewer (follow mode, line cap)
│ │ │ ├── binary.py # 🔧 Binary detect, path override, install/update
│ │ │ └── git_manager.py # ⬡ Git Manager launcher tab
│ │ ├── workers/
│ │ │ ├── base.py # CommandWorker, InstallerWorker, LogFollowWorker
│ │ │ └── binary_check.py # BinaryCheckWorker (version detect + upstream API)
│ │ └── utils/
│ │ ├── binary.py # find_binary(), find_installer_binary(), screen_aware_size()
│ │ └── ansi.py # strip_ansi()
│ └── forge_git_manager/ # Forge Git Manager (embedded, also runnable standalone)
│ ├── app.py # ForgeGitManagerApp — main window, all 7 tabs
│ ├── theme.py # slate-900 / amber stylesheet (scoped to window only)
│ ├── workers.py # QThread workers (git init, push, clone, extractor, …)
│ ├── git_config.py # git binary detection, Termux / proot / root helpers
│ ├── gitignore_templates.py # ~30 built-in language/framework templates
│ └── __init__.py
└── Makefile
License
MIT License — see LICENSE