Skip to content

How to install fullsend

This guide walks through installing fullsend for a GitHub organization or a single repository.

Choose your installation mode

Before running any install commands, decide whether you need per-org or per-repo mode:

ModeCommand formatBest forCreates .fullsend repo?
Per-orgfullsend admin install ORGOrgs where one admin manages fullsend for all reposYes
Per-repofullsend admin install ORG/REPOTeams in shared orgs, single-repo onboarding, independent setupsNo

Use per-repo mode if any of these apply:

  • Multiple independent teams share the same GitHub organization
  • You only want fullsend on specific repositories without org-wide configuration
  • You do not have (or do not want to use) org-level admin access

→ Skip to Per-repo installation

Use per-org mode if:

  • A single admin manages fullsend across the entire organization
  • You want centralized configuration via the .fullsend config repo
  • You plan to enroll many repositories under unified management

→ Continue below to choose your setup path

Choose your setup path

Your setup path depends on what GCP infrastructure is already in place and how much control you need. Most users follow the end-user path — your organization is enrolled in a hosted mint service, and you provision inference access and configure GitHub yourself. This is the fastest way to get started.

PathWhen to useWhat you need
End-user setupMint service is hosted for you (most common)GCP project for inference + GitHub org access
GitHub-only setupBoth GCP inference and mint are pre-provisionedGitHub org access + GCP config values from your admin (no GCP credentials needed)
All-in-one admin installYou manage everything — GCP mint, inference, and GitHubFull GCP + GitHub access

Mint service note: The token mint is fully self-hostable, but most users currently use the mint service hosted by the fullsend team. Work is in progress to offer this as a secure, trusted public service — reducing the need for per-org enrollment. See Mint service administration for GCF-based self-hosting, or Standalone mint for running a mint without GCP infrastructure.


End-user setup

This is the standard path for organizations using a hosted mint service. You provision GCP inference access and configure GitHub — the mint service admin handles enrollment.

Prerequisites

  • From your mint service admin: Before starting, confirm that your organization is enrolled in the hosted mint and obtain the token mint URL (the HTTPS endpoint for OIDC token exchange). This is a blocking prerequisite — contact your mint admin first.

  • GitHub organization with admin access

  • GitHub CLI (gh) authenticated — no special scopes are needed upfront. The installer runs a preflight check and tells you exactly which scopes are missing before making any changes. When prompted, run the gh auth refresh -s <scopes> command it suggests.

    Note on scope breadth: gh auth scopes apply to every organization your account belongs to — GitHub does not support per-org scoping for classic OAuth tokens. If that is a concern, create a fine-grained personal access token scoped to the target organization and export it as GH_TOKEN before running the installer.

  • fullsend CLI — download the latest binary from GitHub Releases

  • GCP project with the following APIs enabled:

    bash
    gcloud services enable \
      iam.googleapis.com \
      cloudresourcemanager.googleapis.com \
      aiplatform.googleapis.com \
      --project="$GCP_PROJECT"
  • GCP IAM roles for inference provisioning — the user authenticates via ADC (gcloud auth application-default login) and needs:

    RoleWhat it covers
    roles/iam.workloadIdentityPoolAdminCreate WIF pool and provider for GitHub Actions OIDC authentication
    roles/resourcemanager.projectIamAdminGrant roles/aiplatform.user to WIF principals via project IAM policy

    An administrator can grant the required roles:

    bash
    export GCP_PROJECT="my-project-id"
    export USER_EMAIL="alice@example.com"
    
    for ROLE in \
      roles/iam.workloadIdentityPoolAdmin \
      roles/resourcemanager.projectIamAdmin; do
      gcloud projects add-iam-policy-binding "$GCP_PROJECT" \
        --member="user:$USER_EMAIL" \
        --role="$ROLE"
    done

Step 1: Request mint enrollment

Contact your mint service admin and request enrollment for your GitHub organization. They will run fullsend mint enroll <your-org> on the mint project (see Mint service administration). Once enrolled, they will provide you with the mint URL.

Step 2: Provision inference access

Provision Workload Identity Federation (WIF) infrastructure and grant Agent Platform access in your GCP project:

bash
export ORG_NAME="<your-github-org>"
export GCP_PROJECT="<your-gcp-project>"

fullsend inference provision "$ORG_NAME" \
  --project "$GCP_PROJECT"

This creates a WIF pool (fullsend-inference), an OIDC provider (github-oidc), and grants roles/aiplatform.user to the WIF principal — allowing GitHub Actions workflows to authenticate and call Agent Platform models. The command is idempotent and safe to re-run.

