Skip to content

Publish Stripe World as an OpenEnv Hugging Face Space, on Seahaven 0.6.0 - #11

Merged
scosman merged 21 commits into
mainfrom
claude/seahaven-hub-61adee0
Oct 8, 2026
Merged

scosman merged 21 commits into
mainfrom
claude/seahaven-hub-61adee0

Conversation

@scosman

@scosman scosman commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

This branch makes Stripe World publishable with openenv push. It is live at https://huggingface.co/spaces/scosman/stripe_world. It also moves the world from a git-pinned Seahaven to the 0.6.0 release on PyPI.

Hub files

seahaven hub generated the root Dockerfile, __init__.py, client.py, models.py and openenv.yaml, which openenv push requires. All five are byte-identical to what Seahaven 0.6.0 renders.

The Dockerfile:

  • copies in uv 0.12.18;
  • installs CPython 3.14 into /opt/uv/python;
  • starts the server with python -m uvicorn, so it runs as the Space's uid 1000;
  • runs the health check with the venv's Python.

The root __init__.py makes the checkout a package, so two tools_dev import blocks were re-sorted for ruff.

README and releasing

  • The README gains a "Try it on Hugging Face Spaces →" link and a "Connecting to the published world" section. Its example uses AutoEnv.from_hub("scosman/stripe_world", skip_install=True) to create a customer with stripe_api_write.

  • The README has no Space front matter, because GitHub would render it as a table at the top of the repository page. Hugging Face only reads a Space's settings from that front matter. .github/RELEASING.md is the release checklist, and it sets the card on the Space itself:

    1. take a fresh clone;
    2. run openenv validate;
    3. run openenv push --repo-id scosman/stripe_world;
    4. set the card with huggingface_hub.metadata_update: the title, emoji, colours, a short_description of 60 characters or fewer, base_path: /console and the tags;
    5. test the Space.

    AGENTS.md points to the checklist.

Seahaven 0.6.0

  • The dependency is now seahaven~=0.6 from PyPI, and the [tool.uv.sources] git pin is gone. In the lock, only the seahaven entry changes.
  • Nothing is fetched over git any more, so the image needs no git, and the CI step that set up the SEAHAVEN_CORE_TOKEN credential is removed. That repository secret can now be deleted.
  • AGENTS.md, docs/technical.md and comments no longer describe a private or commit-pinned Seahaven. They also no longer claim that seahaven.openenv cannot import on 3.14.

Verification

  • CI checks on 0.6.0: 1104 passed, 2 skipped, and seahaven check is clean.
  • openenv validate: reports only the missing validation: block. A Seahaven world has no reward to declare.
  • Image, emulated on the host: built as root, run as uid 1000. /health, /console, the health check and an AutoEnv.from_hub session all pass.
  • The Space: deployed from an earlier head of this branch, pinned to the Seahaven commit that became 0.6.0's hub template, and it works.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp

scosman and others added 21 commits October 8, 2026 19:52
Moves `[tool.uv.sources] seahaven` from 0360978 to
61adee0f244bdfcbd163f6fa14dd8da260fc7000 and re-locks. The lock changes
only the seahaven entry (0.0.1 -> 0.5.0); no other package moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Seahaven 0.5.0 is on PyPI and Kiln-AI/Seahaven is public, so the comment's
'unpublished', 'placeholder PyPI release' and 'private repository / CI
credential' statements were false. The commit-pin rationale is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Output of `uv run seahaven hub`, unedited: the root Dockerfile, __init__.py,
client.py, models.py and openenv.yaml that `openenv push` validates for, the
Hugging Face Space front matter at the top of README.md, and the
"Connecting to the published world" section. The app it serves,
`src/seahaven_stripe_world/openenv_app.py`, was already present.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
The `__init__.py` that `openenv push` requires at the repository root makes
the checkout itself a package, so ruff's isort no longer counts `tools_dev`
as the importing file's own package and classifies it as third-party, the
way `tests/` already does. `ruff check --fix` on the two files that
imported both `tools_dev` and `conformance`; import order only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
`ghcr.io/huggingface/openenv-base:latest` is built from OpenEnv main's
src/openenv/core/containers/images/Dockerfile: python:3.11-slim with uv
0.5.27 copied in. uv 0.5.27's newest downloadable CPython 3.14 is 3.14.0a4,
a pre-release, so the generated `RUN uv sync --extra serve` stops with "No
interpreter found for Python >=3.14" and the Space cannot build. Reproduced
on the host with the uv 0.5.27 wheel and only Python 3.11 available.

Copy uv 0.12.18, the version that wrote uv.lock, over the base image's
before the sync; it downloads CPython 3.14.7. This patches output of
`seahaven hub`, whose template has the same defect; drop it when the template
is fixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Reviewing what `seahaven hub` wrote into the README:

- The connecting example named the `<owner>/seahaven-stripe-world`
  placeholder and called `create_item`, the scaffold's example tool, which
  this world does not have. It now connects to `Kiln-AI/stripe_world` and
  creates a customer with `stripe_api_write`, in test mode. Run verbatim
  (plus `base_url`) against a local server from a Python 3.11 client with
  only openenv 0.5.0 installed.
- The section was appended after "Created by Kiln AI", because this README
  has no `## Using it` heading. It now follows the examples, and the
  OpenEnv example points to it.
