Family · 9 packages, one product
FG

Fancy Git

PHP + Node / TypeScript + React · 9 packages

Git as a first-class, agent-driveable surface — a headless engine with proposal-first mutations, normalized provider adapters for GitHub / GitLab / Bitbucket, and a React UI. Mirrored in PHP and Node.

UI+ BackendPHP · Node / TypeScript · React
Browse 8 previews
Everything in this family ships against one shared contract — install only the pieces your stack needs. Language mirrors behave identically, so you pick your backend and get the same product.

Engine

2 packages · headless — install and call it · Local Git + GitHub / GitLab / Bitbucket collaboration

fancy-gitPHP Backend · renders no UI

Framework-agnostic PHP Git engine with normalized provider contracts and proposal-first mutations.

$composer require particle-academy/fancy-git
fancy-gitNode / TypeScript Backend · renders no UI

Node/TypeScript Git engine and normalized GitHub, GitLab, and Bitbucket provider contracts.

$npm install @particle-academy/fancy-git

React UI

1 package · component previews inside

feat/human-plus
+12
−3
fancy-git-uiReact UI surface 8 components

Controlled Human+ React surfaces for repositories, working trees, diffs, commits, branches, and pull/merge requests.

$npm install @particle-academy/fancy-git-ui

GitHub provider

2 packages · headless — install and call it · GitHub.com / GitHub Enterprise provider adapter

fancy-git-githubPHP Backend · renders no UI

GitHub.com and GitHub Enterprise adapter for particle-academy/fancy-git.

$composer require particle-academy/fancy-git-github
fancy-git-githubNode / TypeScript Backend · renders no UI

GitHub.com and GitHub Enterprise adapter for @particle-academy/fancy-git.

$npm install @particle-academy/fancy-git-github

GitLab provider

2 packages · headless — install and call it · GitLab.com / Self-Managed provider adapter

fancy-git-gitlabPHP Backend · renders no UI

GitLab.com and Self-Managed adapter for particle-academy/fancy-git.

$composer require particle-academy/fancy-git-gitlab
fancy-git-gitlabNode / TypeScript Backend · renders no UI

GitLab.com and GitLab Self-Managed adapter for @particle-academy/fancy-git.

$npm install @particle-academy/fancy-git-gitlab

Bitbucket provider

2 packages · headless — install and call it · Bitbucket Cloud provider adapter

fancy-git-bitbucketPHP Backend · renders no UI

Bitbucket Cloud adapter for particle-academy/fancy-git.

$composer require particle-academy/fancy-git-bitbucket
fancy-git-bitbucketNode / TypeScript Backend · renders no UI

Bitbucket Cloud adapter for @particle-academy/fancy-git.

$npm install @particle-academy/fancy-git-bitbucket
Why
Anything that automates Git ends up writing the same two layers twice. First a shell of exec('git status --porcelain') calls with hand-rolled parsing, which works until a path has a space in it or the porcelain format shifts. Then, separately, a REST client per host — because GitHub calls it a pull request, GitLab a merge request, and Bitbucket a pull request with an entirely different payload — so supporting a second host means writing the feature again. fancy-git is that work done once, in two languages: local operations over the installed git binary, and a provider-neutral contract for the hosted side, so one code path serves GitHub, GitLab and Bitbucket.

It is also built for Human+ UX, and that shows up as a design constraint rather than a feature: every mutation takes a propose flag. Called with it, the operation returns an OperationProposal describing exactly what it would run instead of running it. An agent can therefore stage, branch, or push through the same API a human uses, and a human confirms before anything touches the repository — trust-but-verify in the contract, not bolted on by the caller.
What
The family is nine packages in a deliberate shape: a matched PHP + TypeScript core, a React UI, and a per-host adapter pair.

The engineparticle-academy/fancy-git (PHP) and @particle-academy/fancy-git (TypeScript) are twins, not a port and an afterthought. Both expose a GitRepository over the installed binary: info(), status(), log(), diff(), branches(), and the mutations stage() / unstage() / checkout() / fetch() / pull() / push(), each taking that propose flag. Invocation goes through a process runner (Symfony Process on PHP), never a shell string, so a branch named --upload-pack=… is an argument rather than an injection.

The hosted contractGitProvider normalises the three hosts to one vocabulary: repository(), listReviews(), getReview(), createReview(), compare(), checks(). A pull request and a merge request are both a Review, with the host's extras preserved under extensions rather than flattened away. Adapters register on a ProviderRegistry, and identify() maps a remote URL back to the provider that owns it — so code written against the contract works on a host it has never seen.

The adapters — six packages, one pair per host: fancy-git-github-{php,js}, fancy-git-gitlab-{php,js}, fancy-git-bitbucket-{php,js}. You install only the hosts you actually talk to; the core carries no HTTP client for the other two.

The surface@particle-academy/fancy-git-ui ships eight controlled React components over that data: <RepositoryBrowser>, <WorkingTree>, <CommitHistory>, <DiffViewer>, <BranchPicker>, <ReviewList>, <CommitComposer> and <CreateReviewForm>. Every one is fully controlled and provider-neutral — it renders what you pass and emits intents, holding no Git state of its own, which is what lets an agent drive the same surface a person is looking at.
How
Pick the runtime that executes your workflow, then add the hosts you use. On PHP: composer require particle-academy/fancy-git particle-academy/fancy-git-github. On Node: npm install @particle-academy/fancy-git @particle-academy/fancy-git-github. The React surface is additional and orthogonal — npm install @particle-academy/fancy-git-ui — because a Laravel app still renders its editor in a browser.

Local operations read the same on both sides: $repository = new GitRepository(base_path()); $status = $repository->status(); in PHP, const status = await new GitRepository(process.cwd()).status() in TypeScript. To let an agent act without letting it act unsupervised, pass the flag: $repository->push(propose: true) returns an OperationProposal you can render for a human to approve, then re-run without it once they do.

For the hosted side, register the adapters you installed and let the remote choose: $registry = (new ProviderRegistry)->register(new GitHubProvider($token)); [$provider, $ref] = $registry->identify($remote); — from there $provider->listReviews($ref) is the same call whether that remote points at GitHub, GitLab or Bitbucket. And if you would rather drive all of this from a workflow than from code, the marketplace ships five PR-lifecycle nodes built on exactly this contract: npx fancy-cli@latest add node @particle-academy/git_pr_open.
readmeShared model & API — README.md

Fancy Git for PHP

Fancified

Framework-agnostic local Git operations and normalized provider contracts.

use FancyGit\GitRepository;

$repository = new GitRepository(getcwd());
$status = $repository->status();

The core uses Symfony Process for safe, portable invocation of the installed Git binary. GitHub, GitLab, and Bitbucket clients live in separate adapter packages.

What next
Open a surface and click any component for a live demo with source.