Note the WIF provider resource name printed by the command — you will need it for the next step.

Step 3: Set up GitHub

Configure your GitHub organization with the mint URL and inference settings:

bash
fullsend github setup "$ORG_NAME" \
  --mint-url="<MINT_URL>" \
  --inference-project "$GCP_PROJECT" \
  --inference-wif-provider "<WIF_PROVIDER_FROM_STEP_2>"

This creates the .fullsend config repository, installs GitHub Apps (opens browser windows for each agent role), configures org-level variables and secrets, and prompts you to enroll repositories.

The --inference-region flag defaults to global for the broadest model availability. For a list of all available regions, see the Agent Platform documentation.

See Setting up with pre-provisioned infrastructure for the full github setup reference, including per-repo mode, --skip-app-setup, and day-2 operations.

Scaffold delivery: The installer creates a PR with the scaffold files by default. Merge the scaffold PR to complete setup. If you prefer to push scaffold files directly to the default branch (e.g., for automation), pass --direct to skip PR creation — the installer will fall back to a PR automatically if branch protection blocks the direct push.

Step 4: Merge enrollment PRs

If you enrolled repositories during setup, the installer dispatches a workflow that creates an enrollment PR in each enrolled repo. These PRs add a shim workflow (.github/workflows/fullsend.yaml) that wires events to the agent pipeline.

Review and merge each enrollment PR to complete enrollment.

Step 5: Test the pipeline

Once a repo is enrolled (enrollment PR merged):

  1. Create an issue in the enrolled repo
  2. The triage agent picks it up automatically — check the Actions tab in both the target repo and .fullsend for workflow run logs

All-in-one admin install

For administrators who manage both GCP infrastructure and GitHub configuration, fullsend admin install provisions everything in a single command: token mint, inference WIF, GitHub Apps, and repository enrollment.

Additional prerequisites

All prerequisites from the end-user setup above, plus:

  • GCP project with the following additional APIs enabled (for the token mint):

    bash
    gcloud services enable \
      cloudfunctions.googleapis.com \
      run.googleapis.com \
      secretmanager.googleapis.com \
      iamcredentials.googleapis.com \
      --project="$GCP_PROJECT"

    Note: iamcredentials.googleapis.com is a runtime dependency — the deployed mint Cloud Function uses it for WIF token exchange, not the CLI itself. It must be enabled before deployment.

  • GCP IAM roles — the full set required for both mint and inference:

    RoleWhat it covers
    roles/iam.workloadIdentityPoolAdminCreate, read, update, and undelete WIF pools and providers
    roles/iam.serviceAccountAdminCreate the fullsend-mint service account
    roles/resourcemanager.projectIamAdminRead and set project-level IAM policy (grants roles/aiplatform.user to WIF principals)
    roles/secretmanager.adminCreate secrets, add versions, read and set secret-level IAM policy
    roles/cloudfunctions.developerDeploy, update, and inspect the mint Cloud Function
    roles/run.adminRead and set Cloud Run IAM policy (sets allUsers as invoker)

    roles/owner covers all of the above for users with broad access.

    An administrator with elevated access to the GCP project can grant all required roles with a single script:

    bash
    export GCP_PROJECT="my-project-id"    # target GCP project
    export USER_EMAIL="alice@example.com" # email of the user who will run the installer
    
    for ROLE in \
      roles/iam.workloadIdentityPoolAdmin \
      roles/iam.serviceAccountAdmin \
      roles/resourcemanager.projectIamAdmin \
      roles/secretmanager.admin \
      roles/cloudfunctions.developer \
      roles/run.admin; do
      gcloud projects add-iam-policy-binding "$GCP_PROJECT" \
        --member="user:$USER_EMAIL" \
        --role="$ROLE"
    done

    Reducing required roles: If you supply --inference-wif-provider with a pre-existing WIF provider, roles/iam.workloadIdentityPoolAdmin is not needed. If you supply --skip-mint-check with --mint-url and --inference-wif-provider, no GCP roles are needed (all GCP provisioning is skipped). Without --inference-wif-provider, inference WIF auto-provisioning still requires roles/iam.workloadIdentityPoolAdmin and roles/resourcemanager.projectIamAdmin.

OAuth scope reference

The table below lists every scope the installer may request and why. You are never asked for all of them at once — the preflight check requests only the scopes needed for the operation you are running.

