Skip to content

xunc · Container session

xuns runs inside a Docker container; the host only creates the container, forwards environment variables and wires the output back to your terminal.

git clone https://github.com/MenxLi/xun.git
cd xun
make build-docker      # build the frontend first, then docker build -t xun -f docker/Dockerfile .

xunc                   # sandbox: an ephemeral workspace inside the container
xunc .                 # bind-mount the current directory as /workspace in the container
xunc --copy .          # copy the current directory into /workspace (nothing is written back to the host)

Parameters

Parameter Form Default Description
mount positional, optional nothing mounted host directory bind-mounted as /workspace in the container (resolve() is applied first)
--copy flag False copy that directory into /workspace instead; errors out when mount is not given
--image string xun image to use
--name string xun-<first 8 chars of md5> container name; by default the hash is taken from the mount path (from the image name when nothing is mounted)
--network bridge / host bridge bridge publishes the --port ports; host shares the host network namespace (on macOS the Docker VM's, so the host browser cannot open the URL)
--port list of strings 18960 ports to publish on the host; accepts comma-separated values or repeated flags; --port "" publishes no ports at all
--env list of strings empty comma-separated: NAME=VALUE assigns directly; a token without = acts as a wildcard forwarded from the host
--exec string see below command to run inside the container; an empty string uses the image's default CMD

When --exec is not given: if mount was provided it uses xuns . --host 0.0.0.0 (the positional . is /workspace, so the session workspace is the mount point itself), otherwise xuns '' --host '0.0.0.0' (one temporary workspace per session).

The three shapes of the working directory

Invocation /workspace in the container Where the data goes
xunc the empty directory shipped in the image gone as soon as the container is destroyed
xunc . bind mount (read-write) lands directly in the host directory, writes are persisted
xunc --copy . a copy changes inside the container do not go back to the host

Note that working_dir is set to /workspace whenever mount is given, so the agent inside the container starts in the mount point.

Environment variable forwarding

XUN_* and _XUN_* are always forwarded into the container, with no explicit declaration needed. --env adds to that baseline:

xunc . --env "XUN_AUTO_CONFIRM=true,_XUN_DEFAULT_MAX_ITER=384,HTTPS_PROXY"
  • NAME=VALUE: assign directly
  • bare NAME or MY_*: forwarded from the host environment by fnmatch
  • XUN_HOME cannot be overridden (it is fixed to /.xun in the image); forcing an assignment prints a warning and is ignored

Copying the xun home

When the container is created, the host xun home ($XUN_HOME, or .xun/ inside the host's current directory when it is unset) is copied into the container's /.xun, taking only config.json and extensions/ (HOME_COPY_INCLUDE) — session history and x/ (the xunx user store) are not carried over. That is why the container can still read the same secret placeholders and extensions.

Lifecycle and output

The container is created with auto_remove=True, stdin_open, tty and working_dir=/workspace (when mounted). xunc forwards host stdin into the container and echoes container output back to the host; after Ctrl+C the container is force-removed. So the URL you see in the browser is the one printed by xuns inside the container:

Agents are available at the following URLs:
http://0.0.0.0:18960/chat/?session=%2F&token=...   (aka http://localhost:18960/chat/?...)

In bridge mode the host port equals the container port (18960 is published by default), so simply copy the localhost:18960 line; with --port "" there is no reachable port, which suits one-off --exec tasks such as how this repository generates its documentation:

xunc . \
    --env "XUN_AUTO_CONFIRM=true,_XUN_DEFAULT_MAX_ITER=384" \
    --exec "xun --non-interactive '请按照docs/AGENTS.md的要求制作文档'" \
    --name "xun-doc" \
    --port ""

The repository's Makefile freezes this one-shot pattern into two targets: make doc (build the bilingual documentation from scratch) and make doc-update (refresh it according to the most recent source changes). Both pass only --env "XUN_AUTO_CONFIRM=true" (unlike the example above, which also forwards _XUN_DEFAULT_MAX_ITER); only the --exec prompt differs.

Containers are disposable

xunc removes its container automatically on exit, so the ephemeral workspace inside it and any saved sessions are lost. Use a bind mount (xunc .) to keep data, or switch to the persistent xunx instead.