# Use Settings Not Environ

> Read env vars through gg_api_core.settings.get_settings(), not os.environ. Triggers when adding a new env-driven config or reviewing code that calls os.environ / os.getenv. Use when this capability is needed.

- Skill: `tomevault-io/use-settings-not-environ` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/use-settings-not-environ`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/use-settings-not-environ/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/use-settings-not-environ

---


# Use `Settings`, not `os.environ`

All env-var access in `gg-mcp` goes through `gg_api_core.settings.Settings`. Adding `os.environ.get(...)` to non-test code is a review-blocker.

## Pattern

```python
# 1. Declare the field on Settings (packages/gg_api_core/src/gg_api_core/settings.py)
github_token: str | None = None   # → reads GITHUB_TOKEN (case-insensitive)

# 2. Read it
from gg_api_core.settings import get_settings
token = get_settings().github_token
```

Derived booleans/lists → add a `@property` on `Settings` (see `is_oauth_enabled`, `requested_scopes`).

## Don't

- `os.environ.get(...)` / `os.getenv(...)` in production code.
- Module-level capture: `_S = get_settings()` — breaks `monkeypatch.setenv` in tests.
- `@lru_cache` on `get_settings` — same reason. It is intentionally uncached.

## OK exceptions

Tests (`monkeypatch.setenv`), pre-`Settings`-import bootstrap, and constructing a subprocess `env=`.

---
> Source: [GitGuardian/ggmcp](https://github.com/GitGuardian/ggmcp) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-07-05 -->