ScopeWhen neededWhy
repoinstall, analyzeRead/write repository contents, manage repo-level secrets and variables
workflowinstallCreate and update GitHub Actions workflow files in .github/workflows/
admin:orginstall (per-org), uninstall, analyzeManage organization-level Actions variables and app installations
delete_repouninstallDelete the .fullsend config repository

Per-repo scope note: Per-repo install (fullsend admin install <owner/repo>) only requires repo and workflow when reusing existing GitHub Apps. Creating new apps requires admin:org.

Run the installer

The installer is interactive. It will open multiple browser windows to create and install a GitHub App for each agent role. Follow the prompts in each window to complete the app setup.

During installation, you'll be prompted to choose repository enrollment:

  • [a] Enroll all repositories — immediately enrolls all org repos (excluding .fullsend)
  • [n] Enroll no repositories — skip enrollment during install; enroll repositories later using fullsend admin enable repos

The installer creates the .fullsend config repo as public by default. This is required for cross-repo workflow_call to work with enrolled repos of any visibility (public, private, or internal) across all GitHub plan tiers. If an admin later makes .fullsend private, only other private repos in the org will be able to trigger agent workflows — public and internal repos will fail silently.

The installer creates a PR with the scaffold files by default. Merge the scaffold PR to complete setup. Pass --direct to push scaffold files directly instead; the installer will fall back to a PR automatically if branch protection blocks the direct push.

If the installer fails partway through, run fullsend admin uninstall "$ORG_NAME" to clean up before retrying. The uninstall preflight will prompt you to add the delete_repo scope if it is missing.

Set the variables for your environment:

bash
export ORG_NAME="<your-github-org>"
export GCP_PROJECT="<your-gcp-project>"

Then run the installer:

bash
fullsend admin install "$ORG_NAME" \
  --inference-project "$GCP_PROJECT" \
  --mint-project "$GCP_PROJECT"

The installer automatically provisions Workload Identity Federation (WIF) infrastructure (pool fullsend-inference, provider github-oidc, IAM bindings) in the inference project. WIF eliminates long-lived credentials — GitHub Actions exchange short-lived OIDC tokens for GCP access tokens. To use a pre-existing WIF provider instead, pass --inference-wif-provider "$WIF_PROVIDER" with the full resource name (projects/{number}/locations/global/workloadIdentityPools/{pool}/providers/{id}) — the CLI validates the format and skips auto-provisioning (see Advanced: pre-configure WIF below).

--mint-project specifies the GCP project where the OIDC token mint Cloud Function is deployed. It can be the same project as --inference-project or a separate project. The installer automatically provisions a Cloud Function, WIF pool (fullsend-pool), WIF provider (github-oidc), and Secret Manager secrets in the mint project. A service account (fullsend-mint) is also created as the Cloud Function's runtime identity to access Secret Manager — this is internal infrastructure and does not require any admin setup.

admin install flags

FlagDefaultDescription
--agentsfullsend,triage,coder,review,retro,prioritizeComma-separated agent roles to provision
--dry-runfalsePreview changes without making them
--inference-projectGCP project ID for inference (Agent Platform)
--inference-regionglobalGCP region for inference
--inference-wif-providerFull WIF provider resource name (projects/{number}/locations/global/.../providers/{id}); skips auto-provisioning when set
--mint-projectGCP project for the token mint Cloud Function
--mint-regionus-central1Cloud region for the token mint function
--mint-urlUse an existing mint at this URL instead of deploying one
--mint-providergcfToken mint provider backend
--mint-source-dirinternal/mint/Path to mint function source directory. The mint consists of two modules (internal/mint/ and internal/mintcore/); the provisioner bundles mintcore from the sibling directory automatically. When the path does not exist (e.g., running from a downloaded binary), the embedded source baked into the binary is used instead
--publicfalseCreate public unlisted GitHub Apps (for multi-org)
--app-setfullsend-aiApp set name prefix for GitHub Apps (see Custom app sets)
--skip-app-setupfalseSkip GitHub App creation (reuse existing apps)
--skip-mint-deployfalseSkip Cloud Function deployment, reuse existing mint URL
--skip-mint-checkfalseSkip mint validation, GCP provisioning, and app setup; requires --mint-url
--enroll-allfalseEnroll all repositories without prompting (per-org only)
--enroll-nonefalseSkip repository enrollment without prompting (per-org only)
--vendorfalseVendor binary, reusable workflows, actions, and agent content (see Vendored vs layered installs)
--fullsend-sourceFullsend source checkout for content walks and binary cross-compile (requires --vendor)
--fullsend-binaryPath to a Linux fullsend binary to upload when --vendor is set (skips auto-resolution)
--directfalsePush scaffold files directly to the default branch instead of creating a PR (falls back to PR if branch protection blocks the push)

The --skip-mint-check flag bypasses all mint validation, GCP provisioning, and app setup. It requires --mint-url to be set and only validates that the URL uses HTTPS. This is useful when the mint infrastructure is managed externally or you want to skip GCP API calls entirely.

The installer automatically detects when the deployed mint function is up-to-date (same source hash) and skips code redeployment, only updating WIF infrastructure and org registration. Use --skip-mint-deploy to explicitly skip the Cloud Function deployment step.

Multi-org setup

A single token mint can serve multiple GitHub organizations. See Mint service administration — Multi-org setup for the complete multi-org workflow.

Vendored vs layered installs

Layered (default): Thin caller workflows reference upstream reusable workflows at fullsend-ai/fullsend@v0. At runtime, reusables sparse-checkout upstream into .defaults/ and copy agent content to the workspace root. No distribution settings in config.yaml.

Vendored (--vendor): Install commits a linux/amd64 binary plus reusable workflows and an upstream mirror under .defaults/ (same layout as the runtime checkout). Thin callers use local ./... paths. Runtime skips the upstream fetch when .defaults/action.yml is already present.

Source resolution (shared by binary and content):

  1. --fullsend-source <dir> — validated checkout (go.mod, cmd/fullsend/)
  2. Module root — when CWD is inside a fullsend checkout
  3. GitHub source fetch — at CLI version (released CLI only)
  4. Fail — dev CLI outside a checkout fails with a clear error

Binary resolution:

  1. --fullsend-binary <path> — upload that file (validated as linux/amd64 ELF)
  2. Cross-compile from resolved source (stamped {version}-vendored)
  3. Release fetch — only if cross-compile is unavailable and the running CLI is a released version
  4. Fail — no “latest release” fallback for dev builds

When --vendor is off, stale vendored binary and content paths are removed so CI uses released upstream versions.

Notes:

  • Vendoring does not air-gap the full pipeline (OpenShell, gateway, sandbox image still download at runtime).
  • Release fallback requires network access at install time; CI consumes the uploaded files.
  • Works from any directory inside the module checkout (module root discovery via GOMOD).

Merge enrollment PRs

If you chose to enroll repositories during install, the installer dispatches a workflow that creates an enrollment PR in each enrolled repo. These PRs add a shim workflow (.github/workflows/fullsend.yaml) that wires events to the agent pipeline.

Review and merge each enrollment PR to complete enrollment. Then follow Step 5: Test the pipeline from the end-user setup to verify agent workflows are running.

Managing repository enrollment

After installation, you can enroll or unenroll repositories at any time using the repos subcommands.

Enable repositories

Set the variables for your environment:

bash
export ORG_NAME="<your-github-org>"

To enroll specific repositories (pass repo names as arguments):

bash
fullsend admin enable repos "$ORG_NAME" <repo-name> [repo-name...]

To enroll all repositories:

bash
fullsend admin enable repos "$ORG_NAME" --all

The enable command:

  • Updates config.yaml in the .fullsend repository
  • Triggers the repo-maintenance workflow to create enrollment PRs
  • Validates that repositories exist in the organization before making changes

Disable repositories

ORG_NAME carries over from the enable step above, or set it now:

bash
export ORG_NAME="<your-github-org>"

To unenroll specific repositories (pass repo names as arguments):

bash
fullsend admin disable repos "$ORG_NAME" <repo-name> [repo-name...]

To unenroll all repositories:

bash
fullsend admin disable repos "$ORG_NAME" --all

The --all flag prompts for confirmation — you must type the exact organization name when prompted. To skip the confirmation prompt (e.g., in automated scripts):

bash
fullsend admin disable repos "$ORG_NAME" --all --yolo

The disable command:

  • Updates config.yaml to mark repositories as disabled
  • Triggers the repo-maintenance workflow to create unenrollment PRs
  • Warns (but does not reject) repository names not found in the config, allowing safe cleanup of deleted repos
  • Does not delete existing shim workflows (merge the unenrollment PR to remove them)

Analyze installation status

The analyze command checks the current state of a fullsend installation and reports what is installed, missing, or needs updating. It requires repo and admin:org scopes.

bash
export ORG_NAME="<your-github-org>"
bash
fullsend admin analyze "$ORG_NAME"