- The Space title is the world's name, Stripe World, not the distribution
  name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Hugging Face Docker Spaces run the container as uid 1000; the build runs
as root. Emulated on the host (root `uv sync --extra serve` in /app, then
the CMD as uid 1000 via setpriv), the image failed two ways:

- uv installed CPython 3.14 under /root/.local/share/uv/python, and /root
  is mode 700, so /app/.venv/bin/python could not be resolved
  ("failed to canonicalize path `/app/.venv/bin/python`: Permission
  denied"). The HEALTHCHECK still passed, because PATH lookup fell
  through to the base image's Python 3.11, so it hid the failure.
- `uv run` could not create its cache ("Failed to initialize cache at
  `/.cache/uv`: Permission denied" with HOME=/; the same under any
  HOME uid 1000 cannot write).

Install Python under /opt/uv/python (UV_PYTHON_INSTALL_DIR, before the
sync), and set UV_NO_CACHE=1 and UV_NO_SYNC=1 after it, so `uv run`
writes nothing. Verified as uid 1000 with HOME=/, HOME=/home/user and
HOME unset: the server starts, /health, /console and /web/ answer 200,
the HEALTHCHECK runs the venv's CPython 3.14.7, and an AutoEnv drive
creates and reads a customer. `python -m uvicorn` as uid 1000 (the
Modal/Daytona start) also serves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
The Hugging Face build failed at `uv sync --extra serve` with "Git executable
not found": pyproject.toml pins Seahaven to a git commit, and openenv-base has
no git. The uv download of CPython 3.14.7 and the resolve both worked on the
real build.

The HEALTHCHECK now runs the venv's interpreter by path, so it fails when that
interpreter is unusable instead of falling back to the base image's Python 3.11.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Adds a "Try it on Hugging Face Spaces" link above "How real is it?", and points
the connecting example at the published Space, scosman/stripe_world.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Moves `[tool.uv.sources] seahaven` from 61adee0 to
7c00046adf082457dae492bac202bea87dab9cd9 and re-locks. The lock changes
only the seahaven source; the version stays 0.5.0 and no other package
moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Replaces the Dockerfile with what the pinned Seahaven's `seahaven hub`
renders for seahaven_stripe_world, and re-adds the one world-specific
block: the apt `git` install before the sync, which the commit-pinned
Seahaven source needs. The rest is byte for byte the template.

The template now carries this world's earlier fixes itself: uv 0.12.18,
UV_PYTHON_INSTALL_DIR=/opt/uv/python and the venv-path HEALTHCHECK. Its CMD
is `python -m uvicorn` instead of `uv run`, so UV_NO_CACHE/UV_NO_SYNC
are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Without `short_description`, Hugging Face wrote its own card text ("Run
commands in a web-based console") from the console page, and picked a default
emoji. These are the Space config keys the card reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
`seahaven~=0.6` in place of `seahaven~=0.0`, and the `[tool.uv.sources]`
git pin to 7c00046 is gone with its comment. 0.6.0 is the release tagged
v0.6.0 (cff1ab3). `uv lock` resolves seahaven 0.6.0 from PyPI with its
sdist and wheel hashes; no other package moves. The serve and mcp extras
are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Seahaven now comes from PyPI, so uv no longer fetches a git source and
the image needs no git executable. The Dockerfile is now byte for byte
what Seahaven 0.6.0's `seahaven hub` renders for seahaven_stripe_world, as
are __init__.py, client.py, models.py and openenv.yaml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Seahaven now comes from PyPI, so CI fetches no git source and needs no
SEAHAVEN_CORE_TOKEN. The step and its comment are gone, and so is the
concurrency comment's 'every job costs a Seahaven clone'. The install
comment no longer says `seahaven.openenv` cannot import on 3.14: with
the locked beartype 0.22.9 it imports on CPython 3.14.7. CI still skips
the `serve` extra, because no suite needs it.

The SEAHAVEN_CORE_TOKEN repository secret is now unused and can be
deleted in the repository settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
AGENTS.md described Seahaven as a commit-pinned git source in a private
repository. It is now `seahaven~=0.6` from PyPI, pinned by uv.lock. The
CI paragraph no longer names a `rev` in `[tool.uv.sources]`. AGENTS.md and
the comment on the `http` extra in pyproject.toml no longer say openenv
cannot import on 3.14, because `seahaven.openenv` imports on CPython
3.14.7 with the locked beartype 0.22.9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
The Development and Framework sections said Seahaven came from a
private repository at a pinned commit SHA. It is now `seahaven~=0.6`
from PyPI, with the exact version in uv.lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
GitHub renders YAML front matter in a README as a table at the top of the
repository page. Hugging Face only reads a Space's settings from that front
matter, so the README now has none, and .github/RELEASING.md sets the card on
the Space after each `openenv push` with huggingface_hub's metadata_update:
title, emoji, colours, the 60-character short_description, base_path /console
and the tags. Without it, push writes its own defaults (base_path /web).

The checklist covers a release end to end: a fresh clone, validate, push, set
the card, and test the Space with AutoEnv.from_hub(..., skip_install=True).
AGENTS.md points to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QWJSvm3Hep8BHqyKWBkKvp
@scosman
scosman merged commit bb5e9c8 into main Oct 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant