Share Claude Code configuration with PVC direct mount

Both /home/user/.claude/ and /home/user/.claude.json are mounted directly from a dedicated PVC. All changes persist automatically.

The direct mount flow:

  1. A one-time init pod creates an empty skeleton on the PVC: {} in .claude.json and an empty .claude/ directory.

  2. The first workspace starts. The PVC mounts to /home/user/.claude/ and /home/user/.claude.json. Claude Code sees valid, empty configuration.

  3. You configure Claude Code — install plugins, add MCP servers, change settings. All writes go directly to the PVC.

  4. The second workspace starts. The same PVC mounts, and all configuration from the previous workspace is available.

For a comparison with other approaches, see Persist Claude Code configuration in Che workspaces.

Prerequisites
  • An active kubectl session with permissions to create PVCs in your namespace. See Overview of kubectl.

  • Claude Code installed in the workspace container image.

  • For concurrent workspaces: a storage class that supports ReadWriteMany (RWX) access mode, such as AWS EFS or NFS. Standard block storage (gp2, gp3) supports only ReadWriteOnce (RWO).

  • All running workspaces must be stopped before creating the PVC. If a workspace is running when the PVC with the automount label is created, /home/user/.claude.json may be mounted as a directory instead of a file.

Procedure
  1. Create a file claude-config-pvc.yaml with the following PVC definition:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: claude-config
      annotations:
        controller.devfile.io/mount-path: >-
          [{"path":"/home/user/.claude","subPath":".claude"},
           {"path":"/home/user/.claude.json","subPath":".claude.json"}]
      labels:
        controller.devfile.io/mount-to-devworkspace: 'true'
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 1Gi
  2. Apply the PVC to your namespace:

    $ kubectl apply -f claude-config-pvc.yaml -n <your_namespace>
  3. Create the init pod to initialize the PVC.

    The /home/user/.claude.json subPath target must exist as a file on the PVC before any workspace starts. Without this step, Kubernetes kubelet creates a directory instead of a file, and Claude Code fails to parse it.

    Create a file claude-config-init-pod.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: claude-config-init
    spec:
      restartPolicy: Never
      containers:
        - image: registry.access.redhat.com/ubi9/ubi-minimal
          name: init
          command:
            - sh
            - -c
            - |
              mkdir -p /mnt/.claude
              echo '{}' > /mnt/.claude.json
              echo "=== Initialization complete ==="
              ls -la /mnt/
          volumeMounts:
            - mountPath: /mnt
              name: vol
      volumes:
        - name: vol
          persistentVolumeClaim:
            claimName: claude-config
  4. Apply the init pod:

    $ kubectl apply -f claude-config-init-pod.yaml -n <your_namespace>
  5. Wait for the pod to complete:

    $ kubectl wait pod/claude-config-init --for=condition=Ready --timeout=120s
  6. Verify the initialization:

    $ kubectl logs claude-config-init
  7. Delete the init pod:

    $ kubectl delete pod claude-config-init
  8. Start any workspace. The PVC auto-mounts into every workspace pod.

On multi-AZ clusters using WaitForFirstConsumer storage classes (gp2, gp3), the init pod may bind the PV to a different availability zone than workspace pods. See PVC scheduling failure after init pod setup.

Verification
  1. Start a workspace and configure Claude Code (add an MCP server, install a plugin, or modify settings).

  2. Stop and restart the workspace. Verify the configuration is preserved.

  3. Start a different workspace. Verify the same configuration is available.

Filtering by workspace name

Control which workspaces mount the PVC by adding annotations:

annotations:
  controller.devfile.io/mount-to-devworkspace-include: '<pattern>' (1)
  controller.devfile.io/mount-to-devworkspace-exclude: '<pattern>' (2)
1 Mount the PVC only to workspaces whose names match the pattern.
2 Mount the PVC to all workspaces except those whose names match the pattern.

Supported patterns: exact match (name), prefix (name*), suffix (\*name), contains (\*name\*). Matching is on the DevWorkspace resource name.

Concurrent workspaces

Access mode Behavior

ReadWriteOnce (RWO)

One workspace at a time. Two workspaces on different nodes cause a multi-attach error.

ReadWriteMany (RWX)

Concurrent workspaces work. Requires a storage class that supports RWX, such as AWS EFS or NFS. Standard block storage (gp2, gp3) does not support RWX.

Compatibility with persistUserHome

A dedicated PVC mounted at /home/user/.claude and the persistent home PVC mounted at /home/user/ coexist correctly as nested mounts. Writes to /home/user/.claude/ go to the dedicated PVC. Writes to other paths under /home/user/ go to the persistent home PVC.

If you only need persistence within a single workspace and not cross-workspace sharing, persistUserHome alone is sufficient.

Limitations

  • Requires manual PVC setup per user namespace.

  • RWX storage may not be available on all clusters.

  • On clusters with only block storage and multi-AZ topology, the init pod may cause scheduling failures. Use the tmp copy approach instead.