This is a read-only operation — it makes no changes.

Uninstall

The uninstall command tears down the fullsend installation for a GitHub organization, removing the .fullsend config repo and associated resources. It prompts for confirmation by requiring you to type the exact organization name.

bash
export ORG_NAME="<your-github-org>"
bash
fullsend admin uninstall "$ORG_NAME"

The uninstall preflight will prompt you to add the delete_repo scope if it is missing.

After removing the config repo and secrets, the CLI opens a browser tab for each installed fullsend GitHub App. Click Uninstall on the page, then press Enter in the terminal to continue to the next app. Once all apps have been processed, the CLI re-checks the org's installations and reports whether each app was successfully removed.

FlagDefaultDescription
--yolofalseSkip the confirmation prompt
--app-setfullsend-aiApp set name prefix for GitHub Apps (used for fallback slug generation when config is unavailable)

Per-repo installation

Per-repo mode installs fullsend for a single repository without requiring an org-wide .fullsend config repo. It's fully self-contained — creating GitHub Apps, deploying a token mint, and configuring WIF as needed.

Installing fullsend in the fullsend-ai org: When installing fullsend for fullsend-ai/fullsend itself, prefer per-org mode (fullsend admin install fullsend-ai). Per-repo mode technically works but creates a circular reference: the per-repo shim workflow calls fullsend-ai/fullsend/.github/workflows/reusable-dispatch.yml@<ref>, which in turn calls reusable stage workflows in the same repo, which check out fullsend-ai/fullsend@<ref> again for upstream defaults and use fullsend-ai/fullsend@<ref> as the composite action. The repo ends up simultaneously serving as the source of reusable workflows, the source of the composite action, the caller repo, and the target repo being acted on. Per-org mode avoids this by placing the shim in fullsend-ai/fullsend and the agent workflows in a separate fullsend-ai/.fullsend config repo, keeping the reference chain unidirectional: target repo → .fullsend → upstream fullsend-ai/fullsend.

Using platform-provided infrastructure

When a platform operator has pre-provisioned shared public GitHub Apps and a token mint, you only need to provide a GCP project for inference. This is the simplest installation path — no Apps to create, no mint to deploy, no PEM management.

Tip: For GitHub-only setup without GCP access, use fullsend github setup instead of admin install. See Setting up with pre-provisioned infrastructure.

This section documents the SaaS installation profile defined in ADR 0033 §6. If you are reusing apps from your own prior per-org installation, see Reusing existing infrastructure instead.

Prerequisites:

  • Org admin approval to install the shared GitHub Apps on your repository
  • GCP project with the Agent Platform API enabled for inference
  • Mint URL — obtain from your platform operator (for OIDC token exchange)
  • Platform operator coordination — the following must be in place before installation:
    • Your organization is registered in the mint's ALLOWED_ORGS configuration
    • The shared GitHub Apps are installed on your repository
    • The mint has the necessary GitHub App PEMs stored in Secret Manager
    • Mint-side Workload Identity Federation (WIF) is configured to accept OIDC tokens from your organization's repositories
  • For assisted installation only — mint GCP project ID and region, plus IAM access to the platform project (see the alternative path below)

Recommended: Use the mint URL directly

Most per-repo users will not have IAM access to the platform operator's GCP project. Ask your platform operator for the mint URL and confirm that the following are in place before running the installer:

  • The shared GitHub Apps are already installed on your repository
  • Your organization is registered in the mint's ALLOWED_ORGS
  • Mint-side WIF is configured to accept tokens from your organization
  • All PEMs are stored in Secret Manager

Then run:

bash
fullsend admin install "$ORG_NAME/$REPO_NAME" \
  --inference-project "$GCP_PROJECT" \
  --mint-url "$PLATFORM_MINT_URL" \
  --skip-mint-check

The installer skips all app discovery, mint validation, and mint-related GCP provisioning — it only generates workflow files and sets repository variables and secrets. WIF infrastructure is still auto-provisioned in the inference project; pass --inference-wif-provider to skip this as well if the platform operator provides a pre-existing WIF provider.

Alternative: Assisted installation (requires platform project access)

If you have IAM access to the platform operator's GCP project, the installer can discover shared apps and handle validation automatically:

bash
fullsend admin install "$ORG_NAME/$REPO_NAME" \
  --inference-project "$GCP_PROJECT" \
  --mint-url "$PLATFORM_MINT_URL" \
  --mint-project "$PLATFORM_MINT_PROJECT" \
  --mint-region "$PLATFORM_MINT_REGION"

This requires roles/cloudfunctions.developer and roles/secretmanager.admin on the platform mint project for app discovery, validation, and org registration. WIF auto-provisioning in the inference project additionally requires roles/iam.workloadIdentityPoolAdmin and roles/resourcemanager.projectIamAdmin on the inference project; pass --inference-wif-provider to skip this if you have a pre-existing WIF provider. The command:

  • Discovers shared app IDs from the platform mint project via GCP Cloud Functions API
  • Checks if the shared apps are already installed on your repository
  • If apps are not installed, opens browser windows to install the pre-existing shared apps (requires org admin approval)
  • Validates and updates the mint configuration if needed (registers your org, updates WIF, stores PEM references)
  • Auto-provisions Workload Identity Federation for your repo in the inference project
  • Generates workflow files and commits scaffold to your repository
  • Sets repository variables and secrets

First-time install (no prior infrastructure)

Set the variables for your environment:

bash
export ORG_NAME="<your-github-org>"
export REPO_NAME="<your-repo-name>"
export GCP_PROJECT="<your-gcp-project>"
bash
fullsend admin install "$ORG_NAME/$REPO_NAME" \
  --inference-project "$GCP_PROJECT" \
  --mint-project "$GCP_PROJECT"

This discovers existing infrastructure and creates what's missing:

  • If no GitHub Apps exist, opens browser windows to create them (same manifest flow as per-org)
  • If no token mint exists, deploys a Cloud Function
  • If both exist from a prior per-org install, reuses them

Creating apps requires admin:org OAuth scope (the installer prompts for it). Reusing existing apps only requires repo and workflow scopes.

Reusing existing infrastructure

When a per-org install already exists in your own org, per-repo reuses the apps and mint. If the infrastructure belongs to a separate platform operator (SaaS profile), see Using platform-provided infrastructure instead.

bash
fullsend admin install "$ORG_NAME/$REPO_NAME" \
  --inference-project "$GCP_PROJECT" \
  --mint-url "$MINT_URL"

Or let it auto-discover the mint from the GCP project:

bash
fullsend admin install "$ORG_NAME/$REPO_NAME" \
  --inference-project "$GCP_PROJECT" \
  --mint-project "$GCP_PROJECT"

Per-repo flags

Per-repo accepts all admin install flags except --enroll-all and --enroll-none (which only apply to org-wide enrollment). Per-repo install requires only repo and workflow OAuth scopes when reusing existing apps. Creating new apps requires admin:org.

--mint-region note: Per-repo uses the same --mint-region default (us-central1) as per-org. When reusing a mint deployed to a non-default region, pass --mint-region explicitly so auto-discovery finds the correct function.


Custom app sets

By default, the installer creates GitHub Apps with the fullsend-ai prefix (e.g., fullsend-ai-fullsend, fullsend-ai-coder, fullsend-ai-review). Organizations that need their own set of apps — for example, to use org-specific permissions or to register multiple app sets on the same mint — can pass --app-set to override the prefix.

Creating a custom app set

Set the variables for your environment:

bash
export ORG_NAME="<your-github-org>"
export GCP_PROJECT="<your-gcp-project>"
bash
fullsend admin install "$ORG_NAME" \
  --inference-project "$GCP_PROJECT" \
  --mint-project "$GCP_PROJECT" \
  --app-set "$ORG_NAME"

This creates apps named {org}-fullsend, {org}-coder, {org}-review, etc. The app set prefix is stored in the .fullsend/config.yaml slug mappings, so subsequent operations (permission checks, PEM recovery) find the correct apps automatically.

Using existing public apps from another app set

When a mint already has public apps registered under a custom app set (e.g., fullsend-ai-fullsend, fullsend-ai-coder), additional orgs installing those apps must pass the same --app-set so the CLI resolves the correct slugs:

bash
export NEW_ORG="<new-github-org>"

GCP_PROJECT carries over from the custom app set creation step above.

bash
fullsend admin install "$NEW_ORG" \
  --inference-project "$GCP_PROJECT" \
  --mint-project "$GCP_PROJECT" \
  --app-set fullsend-ai

The installer detects that the public apps are already installed in the org (matched by app ID from the mint's ROLE_APP_IDS) and skips app creation — role PEM secrets are shared and already exist. The --app-set value ensures convention-based slug lookups match the existing apps.

Migration note: Prior to this change, the default app set was fullsend, producing slugs like fullsend-coder. The default is now fullsend-ai, producing fullsend-ai-coder. Existing installations that used the old default should pass --app-set fullsend explicitly to continue matching their existing GitHub App slugs, or re-install with the new default.

Uninstalling a custom app set

When uninstalling an org that used a custom app set, pass the same --app-set value so the CLI generates the correct fallback slugs if the config repo is unavailable. ORG_NAME carries over from the custom app set creation step above, or set it now:

bash
export ORG_NAME="<your-github-org>"
bash
fullsend admin uninstall "$ORG_NAME" --app-set "$ORG_NAME"

Constraints

  • App set names must be lowercase alphanumeric with optional hyphens (no leading/trailing hyphens, no consecutive hyphens), max 23 characters (GitHub App names are limited to 34 characters, and the role suffix is appended)
  • The app set prefix only affects GitHub App slugs — GCP secret naming (fullsend-{role}-app-pem) and mint ROLE_APP_IDS keys ({role}) are independent of the app set

Standalone commands

The admin install command performs all setup in a single invocation. For organizations that separate GCP and GitHub responsibilities across teams, fullsend provides standalone commands that decompose the same pipeline:

RoleCommandWhat it does
GCP Admin (Inference)fullsend inference provision <org|owner/repo>Create WIF pool/provider and grant Agent Platform access (idempotent — safe to re-run for new orgs)
GCP Admin (Inference)fullsend inference deprovision <org|owner/repo>Remove org or repo from WIF
GCP Admin (Inference)fullsend inference status <org|owner/repo>Check WIF health, print config values
GitHub Maintainerfullsend github setup <org|owner/repo>Configure GitHub org or repo (no GCP needed)
GitHub Maintainerfullsend github enroll <org> [repo...]Add repositories to agent enrollment
GitHub Maintainerfullsend github unenroll <org> [repo...]Remove repositories from agent enrollment
GitHub Maintainerfullsend github set <org|owner/repo> <key> <value>Update a single config value (secret or variable)
GitHub Maintainerfullsend github status <org>Analyze GitHub-side installation state
GitHub Maintainerfullsend github sync-scaffold <org>Update workflow templates to current CLI version
GitHub Maintainerfullsend github uninstall <org>Remove GitHub configuration (org-level only)
GCP Admin (Mint)fullsend mint deployDeploy the token mint Cloud Function
GCP Admin (Mint)fullsend mint add-role <role>Register a role PEM and app ID on the mint
GCP Admin (Mint)fullsend mint remove-role <role>Remove a role from the mint (deletes PEM secret by default)
GCP Admin (Mint)fullsend mint enroll <org|owner/repo>Register an org or repo in the mint (does not grant Agent Platform access — use inference provision)
GCP Admin (Mint)fullsend mint unenroll <org|owner/repo>Remove an org or repo from the mint
GCP Admin (Mint)fullsend mint statusInspect mint state and PEM health

See Setting up with pre-provisioned infrastructure for the complete GitHub maintainer guide and Mint service administration for the mint admin guide.

Per-command IAM role breakdown

When using the split-responsibility workflow, each standalone command requires a subset of IAM roles. Use this table to request only what you need.

IAM Roleinference provisioninference deprovisioninference statusmint deploymint add-rolemint remove-rolemint enrollmint unenrollmint status
roles/iam.workloadIdentityPoolAdminxxxxx
roles/resourcemanager.projectIamAdminx***
roles/iam.serviceAccountAdminx
roles/secretmanager.admin********
roles/cloudfunctions.developerx
roles/cloudfunctions.viewerxxxxx
roles/run.adminxxxxx
roles/iam.workloadIdentityPoolViewerx†
roles/secretmanager.viewer§x

* roles/resourcemanager.projectIamAdmin and roles/secretmanager.admin are required for mint deploy only when using --pem-dir (first-time bootstrap). Standard deploys without --pem-dir do not need these roles.

** roles/resourcemanager.projectIamAdmin is required for mint enroll only in per-repo mode (mint enroll owner/repo). Org-scoped enrollment does not grant IAM bindings — use inference provision separately.

*** roles/secretmanager.admin is required for mint add-role when uploading a new PEM (--pem or browser mode). When using --use-existing-pem-secret, only roles/secretmanager.viewer is required (see §).

**** roles/secretmanager.admin is required for mint remove-role unless --keep-pem is passed (default deletes the PEM secret).

§ roles/secretmanager.viewer is required for mint add-role when using --use-existing-pem-secret (checks that the PEM secret exists).

† All commands that call GCP APIs also require resourcemanager.projects.get (typically available via roles/browser or any project-level viewer role). This is only notable for inference status where it is not covered by the other listed roles.

Required GCP APIs also differ by command group:

bash
# Inference commands (inference provision/deprovision/status):
gcloud services enable \
  iam.googleapis.com \
  cloudresourcemanager.googleapis.com \
  aiplatform.googleapis.com \
  --project="$GCP_PROJECT"

# Mint commands (mint deploy/enroll/unenroll/status):
gcloud services enable \
  iam.googleapis.com \
  cloudresourcemanager.googleapis.com \
  cloudfunctions.googleapis.com \
  run.googleapis.com \
  secretmanager.googleapis.com \
  iamcredentials.googleapis.com \
  --project="$GCP_PROJECT"

Note: iamcredentials.googleapis.com is a runtime dependency — the deployed mint Cloud Function uses it for WIF token exchange, not the CLI itself. It must be enabled before mint deploy.


Advanced: pre-configure WIF

The installer auto-provisions WIF infrastructure. For most cases, fullsend inference provision <org> handles this automatically and prints the WIF provider resource name to pass to admin install --inference-wif-provider or github setup --inference-wif-provider.

If you need custom pool names, attribute conditions, or want to share a provider across tools, you can create WIF manually:

Create a Workload Identity Pool and OIDC Provider:

bash
export GCP_PROJECT="<gcp-project>"
export ORG_NAME="<org-name>"

gcloud iam workload-identity-pools create fullsend-inference \
  --location=global \
  --display-name="Fullsend Inference" \
  --project="$GCP_PROJECT"

gcloud iam workload-identity-pools providers create-oidc github-oidc \
  --location=global \
  --workload-identity-pool=fullsend-inference \
  --issuer-uri="https://token.actions.githubusercontent.com" \
  --attribute-mapping="google.subject=assertion.sub,attribute.repository_owner=assertion.repository_owner,attribute.repository=assertion.repository" \
  --attribute-condition="assertion.repository_owner == '$ORG_NAME'" \
  --project="$GCP_PROJECT"

Grant Agent Platform access to the WIF principal:

bash
export PROJECT_NUMBER=$(gcloud projects describe "$GCP_PROJECT" --format='value(projectNumber)')
export WIF_PRINCIPAL="principalSet://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/fullsend-inference/attribute.repository_owner/$ORG_NAME"

gcloud projects add-iam-policy-binding "$GCP_PROJECT" \
  --role="roles/aiplatform.user" \
  --member="$WIF_PRINCIPAL" \
  --condition=None

Warning — broad WIF scope: The attribute.repository_owner condition above grants WIF access to all repositories in the organization, not just .fullsend. This is required for orgs using per-repo mode (where multiple repos need to authenticate to GCP independently), but it significantly widens the trust boundary compared to per-org-only setups. Note that fullsend admin install <owner/repo> auto-provisions a per-repo WIF provider scoped to a single repository — the org-wide condition here is broader than what the automated path creates.

For per-org-only setups, use the tighter assertion.repository == '$ORG_NAME/.fullsend' condition instead, and scope the WIF principal to attribute.repository/$ORG_NAME/.fullsend. See Google Cloud WIF documentation for condition syntax.

Pass the provider to the installer:

bash
export WIF_PROVIDER="projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/fullsend-inference/providers/github-oidc"

fullsend admin install "$ORG_NAME" \
  --inference-project "$GCP_PROJECT" \
  --inference-wif-provider "$WIF_PROVIDER" \
  --mint-project "$GCP_PROJECT"

Note: IAM policy bindings may take several minutes to propagate. If agent workflows fail with a permission error immediately after setup, wait a few minutes and retry.

Status notifications

Agent workflows post status comments on issues and PRs when they start and complete. This behavior is controlled by the status_notifications section in config.yaml:

yaml
defaults:
  status_notifications:
    comment:
      start: enabled      # "enabled" (default) | "disabled"
      completion: enabled  # "enabled" (default) | "disabled"

When status_notifications is omitted, comments default to enabled.

The composite action accepts four optional inputs for status notifications:

InputDescription
run-urlURL of the CI/CD run shown in the status comment
status-repoRepository (owner/repo) to post status comments on
status-numberIssue or PR number for status comments
mint-urlURL of the token mint service used to obtain fresh tokens for posting comments

All reusable workflows pass these inputs automatically.

See Also