Serve Docs (solvcon)

SkillDocs & knowledge

Build the solvcon Sphinx docs and serve them on specified network with guaranteed teardown when the Claude session ends. Use when the user asks to build and serve the documentation, preview the docs, or share the rendered docs online.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Serve Docs (solvcon) skill

What this skill tells your AI

The instructions your AI receives, as published by solvcon/solvcon in .claude/skills/serve-docs/SKILL.md and read by ahel’s review.

Build doc/build/html and serve it on the network interface specified by the user so they can open it from another machine, usually on a trusted network, with a watchdog that shuts the server down within a few seconds of the Claude session ending. There is no documentation build job in CI, so the local build is also the only validation the docs get; always build before serving.

When to use

The user wants to see the rendered docs, preview a doc change, or reach the docs from another machine on the trusted network. This skill owns the build-serve-teardown flow; pair it with commit-code and create-pr when the change is also being landed.

1. Build locally

Doxygen feeds the C++ API page through breathe, so run it before Sphinx; without it the C++ API page renders empty (a warning, not an error). From doc/, run the Doxygen target (make doxygen, which writes the C++ API XML to build/doxygen/xml and needs a system doxygen), then the HTML target (make html, which writes the site to build/html/index.html).

Treat a non-empty make html warning list as a defect to fix. The pre-existing LaTeX siunitx/EPS image warnings from the CESE math pages are environment noise and can be ignored; a warning naming a file you edited cannot. For a faithful rebuild after only comment or XML changes, prefer make clean html (or make doxygen again): Sphinx does not track the Doxygen XML as a dependency and an incremental build can serve stale content.

Whenever you rebuild during a session, report the document address to the user again (section 2): the server keeps serving the same URL, now with the refreshed content.

2. Serve on the specified network, with teardown tied to the session

doc/contrib/serve-docs.sh does the serving. Derive the trusted-network address the user named at run time (never hardcode it, never 0.0.0.0) and pass it as the first argument; an optional second argument pins the port, otherwise the script takes the first free port in 8765-8769.

The script ties the server's lifetime to a launcher PID and tears the server down when that process exits. Its default launcher is its own parent, which is useless here because each command runs in a throwaway shell, so pass the real session with --launcher-pid: the launcher is the nearest ancestor process named claude, found by climbing PPid in /proc/<pid>/status from the shell's parent. Invoke it as doc/contrib/serve-docs.sh <bind-ip> --launcher-pid <pid> (add the port as a second positional argument to pin it).

The script binds python3 -m http.server to that address, starts a watchdog that kills the server within about half a minute of the launcher exiting, probes the URL with curl, and prints it. Report that http://<trusted-network-ip>:<port>/ URL to the user.

Report the URL again after every rebuild: the server serves straight from build/html, so a fresh make html updates the live site at the same address without a restart, no need to rerun the script. If the address has a DNS record, use it.

3. Teardown

The watchdog guarantees teardown: the server is killed within about half a minute of the session process exiting, so nothing is left listening after the session ends. To stop it earlier in the same session, kill the server PID the script printed (or pkill -f "http.server <port>"). A SessionEnd hook is a weaker backstop only, because a mid-session settings edit may not reload; the watchdog is the primary mechanism.

Gotchas

  • Keep the serving logic in the script. doc/contrib/serve-docs.sh is reviewable, checked-in code; do not inline a copy of it back into this skill. Read it before trusting it.
  • Do not switch the script to setsid. With job control setsid forks, so $! is the dead parent, not the python PID, which breaks both the watchdog and any explicit kill. The script uses nohup ... & then disown on purpose.
  • Pass --launcher-pid. The script's default launcher is its parent shell, a throwaway per-command shell here; without the real session PID the watchdog would kill the server almost immediately. Pass the nearest claude ancestor's PID.
  • Bind to the specified network IP, not an all-interfaces address. Binding to all interfaces exposes the server on the local LAN. http.server is unauthenticated, so anyone who can reach the bound address can read everything under build/html; keep it on the trusted network. The script refuses all-interfaces binds (0.0.0.0, ::) and validates the port and launcher PID, but it cannot tell a trusted address from a public one, so deriving the right address is still the caller's job.
  • Port collisions. Sibling worktrees serving their own docs may hold 8000 or 8765; the script skips busy ports.
  • No doc CI. The local make html is the only doc validation, so a clean build matters. A docs-only branch pushed to pg1 auto-skips the heavy CI matrix.

Signals

GitHub stars
76
Forks
73
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
serve-docs
Source
github.com/solvcon/solvcon