Forge
A portable local execution bridge for human-in-the-loop AI pair programming.
Forge lets an AI assistant work with code that lives in an environment the assistant cannot directly control.
The assistant writes a small plain-text Forge bundle. You run that bundle locally. Forge inspects, edits, executes, or recovers project files and returns a structured run packet describing exactly what happened.
The packet is ground truth.
The assistant proposes.
The user runs.
Forge reports.
The packet confirms.
Forge is pure Python. The portable runtime has no dependency on a particular IDE, clipboard, UI toolkit, shell, or operating-system integration.
The idea in 60 seconds
The basic loop is:
AI assistant
|
| Forge bundle
v
Portable Forge
|
| parse
| validate
| execute
| record
v
Canonical run packet
|
+----> human
|
+----> AI assistant
A host can wrap the two edges:
get bundle text
->
Forge
->
return rendered result
For example, a terminal can read a file and print the result. Pythonista can read from the clipboard and put the packet back on the clipboard. Another host could use a GUI, editor extension, web view, or custom transport.
The center stays portable.
Everything environment-specific lives at the edges.
What Forge is - and what it is not
Forge is not an autonomous coding agent.
It does not silently control your machine, upload your project, or require the assistant to have filesystem or shell access.
Forge is a local protocol and runtime.
The AI produces ordinary text. The user chooses whether to run it. Forge executes that text against an explicit project root and reports the result as deterministic text.
That makes Forge useful when:
- your AI assistant lives in a separate chat interface;
- your code is on a phone, tablet, embedded system, or unusual Python IDE;
- a full coding-agent integration is unavailable or undesirable;
- you want an explicit human approval step before local execution;
- you want each local action confirmed by an inspectable packet.
A first Forge loop
An assistant might send:
MAP .
DEPTH: 2
FORGE ops
Save the bundle to a file and run:
python -m forge bundle.txt
Forge returns something shaped like:
=== FORGE RUN ===
Run: 20260831_123456
Mode: dev
Status: APPLIED
Ops:
- APPLIED | MAP | . :: directory mapped
- APPLIED | FORGE | ? :: 15 public op(s)
=== PREVIEW ===
...
=== FORGE SUMMARY ===
Status: APPLIED
Ops: 2 applied - 0 skipped - 0 failed
Changed: 0 files
The assistant reads that packet before deciding what to do next.
Nothing changed merely because the assistant suggested it.
Quick start
Pythonista: one-copy install
For a clean Pythonista installation, create any temporary Python script, paste the following code into it, and run it once:
import urllib.request
url = (
'https://raw.githubusercontent.com/'
'jackatttack/Forge/v0.1.1/bootstrap/pythonista.py'
)
with urllib.request.urlopen(url) as response:
source = response.read()
exec(
compile(
source,
'forge_bootstrap.py',
'exec',
),
{
'__name__': '__main__',
'__file__': 'forge_bootstrap.py',
},
)
That is the whole bootstrap.
It downloads the Portable Forge installer, installs the runtime into:
~/Documents/site-packages-3
and creates:
~/Documents/forge_entry.py
On a first installation, the installer opens forge_entry.py in Pythonista so
it is ready to use. Existing or updated launchers are left in place without
being auto-opened.
Put a Forge bundle on the clipboard and run forge_entry.py.
1. Install from a checked-out repository
Portable Forge includes a standard-library-only installer:
python install.py --source .
The installer places the runtime packages into a Python package directory and keeps writable Forge state separate from the installed code.
2. Read the first-boot guide
Forge ships with a compact operating prompt for an AI assistant:
python -m forge --first-boot
At the beginning of a cold Forge session, give that text to the assistant.
It establishes the important rules:
- the returned packet is ground truth;
- inspect before editing;
- do not claim local changes without a returned packet;
- read errors and hints before retrying failures;
- orient to the real project and installed Forge language first.
3. Run a bundle
From a file:
python -m forge bundle.txt
From stdin:
python -m forge < bundle.txt
With an explicit project root:
python -m forge --project /path/to/project bundle.txt
The public Forge language
Portable Forge deliberately keeps its normal vocabulary small.
| Area | Operations |
|---|---|
| Forge itself | FORGE |
| Inspect | MAP, READ, SEARCH |
| Edit | WRITE, REPLACE, INSERT, DELETE, COPY |
| Execute and recover | RUN, DIFF, REVERT, BRANCH |
| Utilities | URL, ALIAS |
That is 15 public operations.
Ask the installed runtime for the current catalogue:
FORGE ops
Get help for one operation:
FORGE help WRITE
Get deeper help:
FORGE help WRITE full
Inspect all installed operations, including host-specific extensions:
FORGE ops all
Detailed syntax belongs to each operation's own help. The root README is not intended to duplicate the full command manual.
Typical working pattern
A good Forge session is inspect-first.
For example:
MAP path/to/area
SEARCH path/to/area FOR "thing_to_find"
READ path/to/file.py
REPLACE path/to/file.py::target
BEGIN_BODY
...
END_BODY
RUN relevant_test.py
DIFF current
The exact editing operation depends on the task.
Forge is designed around small grounded changes rather than broad speculative rewrites.
Three ways to use Forge
Standard terminal host
The terminal host is built in:
python -m forge bundle.txt
Standard Forge prints the canonical packet followed by a small human summary.
As a Python library
The core loop is deliberately small:
import forge
run = forge.run_text(
bundle,
project_root="/path/to/project",
)
result = forge.render_standard(run)
Forge does not care where bundle came from or what you do with result.
Through a host wrapper
A host can provide the two environment-specific edges:
bundle = get_bundle_text()
run = forge.run_text(
bundle,
project_root=PROJECT_ROOT,
)
result = forge.render_standard(run)
set_result_text(result)
get_bundle_text() and set_result_text() belong to the host.
The Forge runtime between them does not.
See examples/minimal_loop.py for the smallest complete example.
The packet is the contract
Forge separates execution from claims about execution.
A successful packet can prove that a file was read, changed, executed, or restored.
A failed packet is useful too. It records the failure rather than requiring the assistant to guess what happened.
The normal loop is:
propose
->
run
->
inspect packet
->
decide next action
That distinction is central to Forge.
Safety model
Forge is intentionally powerful enough to edit and execute project code, so its boundaries need to remain explicit.
The complete bundle is parsed first
Forge parses the full submitted bundle before executing operations.
A parser failure does not leave a half-parsed instruction stream.
Project boundaries are explicit
Project operations resolve against project_root.
Portable Forge does not silently discover a hidden working project inside its core.
Installed code and writable state are separate
The installed package can be treated as read-only.
Run history, aliases, branches, configuration, and other generated state live under a writable Forge home.
The standard host uses:
~/.forge
unless another location is supplied.
Mutations are observable
Successful editing operations report touched files and record recovery information where appropriate.
Use:
DIFF current
to inspect changes.
Use:
REVERT <run>
to restore project files from a stored Forge run.
Destructive scope matters
A precise ordinary DELETE expresses deletion intent directly.
Broader destructive scope, such as deleting every matching block with
ALL: yes, requires explicit confirmation.
Protected Forge internals may independently require confirmation.
Installer collisions are blocked
Portable Forge uses the Python package names:
forge
forge_core
forge_packages
The installer checks for namespace collisions before installation.
It refuses to overwrite unrecognised packages merely because they share those names.
--force can replace only an installation carrying Portable Forge's own
installer marker.
This protects existing Forge installations and unrelated Python packages from accidental replacement.
Failures are evidence
When a Forge run fails:
- read
ERRORS,HINTS, andPREVIEW; - identify the failed operation;
- follow the Forge hint when present;
- use
FORGE help <OP>when syntax is unclear; - inspect the relevant state;
- make the smallest correction;
- run again and inspect the new packet.
Do not guess Forge syntax after a failure.
See docs/SAFETY.md for the fuller model.
Portable core and host adapters
The central architectural rule is:
Adapters import Forge. Forge never imports adapters.
Portable Forge core does not import Pythonista UI modules, clipboard APIs, editors, terminal wrappers, or other platform adapters.
A host adapter may choose:
- how bundle text is obtained;
- what the project root is;
- where writable Forge state lives;
- what capabilities the environment exposes;
- where output is sent;
- whether richer presentation is available.
A host must not change Forge execution semantics or the meaning of the canonical packet.
See docs/HOST_ADAPTERS.md.
Environment and configuration
Forge separates persistent wishes from runtime truth.
Configuration describes defaults and preferences.
Environment context describes the resolved runtime:
- project root;
- writable Forge home;
- storage root;
- aliases path;
- host name;
- available capabilities.
The portable core consumes that explicit environment.
Environment detection belongs to the host.
Presentation
The portable baseline is intentionally simple:
forge.render_standard(run)
That produces:
canonical packet
+
small human summary
The canonical packet does not depend on a particular renderer.
A richer host can render the structured run however it wants:
import forge
from my_renderer import render
run = forge.run_text(
bundle,
project_root=PROJECT_ROOT,
)
render(run)
No large renderer framework is required.
Pythonista
Forge itself does not depend on Pythonista.
Pythonista is one example of a host environment.
The intended layout is:
writable Python package directory/
forge/
forge_core/
forge_packages/
~/Documents/forge_entry.py
The bootstrap helper:
bootstrap/pythonista.py
downloads the Portable Forge installer. The installer detects Pythonista,
installs the runtime into ~/Documents/site-packages-3, creates the small
~/Documents/forge_entry.py launcher, and opens it in the editor.
The launcher provides a clipboard-based workflow by default.
Clipboard behaviour is part of the Pythonista adapter, not part of Forge core.
Existing Forge installations
Pythonista can also contain older Forge layouts such as:
~/Documents/forge/
Installing another runtime with the same top-level Python namespaces can shadow the existing one.
The Pythonista bootstrap therefore checks for conflicting Forge namespaces and stops before installation when one is found.
Migration should be deliberate rather than silently replacing or shadowing an existing runtime.
See adapters/pythonista/ for the Pythonista-specific layer.
Installation options
Portable Forge supports multiple installation paths.
Standard-library installer
From a local checkout:
python install.py --source .
With an explicit package directory:
python install.py --source . --target /path/to/site-packages
From the stable v0.1.1 release:
python install.py --github jackatttack/Forge --ref v0.1.1
For deliberate testing of the current development branch:
python install.py --github jackatttack/Forge --ref main
The installer uses only the Python standard library.
Bootstrap
Some constrained Python environments make downloading or arranging an entire repository awkward.
A small environment bootstrap can download install.py and invoke it.
See bootstrap/.
Python packaging
Forge is packaged as the Python distribution:
portable-forge
Install it from PyPI with:
pip install portable-forge
The Python import remains:
import forge
The distribution is pure Python and the public package contains the portable
runtime packages forge, forge_core, and forge_packages.
Repository layout
.
|-- README.md
|-- install.py
|-- pyproject.toml
|
|-- forge/ public Python API and standard host
|-- forge_core/ portable execution runtime
|-- forge_packages/ Forge operation packages
|
|-- adapters/ environment-specific wrappers
|-- bootstrap/ environment bootstrap helpers
|-- docs/ architecture and usage documentation
|-- examples/ embedding examples
`-- renderers/ presentation notes and future richer renderers
Public Python API
The intended public API is small:
forge.run_text(...)
forge.render_standard(...)
forge.make_environment(...)
forge.standard_environment(...)
forge.first_boot_text()
Most users should not need to import forge_core directly.
See docs/EMBEDDING.md.
Design principles
Forge aims to stay:
- local-first;
- human-in-the-loop;
- pure Python;
- portable;
- inspectable;
- recoverable;
- text-protocol friendly;
- useful in constrained environments;
- understandable by the person who owns the code.
A host can become sophisticated.
The core should remain boring.
License
Forge is released under the MIT License. See LICENSE.
Project status
This repository is an early portable rebuild of Forge.
The portable release boundary is tested independently from the historical Pythonista-specific implementation.
The current baseline proves that Forge can:
- run with platform UI physically absent;
- run with clipboard integration physically absent;
- run with editor integration physically absent;
- install without pip;
- execute through a standard Python API;
- operate through a thin host wrapper;
- protect against conflicting Forge namespaces during installation;
- return deterministic packets suitable for a human/AI feedback loop.
The API, compatibility matrix, adapters, packaging, and presentation may still evolve before a stable 1.0 release.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file portable_forge-0.1.1.tar.gz.
File metadata
- Download URL: portable_forge-0.1.1.tar.gz
- Upload date:
- Size: 124.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d418a1e47a542fa7a425bf49463e0beaba1e8cdd24e4b117b834648330a8ef1
|
|
| MD5 |
d7c930f56b6006638d72d65610854c92
|
|
| BLAKE2b-256 |
72f95bff9a608a805f88e519c562bedb3ccc6bdf86391c2f8200183e47467e8f
|
Provenance
The following attestation bundles were made for portable_forge-0.1.1.tar.gz:
Publisher:
release.yml on jackatttack/Forge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
portable_forge-0.1.1.tar.gz -
Subject digest:
7d418a1e47a542fa7a425bf49463e0beaba1e8cdd24e4b117b834648330a8ef1 - Sigstore transparency entry: 2673112606
- Sigstore integration time:
-
Permalink:
jackatttack/Forge@8eb661b32d4f8efb60e89f28253293d6de382c79 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/jackatttack
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8eb661b32d4f8efb60e89f28253293d6de382c79 -
Trigger Event:
push
-
Statement type:
File details
Details for the file portable_forge-0.1.1-py3-none-any.whl.
File metadata
- Download URL: portable_forge-0.1.1-py3-none-any.whl
- Upload date:
- Size: 140.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bdc135d8f2f87d66fa2c60b48e71a6854c5666ee804e8703611fde278dbe92b3
|
|
| MD5 |
9242675aae1862e857703b52ff24c966
|
|
| BLAKE2b-256 |
5f81338afd8d05ebc7297ad3406ebf487efc2d180c5e2e15033628c604079d9a
|
Provenance
The following attestation bundles were made for portable_forge-0.1.1-py3-none-any.whl:
Publisher:
release.yml on jackatttack/Forge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
portable_forge-0.1.1-py3-none-any.whl -
Subject digest:
bdc135d8f2f87d66fa2c60b48e71a6854c5666ee804e8703611fde278dbe92b3 - Sigstore transparency entry: 2673112627
- Sigstore integration time:
-
Permalink:
jackatttack/Forge@8eb661b32d4f8efb60e89f28253293d6de382c79 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/jackatttack
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8eb661b32d4f8efb60e89f28253293d6de382c79 -
Trigger Event:
push
-
Statement type: