Getting Started#
Welcome to Gittensory! This guide covers everything you need to get up and running — whether you're a miner or contributor who wants to use the MCP package, or a backend developer setting up a local copy of the API Worker.
Prerequisites#
Before you clone and run Gittensory locally, make sure the following tools are available.
Node.js ≥ 22.0.0#
Gittensory explicitly requires Node.js 22 or later. This is enforced in the root package.json :
"engines": {
"node": ">=22.0.0"
}
Check your current version:
node --version
If you need to install or upgrade, nvm and fnm are both popular version managers. With nvm:
nvm install 22
nvm use 22
npm#
The project is pinned to npm@10.9.2 and uses npm workspaces to manage the monorepo. npm ships with Node.js, so upgrading Node will also upgrade npm. Confirm with:
npm --version
Git#
Git is required to clone the repository and is used internally by several scripts (including the CI gate's git diff --check step). Any reasonably recent version of Git will work.
A GitHub Account#
A GitHub account is needed for:
- Backend development — the GitHub OAuth and GitHub App integrations authenticate against GitHub identity.
- MCP usage —
gittensory-mcp loginuses GitHub Device Flow to authenticate you and exchange your GitHub identity for a Gittensory session token.
A Cloudflare Account (backend development only)#
The API Worker runs on Cloudflare Workers via Wrangler. Wrangler is already included as a dev dependency , so there is no separate global install required. However, you will need a free Cloudflare account if you plan to deploy, and wrangler login must succeed for commands that talk to Cloudflare (such as wrangler secret put). For purely local development (npm run dev), a Cloudflare account is helpful but the local D1 database and Worker can run without one.
MCP-only users (miners and contributors who just want to install
@jsonbored/gittensory-mcp) only need Node.js ≥ 22, npm, and a GitHub account. No Cloudflare setup is required.
Local Development Setup#
These steps bring up a fully working local copy of the Gittensory API Worker.
1. Clone the repository#
git clone https://github.com/JSONbored/gittensory.git
cd gittensory
The repository URL is git+https://github.com/JSONbored/gittensory.git .
2. Install dependencies#
npm install
Gittensory is an npm workspaces monorepo containing both apps/* and packages/* . A single npm install at the repo root installs dependencies for every workspace — the API Worker, the gittensory-ui frontend, and the @jsonbored/gittensory-mcp package — all at once.
Expected output: npm will print the usual dependency tree and produce a single node_modules directory at the root. If you see peer-dependency warnings, they are generally safe to ignore unless they're errors.
3. Generate Cloudflare Worker types#
npm run cf-typegen
This runs wrangler types to generate TypeScript type declarations for every Cloudflare Workers binding — the D1 database, Queues, AI binding, and Durable Objects — and writes them to worker-configuration.d.ts . A trailing perl one-liner strips any trailing whitespace that Wrangler adds.
Why it's necessary: without these generated types, the TypeScript compiler cannot resolve the Cloudflare-specific globals (Env, DB, JOBS, etc.) that the Worker source code references.
Expected output: Wrangler prints a confirmation message and worker-configuration.d.ts is created or updated in the project root.
4. Run local database migrations#
npm run db:migrate:local
This runs wrangler d1 migrations apply gittensory --local , which applies all pending SQL migrations from the migrations/ directory to a local SQLite file that Wrangler manages on your machine . No Cloudflare account or internet connection is needed for the local flag.
Why it's necessary: the API Worker expects the D1 database schema to be in place before it can serve requests. Skipping this step causes runtime errors when the Worker tries to query tables that don't exist yet.
Expected output: Wrangler lists each migration file applied and reports success. If all migrations have already been applied, it prints that there is nothing to run.
5. Start the development server#
npm run dev
This runs wrangler dev , which compiles src/index.ts and serves the gittensory-api Worker locally . Wrangler starts a local HTTP server — by default at http://localhost:8787 — and watches your source files for changes.
Expected output:
⛅️ wrangler dev
------------------
⎔ Starting local server...
[wrangler] Ready on http://localhost:8787
You can verify the Worker is running by visiting http://localhost:8787/health — it should return {"status":"ok"}.
Optional: Link the MCP package from a local checkout#
If you're also developing the @jsonbored/gittensory-mcp package, you can link it locally instead of installing from npm :
npm link --workspace @jsonbored/gittensory-mcp
This makes the gittensory-mcp CLI point to your local packages/gittensory-mcp/ source so that changes are reflected immediately.
Environment Configuration#
Gittensory does not use .env files. All configuration is split between two places:
- Public variables — checked in to
wrangler.jsoncunder thevarskey. These are non-sensitive values that are safe to commit. - Secrets — set with
wrangler secret putand stored encrypted in Cloudflare. These are never written to the filesystem.
Public variables (wrangler.jsonc)#
The following variables are already present in the checked-in wrangler.jsonc . For local development you can use the values as-is:
| Variable | Default value | Purpose |
|---|---|---|
GITHUB_APP_ID | 3824093 | The Gittensory GitHub App ID |
GITHUB_APP_SLUG | gittensory | GitHub App slug for comment attribution |
GITHUB_OAUTH_CLIENT_ID | Iv23li574mpdLo2PnVN4 | GitHub OAuth App client ID |
GITTENSOR_UPSTREAM_REPO | entrius/gittensor | The canonical Gittensor repository |
GITTENSOR_UPSTREAM_REF | test | Branch/ref to track on the upstream repo |
GITTENSOR_REGISTRY_URL | (full URL to registry JSON) | Location of the Gittensor registry manifest |
GITTENSORY_AUTO_FILE_DRIFT_ISSUES | false | Whether to auto-file drift issues |
GITTENSORY_DRIFT_ISSUE_REPO | JSONbored/gittensory | Repo where drift issues are filed |
PUBLIC_API_ORIGIN | https://gittensory-api.aethereal.dev | Public URL of the API Worker |
PUBLIC_SITE_ORIGIN | https://gittensory.aethereal.dev | Public URL of the frontend |
AI_SUMMARIES_ENABLED | false | Enable Cloudflare Workers AI summaries |
AI_PUBLIC_COMMENTS_ENABLED | false | Enable AI-generated public comments |
WORKERS_AI_SUMMARY_MODEL | @cf/meta/llama-3.1-8b-instruct-fp8-fast | Model used when AI is enabled |
AI_DAILY_NEURON_BUDGET | 10000 | Daily token budget for AI features |
AI_MAX_OUTPUT_TOKENS | 256 | Maximum tokens per AI response |
ADMIN_GITHUB_LOGINS | JSONbored | Comma/whitespace-separated allowlist of GitHub logins allowed to receive Gittensory OAuth sessions. Leave unset to disable OAuth session issuance entirely . |
For local development, change
PUBLIC_API_ORIGINtohttp://localhost:8787if you want the frontend and MCP to point at your local Worker instead of production.
Secrets#
These values are sensitive and must be set with wrangler secret put . Run each command and paste the value when prompted:
wrangler secret put GITHUB_WEBHOOK_SECRET
wrangler secret put GITHUB_APP_PRIVATE_KEY
wrangler secret put GITHUB_PUBLIC_TOKEN
wrangler secret put GITHUB_OAUTH_CLIENT_SECRET
wrangler secret put GITTENSORY_API_TOKEN
wrangler secret put GITTENSORY_MCP_TOKEN
wrangler secret put INTERNAL_JOB_TOKEN
| Secret | Purpose |
|---|---|
GITHUB_WEBHOOK_SECRET | Validates incoming GitHub webhook payloads |
GITHUB_APP_PRIVATE_KEY | Signs GitHub App JWT tokens for API authentication |
GITHUB_PUBLIC_TOKEN | Server-side token that raises public GitHub API rate limits during repo backfill. Not a contributor token . |
GITHUB_OAUTH_CLIENT_SECRET | GitHub OAuth App client secret. Set this on the API Worker only — do not put it on the UI Worker . |
GITTENSORY_API_TOKEN | Static bearer token for protected API endpoints |
GITTENSORY_MCP_TOKEN | Token issued to MCP clients |
INTERNAL_JOB_TOKEN | Authenticates internal scheduled-job routes |
For local-only development without deploying, you can skip secrets that are only used by deployed Worker features (e.g., GITHUB_WEBHOOK_SECRET is only needed if you are routing real GitHub webhooks to your machine via a tunnel such as cloudflared or ngrok).
Cloudflare bindings#
The Worker also uses these Cloudflare-managed resources , which Wrangler provisions automatically in local mode:
| Binding | Type | Purpose |
|---|---|---|
DB | D1 (SQLite) | Primary application database |
JOBS | Queue | Async job processing |
RATE_LIMITER | Durable Object | Per-IP rate limiting |
AI | Workers AI | Optional AI prose generation |
No manual setup is needed for local development — Wrangler emulates all of these locally.
MCP environment variables#
If you are using @jsonbored/gittensory-mcp and need to override defaults, the following environment variables are supported :
| Variable | Purpose |
|---|---|
GITTENSORY_API_URL | Override the API endpoint (e.g., point at your local Worker: http://localhost:8787) |
GITTENSORY_CONFIG_PATH or GITTENSORY_CONFIG_DIR | Override the default config storage location |
GITTENSORY_API_TOKEN, GITTENSORY_MCP_TOKEN, or GITTENSORY_TOKEN | Static token, as an alternative to running gittensory-mcp login |
GITHUB_TOKEN | Used for non-interactive login bootstrap via gittensory-mcp login |
GITTENSOR_SCORE_PREVIEW_CMD | Path to a local scorer command (see the MCP README for reference implementations) |
GITTENSOR_ROOT | Path to a local entrius/gittensor checkout (required for the Python scorer) |
GITTENSOR_SCORE_PREVIEW_TIMEOUT_MS | Timeout for the local scorer in milliseconds (default: 15000) |
GITTENSORY_UPLOAD_SOURCE | Must be false or unset. Source upload is unsupported in v1 and fails closed if set to true . |
GITTENSORY_SKIP_NPM_VERSION_CHECK | Set to true to skip the npm version freshness check |
MCP Package Quick Start#
@jsonbored/gittensory-mcp is the primary surface for miners and contributors. It is a local stdio MCP wrapper that reads your branch's git metadata, calls the Gittensory API, and returns structured Gittensor intelligence — without ever uploading your source code .
Install#
npm install -g @jsonbored/gittensory-mcp
Or run it once without installing globally :
npx -y @jsonbored/gittensory-mcp --help
Step 1 — Log in#
gittensory-mcp login
login uses GitHub Device Flow by default . The CLI will print something like:
Open https://github.com/login/device and enter code XXXX-XXXX.
Open the URL in your browser, enter the code, and approve the authorization. The CLI polls for your approval and, once confirmed, stores a Gittensory session token — not your GitHub PAT — in local config .
Alternative (non-interactive): if you already have a GitHub token available (e.g., via the gh CLI), skip the browser step:
gittensory-mcp login --github-token "$(gh auth token)"
After logging in, verify your session:
gittensory-mcp whoami
gittensory-mcp status
status reports your local package version, the latest npm version, API health, auth state, and source-upload posture .
Step 2 — Run a health check#
gittensory-mcp doctor
doctor is a comprehensive diagnostic command . It checks:
api_health— Can the CLI reach the Gittensory API?version— Is your installed package up to date?api_compatibility— Does the API require a newer client version?auth— Is a valid session token configured and verified?source_upload— ConfirmsGITTENSORY_UPLOAD_SOURCEis disabled (safe posture).git_metadata— Can the CLI read the local git repository?client_path— Isgittensory-mcpvisible on your shellPATH?local_scorer— Is an optional local scorer configured and working?
Each check reports pass, warn, or fail along with a remediation hint. The overall status is either ok, warnings, or needs_attention.
Add --json to get machine-readable output:
gittensory-mcp doctor --json
Step 3 — Start the MCP server#
gittensory-mcp --stdio
This starts the MCP server over stdio transport . It is how MCP clients — Claude Desktop, Codex, Cursor, and others — communicate with Gittensory. You do not normally run this command directly; instead, you wire it into your coding agent's configuration.
Wiring into your coding agent#
The quickest way is to let the CLI print the correct configuration snippet for your editor:
gittensory-mcp init-client --print codex
gittensory-mcp init-client --print claude
gittensory-mcp init-client --print cursor
Paste the printed snippet into your agent's config file. See the MCP client setup docs for editor-specific instructions.
For any MCP-compatible client, the generic stdio config is :
{
"mcpServers": {
"gittensory": {
"command": "gittensory-mcp",
"args": ["--stdio"]
}
}
}
Heads-up: if your MCP client does not inherit your shell's
PATH, replace"gittensory-mcp"with the absolute path to the binary (e.g., the output ofwhich gittensory-mcp).
Available MCP tools#
Once connected, your coding agent has access to the following Gittensory tools :
gittensory_agent_plan_next_work— rank and explain next actionsgittensory_agent_start_run— start a deterministic agent rungittensory_agent_get_run— fetch a run result by IDgittensory_agent_explain_next_action— explain blockers for a specific actiongittensory_agent_prepare_pr_packet— draft a public-safe PR packet
Running Tests#
Gittensory uses Vitest for its test suite with a 97% coverage threshold enforced across all metrics . Tests are organized into two separate configurations: one for standard Node.js tests, and one for Cloudflare Workers-specific tests .
Run all tests#
npm test
This is an alias for vitest run and runs every test file matching test/**/*.test.ts except those under test/workers/ .
Run specific test suites#
# Unit tests only
npm run test:unit
# Integration tests only
npm run test:integration
# Cloudflare Workers tests (uses a separate vitest config)
npm run test:workers
The unit suite runs files under test/unit/, the integration suite runs files under test/integration/, and test:workers uses vitest.workers.config.ts with @cloudflare/vitest-pool-workers to run tests against the real Cloudflare Workers runtime .
Watch mode#
npm run test:watch
Runs vitest without the run flag, keeping the process alive and re-running affected tests on every file save .
Coverage report#
npm run test:coverage
This runs vitest run --coverage and generates a coverage report using the v8 provider . Coverage is collected from src/**/*.ts, excluding src/env.d.ts .
The build will fail if any of these thresholds are not met :
| Metric | Threshold |
|---|---|
| Lines | 97% |
| Functions | 97% |
| Branches | 97% |
| Statements | 97% |
Tip: when writing new code, aim for 98%+ branch coverage locally to leave a comfortable margin above the gate .
Full CI gate#
npm run test:ci
This is the complete validation pipeline run on every PR :
git diff --check # no whitespace errors
npm run actionlint # GitHub Actions workflow linting
npm run typecheck # TypeScript type checking
npm run test:coverage # unit + integration tests with coverage
npm run test:workers # Cloudflare Workers tests
npm run build:mcp # MCP package build
npm run test:mcp-pack # MCP package file hygiene
npm run ui:openapi:check # OpenAPI contract check
npm run ui:lint # frontend linting
npm run ui:typecheck # frontend type checking
npm run ui:build # frontend production build
npm audit --audit-level=moderate # dependency vulnerability audit
Run this locally before opening a PR to catch issues early.
Test organization#
The test/ directory is structured as follows:
| Directory | Contents |
|---|---|
test/unit/ | 51 unit test files covering auth, scoring, GitHub integration, MCP services, and more |
test/integration/ | Integration tests against internal service boundaries |
test/contract/ | Contract tests including upstream Gittensor compatibility |
test/workers/ | Cloudflare Workers runtime tests |
test/fixtures/ | Shared test fixtures and mock data |
test/helpers/ | Shared test utility functions |
test/stubs/ | Cloudflare service stubs (cloudflare:email, cloudflare:workers) |
Common Issues / Troubleshooting#
Node version mismatch#
Symptom: npm install or npm run dev fails with an error like The engine "node" is incompatible with this module.
Fix: Gittensory requires Node.js ≥ 22.0.0 . Check your version with node --version and upgrade if needed. With nvm:
nvm install 22
nvm use 22
Or with fnm:
fnm install 22
fnm use 22
Stale global MCP install#
Symptom: A command like gittensory-mcp agent plan is not recognized, or the CLI behaves unexpectedly.
Fix: Run gittensory-mcp doctor — it checks whether your installed version matches npm latest and prints the exact upgrade command if you are behind . This is a known real-world issue . Upgrade with:
npm install -g @jsonbored/gittensory-mcp
Or use the no-install fallback: npx @jsonbored/gittensory-mcp@latest <command>.
Missing secrets / environment variables#
Symptom: npm run dev starts but requests fail with 500 errors, or Wrangler complains about missing bindings.
Fix: Set each required secret with wrangler secret put. All seven secrets listed in the Environment Configuration section are needed for full functionality . For purely local offline development, you can defer secrets that only apply to deployed features (GitHub webhooks, OAuth).
Database migration failures#
Symptom: npm run db:migrate:local exits with an error, or the Worker crashes with SQL errors at startup.
Fix: Make sure you are running the command from the repo root (where wrangler.jsonc lives). Wrangler uses the migrations_dir: "migrations" path from that config . If the local D1 database file is corrupted, delete Wrangler's local state directory (usually .wrangler/) and re-run the migration:
rm -rf .wrangler
npm run db:migrate:local
Port conflicts#
Symptom: npm run dev (Wrangler) fails with EADDRINUSE or a similar port-in-use error.
Fix: Wrangler's API Worker defaults to port 8787. The UI preview server uses port 4173 . Kill any processes already on those ports:
# macOS / Linux
lsof -ti:8787 | xargs kill -9
lsof -ti:4173 | xargs kill -9
Or configure Wrangler to use a different port by passing --port <N> to wrangler dev.
Authentication issues (MCP)#
Symptom: gittensory-mcp analyze-branch or other commands return authentication errors.
Fix: Run gittensory-mcp doctor first — it reports the exact auth state and prints remediation steps :
gittensory-mcp doctor
If the auth check shows fail, re-authenticate:
gittensory-mcp login
If you are using a static API token instead of a session, set GITTENSORY_API_TOKEN (or GITTENSORY_MCP_TOKEN / GITTENSORY_TOKEN) in your environment.
gittensory-mcp not found in MCP client#
Symptom: Your coding agent (Claude Desktop, Codex, Cursor) fails to start the MCP server with a "command not found" error.
Fix: Many MCP clients launch processes without inheriting your shell's full PATH. Use the absolute path to the binary in your agent config :
which gittensory-mcp # copy this path
Then update your config:
{
"mcpServers": {
"gittensory": {
"command": "/absolute/path/to/gittensory-mcp",
"args": ["--stdio"]
}
}
}
GITTENSORY_UPLOAD_SOURCE error#
Symptom: gittensory-mcp doctor reports a fail on the source_upload check.
Fix: Source upload is unsupported in v1 and fails closed if the variable is set to true . Unset the variable:
unset GITTENSORY_UPLOAD_SOURCE
GitHub App installation issues#
Symptom: The GitHub App is installed but fails to respond to webhooks or health checks show missing permissions.
Fix: Verify that the GitHub App has the required repository permissions (Metadata: read, Pull requests: read, Issues: write) and is subscribed to the required events (Pull request, Issues, Issue comment, Repository) . The maintainer can run a structured repair workflow from the API to diagnose and fix missing permissions .
Getting more help#
- GitHub Issues: https://github.com/JSONbored/gittensory/issues
- Support policy: see
SUPPORT.mdin the repository root - Code of Conduct:
CODE_OF_CONDUCT.md - Security issues:
SECURITY.md— do not file security vulnerabilities as public issues