Activepieces community piece for gitmoot: actions that talk to a host gitmoot instance through its authenticated localhost HTTP bridge (gitmoot bridge serve).
MIT licensed. The repo root is
"private": trueso it is never published directly; the publishable package is assembled underdist/by the build (see Building and publishing), carries the MIT license, and matches the Activepieces community-piece layout. It has been validated end to end against a self-hosted Activepieces instance.
A TypeScript npm package that exports a single Activepieces piece (gitmoot) built with @activepieces/pieces-framework. It lets Activepieces flows drive a gitmoot instance running on the host:
| Action | Bridge endpoint | In → Out |
|---|---|---|
Run Pipeline (run_pipeline) |
POST /v1/pipelines/{name}/run |
pipeline_name, optional string-map payload → response containing run_id |
Get Run Status (get_run_status) |
GET /v1/runs/{id} |
run_id → response containing state and optional stages |
Recall Memory (recall_memory) |
POST /v1/memory/recall |
query, optional repo, agent, shared, limit → response containing entries |
Ask Agent (ask_agent) |
POST /v1/agents/{name}/ask |
agent, message, required repo → response containing job_id |
Get Job (get_job) |
GET /v1/jobs/{id} |
job_id → response containing state and optional result |
All requests carry Authorization: Bearer <bridge_token> and Accept: application/json; requests with a body also carry Content-Type: application/json. Non-2xx responses surface as typed errors: BridgeAuthError (401), BridgeConflictError (409), BridgeRateLimitError (429, with retryAfterSeconds when the bridge sends Retry-After), and GitmootBridgeError for everything else.
The exact action request/response mappings are:
run_pipelinerequirespipeline_nameand accepts an optionalpayload. A non-empty payload sends{"payload":{"<key>":"<value>"}}; an absent or empty payload sends no request body. Payload keys must match^[a-z][a-z0-9_]*$and be at most 64 bytes, values must be strings without NUL and at most 32 KiB, and the payload is limited to 32 entries and 48 KiB total. The parsed response is returned unchanged and containsrun_id; additional response fields are preserved.get_run_statusrequiresrun_idand sends no request body. The parsed response is returned unchanged and containsstate, with optionalstages; additional response fields are preserved.recall_memoryrequiresqueryand accepts optionalrepo,agent,shared, andlimit. It sends{"query":"<query>","repo":"<owner/name>","agent":"<agent>","shared":<boolean>,"limit":<number>}with unset optional fields omitted. The parsed response is returned unchanged and containsentries; additional response fields are preserved.ask_agentrequiresagent,message, andrepo. It sends{"message":"<message>","repo":"<owner/name>"}. The parsed response is returned unchanged and containsjob_id; additional response fields are preserved.get_jobrequiresjob_idand sends no request body. The parsed response is returned unchanged and containsstate, with optionalresult; additional response fields are preserved.
On the host, start the bridge and grab its token:
gitmoot bridge serveThe bridge listens on localhost (default port 8791) and writes a bearer token to its token file on startup. Every request must present that token.
Activepieces usually runs in Docker, while the bridge listens on the host's localhost. From inside a container use:
http://host.docker.internal:8791(Docker Desktop; on Linux add--add-host=host.docker.internal:host-gateway/extra_hosts: ["host.docker.internal:host-gateway"]), or- the docker bridge IP directly, e.g.
http://172.17.0.1:8791.
The piece uses Activepieces custom auth with two fields:
- Bridge URL (
bridge_url) — base URL of the bridge, defaults tohttp://host.docker.internal:8791. - Bridge Token (
bridge_token) — the bearer token from the bridge token file (stored as a secret).
This repo is a flat, standalone npm package (package.json at the root, src/index.ts entry) rather than the packages/pieces/community/<name> monorepo layout. Reason: the monorepo layout only matters when contributing a piece upstream into the activepieces/activepieces repo (where Nx drives builds and publishing). A self-hosted Activepieces instance installs community pieces by npm package name and loads the compiled entry point that exports the piece.
The build compiles TypeScript from src/ into a self-contained publishable package under dist/ whose layout matches an official Activepieces community piece: dist/package.json with main: "./src/index.js" and the compiled JS under dist/src/. Activepieces expects this src/index.js entry convention (both @activepieces/pieces-framework and every official piece publish with main: "./src/index.js"), so publishing dist/ — not the repo root — is what a self-hosted instance can install. dist/package.json is generated by scripts/prepare-package.mjs (drops private, dev deps, and scripts), which replaces the manual dist→src repack the first end-to-end run needed.
src/
index.ts # createPiece + exports
lib/
auth.ts # PieceAuth.CustomAuth (bridge_url, bridge_token)
common/client.ts # GitmootBridgeClient + typed errors
actions/ # one file per action
test/ # vitest + undici MockAgent unit tests
Requires Node 20 (see .nvmrc / engines).
npm install
npm test # vitest, all HTTP mocked with undici MockAgent — no bridge needed
npm run build # tsc → dist/src/ + generated dist/package.json (publishable layout)The tests cover the bearer/JSON headers, each action's request/response mapping, and the 401/409/429/other error typing. No test touches the network (MockAgent.disableNetConnect()).
npm run build produces the publishable package under dist/:
dist/
package.json # main: ./src/index.js, runtime deps only, not private
README.md
src/
index.js # compiled entry Activepieces loads
lib/...
Publish the built dist/ directory (never the repo root):
npm run publish:piece # npm run build && npm publish ./distPoint it at any registry the Activepieces instance can reach (npm, or a private/local one such as Verdaccio). Then install it into a self-hosted instance by npm package name (@gitmoot/piece-gitmoot) — via the Pieces admin UI or POST /api/v1/pieces { pieceName, pieceVersion, scope: "PLATFORM", packageType: "REGISTRY" }.
- Triggers (e.g. "run finished", "job completed", "new memory entry") are deliberately absent: the bridge currently exposes no list/watch endpoints to poll. Once the bridge grows list endpoints (
GET /v1/runs,GET /v1/jobs, ...), polling triggers can be added on top of this client. - Keep the request/response mappings above aligned with the bridge when its API contract changes.