claude-cli executes whatever is in the BROWSER env variable to open your browser at a current URL, so I pointed it at a simple shell script that writes the URL to a named pipe which is mounted into the container. The sandbox tool outside of the container is reading from that named pipe. When it receives a URL to open, it pops up a confirmation dialog with info about the URL. If you accept, it opens it in your host browser.
The second step is, the callback URL after you sign in on the claude website wants to connect back to a port on localhost to complete the sign in. If the sandbox is being run with host networking mode, this just works fine as claude cli has already opened that port so it's listening on the host network. However if it is not running in host networking mode, the sandbox tool figures out what port it need to listen on from looking at the URL, listens to it, and when it is hit, it just podman exec's curl inside the container to complete the callback.
When they try to open a browser, they also print the URL to the console. Open that in your browser and go through an authentication flow; it'll end forwarding you to a localhost URL like http://127.0.0.1:8080/authorization-code/callback?code=XXXX&... which will fail.
Copy that callback URL, connect to your VM/docker container, and curl it.
The curl stage requires the agent make a call to auth.whatever-vendor.com so if it fails at this stage, check your VM/container network settings. And make sure you quoted the curl right so the & wasn't misinterpreted.
It'll then save a file at ~/.codex/auth.json or ~/.claude.json or similar, so you won't need to log in again. The secret in this file will periodically rotate, so you need to mount it read-write not read-only.