A local agentic dashboard for comparing, maintaining, and porting changes between
hyperswitch-web and
hyperswitch-client-core.
The dashboard owns the workflow, Git branches, build gates, history, and UI. AI work is delegated to a locally installed agent CLI selected in Settings: Claude Code, Codex, or OpenCode. Each CLI uses its own existing authentication and provider configuration; the dashboard does not store model credentials.
The orchestration and workspace are local, but prompts are sent to the model provider configured in the selected CLI. Workflows can also commit, push a generated branch directly to the canonical
juspay/*repository, and open a pull request there when GitHub access is configured.
| Feature | Description |
|---|---|
| Gap Analysis | Compares both SDKs for missing payment methods, configuration fields, components, and backend APIs. |
| Gap Verification | Checks an individual candidate gap against the supposedly missing repository before it is trusted. |
| Patch Generation | Analyses the source implementation, implements the gap on a feature branch, runs a mandatory ReScript build, verifies behavior, and optionally opens a PR. |
| PR Port | Accepts a web or mobile PR URL, infers the direction, rejects non-portable changes early, and ports the behavior into the other SDK. |
| Add Prop | Adds an integrator-facing configuration prop across both SDKs using their existing patterns. |
| Test Writer | Generates Cypress or Detox tests for a local branch or GitHub PR. |
| Translator | Adds an i18n key to all supported locale files with a minimal diff. |
| PR Reviewer | Runs focused security, logic, and convention reviews against a branch or PR. |
| Integration Agent | Implements a payment method or flow from external integration documentation. |
| Feature Agent | Provides an interactive agent workflow for developing a feature across the SDKs. |
| Preview Panel | Runs the selected patch branch in the web dev server or Android emulator and provides mock-server/config controls. |
| History and Documentation | Persists skill runs and reviews, and generates internal plus GitBook-ready documentation for supported changes. |
The application routes stable agent slots such as patch.implementer or
port.verifier to named profiles. A profile contains:
- a runtime:
claude-code,codex, oropencode; - the exact model invocation passed to that runtime;
- an optional reasoning-effort value.
Model strings are intentionally free-form. Examples include sonnet for
Claude Code or litellm/open-large for OpenCode. The Settings page probes the
installed CLIs and offers discovered models as suggestions, but it does not
restrict the value.
| Runtime | Executable | Supported access policies | Additional readable repositories |
|---|---|---|---|
| Claude Code | claude |
text-only, read, read + commands, write | Yes |
| Codex | codex |
read, read + commands, write | Yes |
| OpenCode | opencode |
read, read + commands, write | No |
Capabilities are checked before strict multi-stage workflows start. Assigning a runtime that cannot enforce a stage's requested access fails visibly instead of silently widening permissions.
The server stores a shared default in data/app.db. The Only for this
browser option stores a complete profile/assignment override in browser
localStorage and sends it with supported requests.
The browser override replaces the shared settings for that request; it is
not merged with them. Give the override a default assignment or explicitly
assign every stage the workflow needs. For example, PR Port requires:
port.triage
port.source-analyst
port.implementer
port.verifier
PR Port resolves and freezes all four choices before the run begins. If a slot
is missing and there is no default, the server returns
AGENTS_NOT_CONFIGURED (HTTP 428) before doing any repository work.
At present, PR Port is the strict workflow that threads the browser-local override end to end. Older routes use the shared server settings through the compatibility layer, so configure their profiles as the shared default until those routes finish migrating.
| Tool | Requirement | Check |
|---|---|---|
| Node.js | 22.x | node --version |
| npm | Version bundled with Node 22 | npm --version |
| Git | Any recent version | git --version |
| Agent CLI | At least one of Claude Code, Codex, or OpenCode | See below |
| GitHub CLI | Optional; needed to open PRs automatically | gh --version |
| gitleaks | Required for any automatic push/PR | gitleaks version |
| Android SDK + emulator | Optional; needed for mobile Preview | adb devices |
The server uses better-sqlite3, a native Node module. This repository is
developed and tested on Node 22; using Node 26 produces a native ABI mismatch.
With nvm:
nvm install 22
nvm use 22
node --versionRun nvm use 22 in each new shell before installing dependencies or starting
the dashboard.
Install at least one runtime. These commands follow the current official setup guides:
# Claude Code
npm install -g @anthropic-ai/claude-code
# Codex (macOS/Linux installer)
curl -fsSL https://chatgpt.com/codex/install.sh | sh
# OpenCode
curl -fsSL https://opencode.ai/install | bashOfficial documentation:
Run the selected executable once and complete its authentication/configuration flow:
claude
codex
opencodeFor OpenCode, configure the provider that owns the model invocation. For
example, litellm/open-large requires an OpenCode provider named litellm and
working credentials for that route. The Dashboard's Test button checks a
profile with a live short request before a long workflow consumes time.
git clone https://github.com/Pradeep-kumar1202/Agent-Control-Center.git
cd Agent-Control-Center
nvm use 22npm run setupnpm run setup installs the root/server/web workspaces, then clones or updates:
workspace/hyperswitch-web
workspace/hyperswitch-client-core
Submodules are initialized from their upstream GitHub repositories over HTTPS.
The mandatory ReScript build gate requires node_modules inside the target SDK
repository. The sync step deliberately does not install those dependencies.
npm ci --prefix workspace/hyperswitch-web
npm ci --prefix workspace/hyperswitch-client-corenpm run devThis starts:
- frontend: http://localhost:5173
- backend: http://localhost:5174
- health check: http://localhost:5174/health
The checked-in seed data is imported into an empty database on first boot, so you can inspect verified gap examples without immediately running a complete analysis.
- Open System → Settings.
- Select Re-probe and confirm the runtime you installed is detected.
- Add a profile containing the runtime, model invocation, and optional effort.
- Select Test beside the profile and resolve any authentication/model error.
- Assign the profile as
default, or assign individual stages. - Choose whether the configuration is shared or Only for this browser.
- Save.
Using a Claude Code default is the quickest way to cover every access policy. Codex and OpenCode cannot enforce the tool-free policy used by the analysis extract/normalize stages, so do not assign those slots to those runtimes. They can still run repository-backed workflows such as PR Port and can be selected for implementation or verification stages individually.
- Run or load Gap Analysis.
- Verify the candidate gap.
- Generate the patch from its row.
- The source analyst studies the SDK where the feature already exists.
- The implementer edits a
feat/gap-*branch in the missing SDK. - The server runs
npm run --silent re:buildas a hard gate. - A read-only verifier checks the implementation against the source spec.
- On success, the dashboard commits the branch and attempts to push/open a PR.
The .patch artifact is saved under data/patches/, and the run is recorded in
SQLite. A failed ReScript build keeps a build_failed record and branch so it
can be inspected or repaired.
Current limitation: the original gap-patch route still uses its legacy three-agent prompt path. PR Port uses the newer deterministic validators and non-silent verifier behavior; the gap-patch route has not yet adopted the repair/critic controls shown in Settings. Treat every generated change as a review candidate, even when its build is green.
Open Agents → PR Port and paste a recognized /pull/<number> URL from
juspay/hyperswitch-web or juspay/hyperswitch-client-core.
The workflow:
- validates the URL and infers web → mobile or mobile → web;
- fetches the exact source PR diff;
- performs deterministic checks and a read-only portability triage;
- stops with reasons before creating a branch when the change is not portable;
- produces a structured cross-SDK implementation specification;
- creates a
port/pr-*branch and implements in the target SDK; - runs the ReScript build, deterministic patch validators, and semantic verifier;
- opens a normal PR on pass or a draft PR for
needs_review, when GitHub is available.
Build and validator failures preserve the target branch and report rather than
deleting the work. The target workspace must be on a clean main checkout when
the run starts.
Current limitation: PR Port does not yet have a dedicated target-equivalence gate. If the behavior is already present and the implementer makes no edits, the run stops with
Implementer produced no target changesand opens no PR; it does not currently classify that outcome asalready_present.
Use the Preview action on the generated patch row/result. That action passes the patch's repository and branch into the global Preview Panel; the server then checks out that branch before running the ReScript build and dev server.
The top-bar Preview button is only a global panel toggle. On first use it
defaults to mobile + main, and later it reuses its last context. Therefore,
do not use the top-bar button as the initial entry point when you specifically
want to test a generated patch.
Patch generation returns the shared workspace checkout to main after saving
the result. This is expected. Starting a patch-specific Preview should check the
generated branch back out. If the panel shows or compiles main, close it and
reopen Preview from the patch row, then confirm the displayed branch name.
For mobile previews, the image inside the panel is the real Android AVD
framebuffer, not a browser fallback. On macOS, Windows, or Linux with a desktop
display, the dashboard also launches a visible Android Emulator window. Linux
without DISPLAY/WAYLAND_DISPLAY remains headless. Override detection in the
dashboard .env when needed:
PREVIEW_EMU_HEADLESS=false # always show the emulator window
PREVIEW_EMU_GPU=auto # optional; defaults by launch modeLaunch mode is fixed when the AVD process starts. If an AVD is already running headless, stop that exact emulator and start Preview again; merely changing the environment cannot add a window to the existing process. The payment sheet can still look web-like because the Android SDK renders part of its UI through its embedded React Native/WebView surface.
Automatic publishing pushes the generated parent branch directly to the canonical repository and opens the PR there:
juspay/hyperswitch-web
juspay/hyperswitch-client-core
Authenticate an account with branch-push and pull-request permissions for those repositories:
gh auth login
gh auth statusInstall the mandatory pre-push secret scanner:
brew install gitleaks
gitleaks versionIf gitleaks is missing, times out, or cannot scan the complete payload, the
dashboard fails closed with SECRET_SCAN_UNAVAILABLE and performs no remote
operation.
Run gh --version and gh auth status in the same shell that starts
npm run dev; the backend inherits that shell's PATH and authentication
environment.
Before pushing, the publisher verifies that the workspace's origin resolves
to the expected juspay/* repository and that the generated branch has commits
ahead of origin/main. It resolves the branch to an immutable commit, scans
that commit, rechecks that the branch did not move, and pushes that exact object.
Existing tool-owned branches are updated with --force-with-lease, never an
unconditional force push.
Every publish also crosses a mandatory secret gate before any remote read or write. It:
- scans every commit in
origin/main..generated-commit, including secrets added and removed in a later commit; - rejects committed
.env*, private-key, credential-store, scanner-policy, and opaque archive files; - captures values from both SDK workspaces'
.env*files at server startup and again at publish time, then rejects raw, base64/base64url, hexadecimal, or URL-encoded copies anywhere in committed blobs, commit metadata, branch names, PR titles, or PR bodies; - blocks LFS pointers, opaque binaries/archives, oversized blobs, and merge histories that cannot be completely inspected automatically;
- runs gitleaks with a dashboard-owned configuration and ignore file, so a generated branch cannot self-allowlist a finding;
- redacts all values from errors and returns
SECRET_SCAN_BLOCKEDwithout invoking the GitHub publishing transport.
Agent subprocesses themselves do not receive GH_TOKEN, GITHUB_TOKEN, the
SSH agent socket, Git credential helpers, or the authenticated gh config.
Their Git environment rewrites GitHub URLs to a blocked local endpoint and sets
the origin push URL to a non-network scheme. Model-provider credentials remain
available only where required for the selected runtime. Consequently, an agent
cannot bypass the scanner by running the normal git push or gh pr create
commands; only the server-side publisher retains that authority.
Runtime profiles that use a GitHub-backed model must therefore authenticate via
that CLI's own login/configuration; a GITHUB_TOKEN environment variable is
intentionally not passed into model subprocesses.
Parent PR automation currently rejects changes inside shared-code, android,
or ios. Those changes require separate PRs to the corresponding canonical
submodule repositories and merge ordering before the parent PR. The dashboard
preserves the local branch and returns SUBMODULE_PRS_REQUIRED instead of
rewriting .gitmodules or publishing a broken parent PR.
If pushing or gh pr create fails, the workflow returns a prWarning; the
local branch and generated diff remain available.
The server can seed agent settings from environment variables on the first boot of an empty settings database:
ACC_PROFILE_FAST="claude-code:sonnet"
ACC_PROFILE_CODING="opencode:litellm/open-large:high"
ACC_ASSIGN_DEFAULT="fast"
ACC_ASSIGN_PATCH_IMPLEMENTER="coding"Profile names are derived from ACC_PROFILE_<NAME>. Assignment names convert
underscores to dots, so ACC_ASSIGN_PATCH_IMPLEMENTER assigns
patch.implementer. This is a one-time seed: after profiles exist in SQLite,
the database is the source of truth and later environment changes do not
overwrite it.
npm run dev # server + frontend in watch mode
npm run dev:server # backend only
npm run dev:web # frontend only
npm run build # TypeScript + production web build
npm run sync -w server # sync both SDK repositories/submodules
npm run analyze -w server # run analysis from the command line
npm run check:pr-port -w server # build server + deterministic PR Port checksAgent-Control-Center/
├── agents/ versioned Markdown agent definitions and JSON schemas
│ ├── patch/ gap-patch prompts
│ ├── pr-port/ PR Port triage/analysis/implementation/verification
│ ├── _partials/ reusable SDK knowledge
│ └── schemas/ structured-output contracts
├── server/src/
│ ├── agents/ agent loader and deterministic validators
│ ├── analyzer/ extract → normalize → derive/verify gap pipeline
│ ├── routes/ Express APIs and NDJSON streaming routes
│ ├── runtime/ runtime adapters, settings, access policies, event normalization
│ ├── skills/ skill workflows, Git/submodule helpers, preview, PR creation
│ ├── workspace/ repository synchronization and per-repo mutexes
│ └── db.ts SQLite schema and persistence
├── web/src/
│ ├── components/ gap, patch, chat, diff, and Preview UI
│ ├── settings/ runtime profiles and stage assignments
│ ├── skills/ registry-driven skill forms/results/history
│ └── App.tsx application shell and navigation
├── seed/ checked-in initial gap data
├── workspace/ cloned SDK repositories; Git-ignored
└── data/ SQLite, cache, and patch artifacts; Git-ignored
See agents/README.md for the prompt frontmatter,
templating, schema, and layering conventions.
Switch to Node 22 and rebuild the native dependency:
nvm use 22
npm rebuild better-sqlite3
npm run devIf it still fails, run npm install again while Node 22 is active.
Open Settings and assign every slot named in the error, or set a default profile. If Only for this browser is enabled, update that complete local override or disable it so the request uses the shared settings.
- Run the CLI directly and complete its login/provider setup.
- Return to Settings → Re-probe.
- Use Test beside the profile.
- Confirm the model invocation exactly matches what the CLI accepts.
For OpenCode/LiteLLM, a blocked or unauthorized provider key must be fixed in that provider configuration; the dashboard cannot unblock it.
npm ci --prefix workspace/hyperswitch-web
npm ci --prefix workspace/hyperswitch-client-coreAfter dependency installation, confirm the SDK worktrees are clean before starting a workflow that creates a branch.
Open Preview from the patch row/result rather than the top bar. Confirm the
branch shown in the panel is the generated feat/gap-* branch rather than
main.
The top-bar Preview defaults to main until it has received patch context.
The workspace clone may be shallow:
cd workspace/hyperswitch-web # or workspace/hyperswitch-client-core
git fetch --unshallowlsof -ti:5173 | xargs kill
lsof -ti:5174 | xargs kill
npm run devRe-run:
npm run sync -w serverThe sync command converts SSH submodule URLs to upstream HTTPS in local Git
configuration. It does not edit the tracked .gitmodules files.
Install the GitHub CLI, authenticate an account with
write access to the canonical juspay/* repository, and retry the push/PR step
manually if needed. The dashboard preserves the local branch and reports the
failure as prWarning.
The following paths are intentionally excluded from Git:
/workspace cloned SDK repositories and generated branches
/data SQLite database, analysis cache, and patch files
/node_modules installed dependencies
/.env local environment configuration
The dashboard stores runtime/model names, not provider secrets. Claude Code,
Codex, OpenCode, and gh keep their own authentication outside this repository.
Browser-local agent settings contain only profile and assignment metadata.
Workspace .env* files may contain real SDK keys; the publisher fingerprints
their values only in server memory for leak detection and never logs or persists
those values.