Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use separate datasource names per environment (wiki_staging vs wiki_prod). Trigger: "glean multi env setup", "multi-env-setup".
.claude/skills/jeremylongshore-glean-multi-env-setup/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 6% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -32% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 11% | 0% |
| case-07 | ✗→✓ | ▲ Improved | -46% | 0% |
| case-08 | ✗→✓ | ▲ Improved | -26% | 0% |
Glean enterprise search requires environment isolation to prevent test data from polluting production search results. Each environment uses its own datasource names, API tokens, and connector configurations. Sandbox indexes synthetic test documents, staging indexes a curated subset of real documents for search quality validation, and production indexes the full corpus. Connector changes must be tested in staging before promotion to avoid breaking search relevance for end users.
typescriptconst gleanConfig = (env: string) => ({ development: { apiToken: process.env.GLEAN_API_TOKEN_DEV!, baseUrl: "https://sandbox.glean.com/api/v1", datasourceSuffix: "_sandbox", indexingEnabled: true, searchQualityChecks: false, }, staging: { apiToken: process.env.GLEAN_API_TOKEN_STG!, baseUrl: "https://staging.glean.com/api/v1", datasourceSuffix: "_staging", indexingEnabled: true, searchQualityChecks: true, }, production: { apiToken: process.env.GLEAN_API_TOKEN_PROD!, baseUrl: "https://app.glean.com/api/v1", datasourceSuffix: "_prod", indexingEnabled: true, searchQualityChecks: false, }, }[env]);
text# Per-env files: .env.development, .env.staging, .env.production GLEAN_API_TOKEN_{DEV|STG|PROD}=<token> GLEAN_BASE_URL=https://{sandbox|staging|app}.glean.com/api/v1 GLEAN_DATASOURCE_SUFFIX={_sandbox|_staging|_prod} GLEAN_INSTANCE={sandbox|staging|production}
typescriptfunction validateGleanEnv(env: string): void { const suffix = { development: "_DEV", staging: "_STG", production: "_PROD" }[env]; const required = [`GLEAN_API_TOKEN${suffix}`, "GLEAN_BASE_URL", "GLEAN_INSTANCE"]; const missing = required.filter((k) => !process.env[k]); if (missing.length) throw new Error(`Missing Glean env vars for ${env}: ${missing.join(", ")}`); }
bash# 1. Index test documents in sandbox curl -X POST "$GLEAN_BASE_URL/indexing/datasources/wiki_sandbox/documents" \ -H "Authorization: Bearer $GLEAN_API_TOKEN_DEV" -d @test-docs.json # 2. Validate search quality in staging curl "$GLEAN_BASE_URL/search" -H "Authorization: Bearer $GLEAN_API_TOKEN_STG" \ -d '{"query": "onboarding guide"}' | jq '.results[:3].title' # 3. Compare relevance scores against baseline node scripts/compare-search-quality.js --env staging --baseline baseline.json # 4. Promote connector config to production cp connectors/staging/*.json connectors/production/ curl -X POST "$GLEAN_BASE_URL/indexing/datasources/wiki_prod/crawl" \ -H "Authorization: Bearer $GLEAN_API_TOKEN_PROD"
| Setting | Dev (Sandbox) | Staging | Prod | |---------|---------------|---------|------| | Data Source | Synthetic test docs | Subset of real docs | Full document index | | Datasource Suffix | _sandbox | _staging | _prod | | Connectors | Mock connectors | Real connectors | Real connectors | | User Access | Developers only | QA + developers | All employees | | Crawl Frequency | Manual | Daily | Continuous |
| Issue | Cause | Fix | |-------|-------|-----| | Datasource not found | Suffix mismatch between env and config | Verify GLEAN_DATASOURCE_SUFFIX matches connector registration | | 401 on indexing API | Token scoped to wrong instance | Regenerate token in the correct Glean admin console | | Search returns stale results | Crawl not triggered after promotion | Manually trigger crawl via indexing API | | Connector sync fails | OAuth credentials expired for data source | Re-authorize connector in Glean admin for the target env | | Staging indexes prod data | Connector config copied without suffix update | Always update datasource names when promoting configs |
See glean-deploy-integration.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 19,625 | 14,121 | -28% | 1 | 1 | 0% | 3,021 | 3,192 | +6% | 0 | 0 | — |
case-02 | fail→fail | 10,299 | 6,810 | -34% | 1 | 1 | 0% | 2,086 | 2,610 | +25% | 0 | 0 | — |
case-03 | fail→pass | 52,335 | 17,646 | -66% | 1 | 1 | 0% | 4,866 | 3,312 | -32% | 0 | 0 | — |
case-04 | fail→fail | 8,314 | 2,464 | -70% | 1 | 1 | 0% | 1,717 | 1,699 | -1% | 0 | 0 | — |
case-05 | pass→pass | 14,260 | 2,988 | -79% | 1 | 1 | 0% | 1,634 | 1,635 | +0% | 0 | 0 | — |
case-06 | fail→pass | 12,441 | 7,442 | -40% | 1 | 1 | 0% | 1,383 | 1,540 | +11% | 0 | 0 | — |
case-07 | fail→pass | 19,476 | 1,897 | -90% | 1 | 1 | 0% | 2,666 | 1,447 | -46% | 0 | 0 | — |
case-08 | fail→pass | 15,708 | 2,088 | -87% | 1 | 1 | 0% | 2,005 | 1,484 | -26% | 0 | 0 | — |
case-09 | pass→pass | 17,575 | 1,959 | -89% | 1 | 1 | 0% | 2,417 | 1,518 | -37% | 0 | 0 | — |
case-10 | fail→fail | 15,567 | 6,792 | -56% | 1 | 1 | 0% | 1,980 | 1,419 | -28% | 0 | 0 | — |
case-11 | fail→pass | 17,036 | 4,500 | -74% | 1 | 1 | 0% | 2,315 | 2,115 | -9% | 0 | 0 | — |
case-12 | fail→pass | 9,879 | 8,254 | -16% | 1 | 1 | 0% | 1,963 | 1,807 | -8% | 0 | 0 | — |
case-13 | pass→pass | 10,646 | 8,230 | -23% | 1 | 1 | 0% | 1,488 | 1,669 | +12% | 0 | 0 | — |
case-14 | fail→pass | 20,066 | 2,072 | -90% | 1 | 1 | 0% | 2,263 | 1,461 | -35% | 0 | 0 | — |
case-15 | fail→pass | 21,991 | 16,738 | -24% | 1 | 1 | 0% | 2,561 | 3,016 | +18% | 0 | 0 | — |
case-16 | fail→pass | 12,670 | 1,898 | -85% | 1 | 1 | 0% | 1,218 | 1,400 | +15% | 0 | 0 | — |
case-17 | fail→pass | 13,235 | 7,209 | -46% | 1 | 1 | 0% | 1,339 | 1,448 | +8% | 0 | 0 | — |
case-18 | fail→pass | 2,224 | 2,078 | -7% | 1 | 1 | 0% | 298 | 1,389 | +366% | 0 | 0 | — |
case-19 | fail→pass | 14,021 | 8,175 | -42% | 1 | 1 | 0% | 1,694 | 1,717 | +1% | 0 | 0 | — |
case-20 | fail→pass | 32,944 | 9,158 | -72% | 1 | 1 | 0% | 1,278 | 2,904 | +127% | 0 | 0 | — |
case-21 | pass→pass | 12,529 | 12,859 | +3% | 1 | 1 | 0% | 2,478 | 2,554 | +3% | 0 | 0 | — |
case-22 | pass→pass | 15,849 | 19,377 | +22% | 1 | 1 | 0% | 3,413 | 4,291 | +26% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +64 percentage points is the difference between those two pass rates over the 21 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.