Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"enabledPlugins": {
"superpowers@claude-plugins-official": true
}
}
89 changes: 89 additions & 0 deletions .claude/skills/fableplan/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
name: fableplan
description: |
Toggle "Fable Plan Mode" for this repo, on this machine only — plan with
Fable 5, execute with Sonnet (opusplan-style). Use when the user runs
/fableplan, optionally with "off" to disable, or "1m" to use the
1M-context Fable variant.
---

# Fableplan — plan with Fable 5, execute with Sonnet (opt-in, per-user)

Claude Code has a built-in `opusplan` model setting ("Opus in plan mode,
Sonnet otherwise") but no Fable equivalent. This skill recreates it by
combining `opusplan` with the `ANTHROPIC_DEFAULT_OPUS_MODEL` environment
variable override, which redirects the "opus" alias to Fable 5 — giving
Fable 5 in plan mode and Sonnet for execution, at lower cost than running
Fable continuously.

This is **opt-in only**: nothing in this repo enables it by default. Running
this skill writes to `.claude/settings.local.json` and
`.claude/.fableplan-backup.json` — both gitignored and specific to this
machine. Nothing is committed, and no other user or repo config is affected.

Adapted from [bapttiste73/fableplan](https://github.com/bapttiste73/fableplan)
(MIT licensed), retargeted from the user's global `~/.claude/settings.json`
to this repo's local settings file so the effect stays scoped to this repo.

## Arguments

- *(none)* — enable fableplan locally with `claude-fable-5`
- `1m` — enable fableplan locally with `claude-fable-5[1m]` (1M context
window; higher per-token cost, use deliberately)
- `off` — disable fableplan locally, reverting to this repo's normal model
configuration

## Enabling (no argument, or `1m`)

1. Read `.claude/settings.local.json` (repo-relative). If it does not exist,
create it with an empty object first.
2. If `.claude/.fableplan-backup.json` does not exist, create it before changing
settings. Record whether `"model"` exists and its current value, and whether
`"env"."ANTHROPIC_DEFAULT_OPUS_MODEL"` exists and its current value. This
backup represents the pre-fableplan configuration and must not be overwritten
on subsequent enables.
3. Merge the following keys, preserving every other existing setting (notably
`permissions` and `defaultMode`, if present):
- Set `"model": "opusplan"`.
- Under `"env"` (create the object if missing, preserve its other
entries), set `"ANTHROPIC_DEFAULT_OPUS_MODEL"` to `"claude-fable-5"` (or
`"claude-fable-5[1m]"` if the argument is `1m`).
4. Validate that both resulting files are valid JSON.
5. Tell the user:
- Fableplan is enabled on this machine: plan mode runs on Fable 5,
execution runs on Sonnet.
- They must **restart their Claude Code session** for the change to take
effect.
- The UI will display "Opus Plan Mode" — that label is cosmetic; plan mode
actually runs Fable 5.
- This only changed gitignored local files — nothing is committed and no
other user is affected.

## Disabling (`off`)

1. Read `.claude/settings.local.json`. If it does not exist, there is nothing
to do — tell the user fableplan is already off (it was never enabled on
this machine).
2. Read `.claude/.fableplan-backup.json`. If it does not exist, do not change
`"model"` or `"ANTHROPIC_DEFAULT_OPUS_MODEL"`: their origin cannot be
determined safely. Tell the user that fableplan's backup is missing and its
settings were left intact.
3. Otherwise, restore `"model"` and `"env"."ANTHROPIC_DEFAULT_OPUS_MODEL"` to
the values recorded in the backup. Remove each key when the backup records
that it was absent; drop the `"env"` key entirely if it becomes empty. Leave
every other key untouched, then delete `.claude/.fableplan-backup.json`.
4. Validate JSON and tell the user:
- Fableplan is disabled on this machine; the repo's normal model
configuration applies again.
- They must restart their Claude Code session for the change to take
effect.
- Run `/fableplan` (no argument) at any time to re-enable.

## Important caveats (mention them when enabling for the first time)

- `ANTHROPIC_DEFAULT_OPUS_MODEL` is an undocumented override — a future CLI
update could change or remove it.
- Fable 5 is not available on every plan/account. If requests fail after
enabling, run `/fableplan off` to revert.
- Anything else that resolves the "opus" alias (e.g. fast mode) will also
point to Fable while `opusplan` + the env override are active.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ schemas
!.gitignore
!.markdownlint.yaml
!.editorconfig
!.claude
.claude/settings.local.json
site
uv.lock
70 changes: 70 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# AGENTS.md

`oapi`: generates type-safe Python API client/model modules from OpenAPI
2.0/3.x documents. Data models are built on `sob` (schema-enforcing
serialization) and reject/validate data not matching the spec.

## Layout

- `src/oapi/oas/model.py` — data model for OpenAPI/Swagger documents
themselves (`OpenAPI`, `Info`, `Paths`, `Schema`, ...). Excluded from
ruff/lint — treat as generated, do not hand-format.
- `src/oapi/oas/references.py` — `$ref` resolution for OAS documents.
- `src/oapi/model.py` — `write_model_module` / `ModelModule`: generates a
data-model `.py` file from an OpenAPI doc.
- `src/oapi/client.py` — `write_client_module` / `ClientModule` /
`Client`: generates a client `.py` file; also request formatting,
encoding, retry logic used by generated clients at runtime.
- `src/oapi/errors.py` — exception types.
- `scripts/remodel.py` — regenerates `src/oapi/oas/model.py` itself (run
via `make remodel` after changes affecting that generation).
- `template/` — cookiecutter template for scaffolding new `oapi`-based
client projects (own `pyproject.toml`, own `scripts/remodel.py`
pattern). Excluded from ruff/mypy/tests.
- `tests/test_*.py` — exactly one test module per `src/oapi` module
(e.g. `test_client.py` for `client.py`, `test_oas_model.py` for
`oas/model.py`, `test_oas_references.py` for `oas/references.py`;
`test_client.py`'s real-Keycloak OAuth2 tests are opt-in/Docker-gated
via the `keycloak_url` fixture but still live in that one file), plus
`test_tests.py` (covers `conftest.py`, `servers.py`, and the
`tests/input-data/*.json` fixtures themselves -- test-support code
with no `src/oapi` module of its own to align with).
- `tests/input-data/*.{yaml,json}` — sample OpenAPI specs used as fixtures.
- `tests/regression-data/` — generated golden model/client modules,
**tracked in git**; compared against on each test run.
- `docs/` — mkdocs-material source (published to oapi.enorganic.org).

## Environment & commands

Uses `hatch` (not bare pip/venv). Python `~=3.10`, tested on 3.10–3.13.

- `make install` — create all hatch envs (first-time setup).
- `make test` — `hatch fmt --check && hatch run mypy && hatch test -c -vv`
(lint check, type check, full test matrix). Run this before considering
work done.
- `make format` — `hatch fmt --formatter && hatch fmt --linter && hatch run mypy`
(auto-fixes formatting/lint, then type-checks).
- `make refresh-test-data` — deletes `tests/regression-data` and reruns
tests to regenerate golden files. Use when a change intentionally
alters generated model/client output; review the diff before committing.
- `make remodel` — regenerate `src/oapi/oas/model.py` via
`scripts/remodel.py`.
- `make docs` — build and serve mkdocs locally.
- Single test: `hatch test -c -vv tests/test_model.py::test_name`.

CI (`.github/workflows/test.yml`) runs `hatch fmt --check && hatch run mypy`
plus `hatch test -c` across OS × Python-version matrix — mirror this
locally before pushing.

## Conventions

- Line length 79 (ruff + black). Ruff is the formatter/linter of record
(`hatch fmt`); black config exists for the `docs` env only.
- mypy strict on new code: `disallow_untyped_defs`,
`disallow_incomplete_defs` — annotate all defs in `src/` and `tests/`.
- Tests run with `--doctest-modules`, so docstring code examples in
`src/` are executed — keep them correct and runnable.
- Don't hand-edit `src/oapi/oas/model.py`; change `scripts/remodel.py` and
run `make remodel` instead.
- Follow existing patterns in `docs/contributing.md` for branch naming
(`feature/...`, `bugfix/...`).
Loading
Loading