Skip to content

Commit a37b627

Browse files
akurinnoyclaude
andcommitted
docs: Add Claude Code configuration persistence guides
Add documentation for persisting and sharing Claude Code configuration across Eclipse Che workspaces under a new "AI coding tools in workspaces" section in the User Guide. New pages: - Overview of Claude Code configuration files and available approaches - Dedicated PVC with automount (Option A: direct mount, Option B: /tmp copy) - GitOps approach using a central Git repository - Troubleshooting known issues with configuration persistence Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Oleksii Kurinnyi <okurinny@redhat.com>
1 parent 09e6dfe commit a37b627

6 files changed

Lines changed: 612 additions & 0 deletions

modules/end-user-guide/nav.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636
** xref:microsoft-visual-studio-code-open-source-ide.adoc[]
3737
** xref:connect-visual-studio-code-to-che-workspace.adoc[]
3838
** xref:defining-a-common-ide.adoc[]
39+
* xref:ai-coding-tools-in-workspaces.adoc[]
40+
** xref:persisting-claude-code-configuration.adoc[]
41+
*** xref:sharing-claude-code-configuration-with-a-dedicated-pvc.adoc[]
42+
*** xref:sharing-claude-code-configuration-with-gitops.adoc[]
43+
*** xref:troubleshooting-claude-code-configuration-persistence.adoc[]
3944
* xref:using-credentials-and-configurations-in-workspaces.adoc[]
4045
** xref:mounting-secrets.adoc[]
4146
*** xref:creating-image-pull-secrets.adoc[]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
:_content-type: ASSEMBLY
2+
:description: Use AI coding tools in {prod-short} workspaces and persist their configuration across workspaces.
3+
:keywords: user-guide, ai, coding, tools, claude-code
4+
:navtitle: AI coding tools in workspaces
5+
:page-aliases:
6+
7+
[id="ai-coding-tools-in-workspaces"]
8+
= AI coding tools in workspaces
9+
10+
{prod-short} workspaces support AI coding tools such as Claude Code.
11+
12+
* xref:persisting-claude-code-configuration.adoc[]
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
:_content-type: ASSEMBLY
2+
:description: Persist and share Claude Code configuration across {prod-short} workspaces.
3+
:keywords: user-guide, claude-code, ai, configuration, persistence, pvc
4+
:navtitle: Persisting Claude Code configuration
5+
:page-aliases:
6+
7+
[id="persisting-claude-code-configuration"]
8+
= Persisting Claude Code configuration in {prod-short} workspaces
9+
10+
New {prod-short} workspaces start without Claude Code configuration. Developers must set up skills, settings, MCP servers, and plugins from scratch in each workspace.
11+
12+
To avoid repeating this setup, persist the Claude Code configuration in a shared volume or a Git repository and reuse it across workspaces.
13+
14+
== Claude Code configuration files
15+
16+
Claude Code stores configuration in two separate locations in the user home directory:
17+
18+
|===
19+
| Path | Contents
20+
21+
| `{prod-home}/.claude/`
22+
| Settings, plugins, custom agents, hooks, per-project memory.
23+
24+
| `{prod-home}/.claude.json`
25+
| Application settings and MCP server configurations.
26+
|===
27+
28+
[IMPORTANT]
29+
====
30+
MCP server configurations are stored in `{prod-home}/.claude.json`, a separate file at the home directory root, not inside `{prod-home}/.claude/`. Both locations must be persisted.
31+
====
32+
33+
[NOTE]
34+
====
35+
Claude Code writes runtime state to both `{prod-home}/.claude/` and `{prod-home}/.claude.json` during every session, including session files, caches, and usage statistics. These paths must be writable. Mounting a read-only ConfigMap or Secret directly to these paths causes Claude Code to fail.
36+
====
37+
38+
== Available approaches
39+
40+
|===
41+
| Approach | Summary
42+
43+
| xref:sharing-claude-code-configuration-with-a-dedicated-pvc.adoc[]
44+
| A dedicated PVC in the user {orch-namespace} shares configuration across all workspaces. The {devworkspace} Operator automatically mounts PVCs labeled with `controller.devfile.io/mount-to-devworkspace: true` into every workspace pod.
45+
46+
| xref:sharing-claude-code-configuration-with-gitops.adoc[]
47+
| A Git repository stores the baseline Claude Code configuration. The {devworkspace} Operator clones the repository at startup, and a `postStart` command copies the configuration into the home directory.
48+
|===
49+
50+
== Claude Code file reference
51+
52+
|===
53+
| Path | Purpose | Size | Regeneratable
54+
55+
| `~/.claude/settings.json`
56+
| Permissions, hooks, enabled plugins, model preferences.
57+
| Small
58+
| No
59+
60+
| `~/.claude/settings.local.json`
61+
| Local setting overrides.
62+
| Small
63+
| No
64+
65+
| `~/.claude/CLAUDE.md`
66+
| User-level instructions for Claude.
67+
| Small
68+
| No
69+
70+
| `~/.claude/plugins/`
71+
| Installed plugins and caches.
72+
| Large (100{nbsp}MB+)
73+
| Partially
74+
75+
| `~/.claude/agents/`
76+
| Custom agent definitions.
77+
| Small
78+
| No
79+
80+
| `~/.claude/hooks/`
81+
| Shell scripts for session lifecycle.
82+
| Small
83+
| No
84+
85+
| `~/.claude/projects/`
86+
| Per-project memory and settings.
87+
| Medium
88+
| No
89+
90+
| `~/.claude.json`
91+
| Application settings and MCP server configurations.
92+
| Small
93+
| No
94+
95+
| `~/.claude/history.jsonl`
96+
| Conversation history.
97+
| Large
98+
| Optional
99+
100+
| `~/.claude/plugins/cache/`
101+
| Plugin download cache.
102+
| Large
103+
| Yes
104+
|===
105+
106+
.Additional resources
107+
108+
* xref:sharing-claude-code-configuration-with-a-dedicated-pvc.adoc[]
109+
* xref:sharing-claude-code-configuration-with-gitops.adoc[]
110+
* xref:troubleshooting-claude-code-configuration-persistence.adoc[]
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
:_content-type: PROCEDURE
2+
:description: Share Claude Code configuration across {prod-short} workspaces by using a dedicated PVC with automount.
3+
:keywords: user-guide, claude-code, ai, configuration, persistence, pvc, automount
4+
:navtitle: Sharing configuration with a dedicated PVC
5+
:page-aliases:
6+
7+
[id="sharing-claude-code-configuration-with-a-dedicated-pvc"]
8+
= Sharing Claude Code configuration across workspaces with a dedicated PVC
9+
10+
A dedicated PVC in the user {orch-namespace} shares Claude Code configuration across all workspaces. The {devworkspace} Operator automatically mounts PVCs labeled with `controller.devfile.io/mount-to-devworkspace: true` into every workspace pod.
11+
12+
Two options are available:
13+
14+
* *Option A: Direct mount* — both `{prod-home}/.claude/` and `{prod-home}/.claude.json` are mounted directly from the PVC. All changes persist automatically. Requires a one-time init pod to pre-create `.claude.json`.
15+
* *Option B: Full `/tmp` copy* — the entire PVC is mounted at `/tmp/claude`. A `postStart` command copies everything into the home directory. No init pod is required, but changes must be synced back manually before stopping the workspace.
16+
17+
|===
18+
| Feature | Option A: Direct mount | Option B: Full `/tmp` copy
19+
20+
| Init pod required
21+
| Yes (one-time)
22+
| No
23+
24+
| `postStart` required
25+
| No
26+
| Yes
27+
28+
| Manual sync before stop
29+
| No
30+
| Yes
31+
32+
| AZ affinity risk
33+
| Yes (RWO on multi-AZ clusters)
34+
| Yes (RWO on multi-AZ clusters)
35+
|===
36+
37+
For an overview of all approaches, see xref:persisting-claude-code-configuration.adoc[].
38+
39+
.Prerequisites
40+
41+
* An active `{orch-cli}` session with permissions to create PVCs in your {orch-namespace}. See {orch-cli-link}.
42+
43+
* Claude Code installed in the workspace container image.
44+
45+
* 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).
46+
47+
== Option A: Direct mount
48+
49+
All Claude Code configuration is mounted directly from the PVC. Changes persist automatically without any `postStart` commands or manual sync steps.
50+
51+
=== Creating the PVC
52+
53+
. Create a file `claude-config-pvc.yaml` with the following PVC definition:
54+
+
55+
====
56+
[source,yaml,subs="+quotes,+attributes"]
57+
----
58+
kind: PersistentVolumeClaim
59+
apiVersion: v1
60+
metadata:
61+
name: claude-config
62+
annotations:
63+
controller.devfile.io/mount-path: >-
64+
[{"path":"{prod-home}/.claude","subPath":".claude"},
65+
{"path":"{prod-home}/.claude.json","subPath":".claude.json"}]
66+
labels:
67+
controller.devfile.io/mount-to-devworkspace: 'true'
68+
spec:
69+
accessModes:
70+
- ReadWriteMany
71+
resources:
72+
requests:
73+
storage: 1Gi
74+
----
75+
====
76+
77+
. Apply the PVC to your {orch-namespace}:
78+
+
79+
[subs="+quotes,+attributes"]
80+
----
81+
$ {orch-cli} apply -f claude-config-pvc.yaml -n __<your_{orch-namespace}>__
82+
----
83+
84+
=== Initializing the PVC with an init pod
85+
86+
The `{prod-home}/.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.
87+
88+
. Create a file `claude-config-init-pod.yaml` with the following pod definition:
89+
+
90+
====
91+
[source,yaml,subs="+quotes,+attributes"]
92+
----
93+
apiVersion: v1
94+
kind: Pod
95+
metadata:
96+
name: claude-config-init
97+
spec:
98+
containers:
99+
- image: registry.access.redhat.com/ubi9/ubi-minimal
100+
name: init
101+
command:
102+
- sh
103+
- -c
104+
- |
105+
mkdir -p /mnt/.claude
106+
echo '{}' > /mnt/.claude.json
107+
echo "=== Initialization complete ==="
108+
ls -la /mnt/
109+
tail -f /dev/null
110+
volumeMounts:
111+
- mountPath: /mnt
112+
name: vol
113+
volumes:
114+
- name: vol
115+
persistentVolumeClaim:
116+
claimName: claude-config
117+
----
118+
====
119+
120+
. Apply the init pod, wait for it to initialize, verify, and delete:
121+
+
122+
[subs="+quotes,+attributes"]
123+
----
124+
$ {orch-cli} apply -f claude-config-init-pod.yaml -n __<your_{orch-namespace}>__
125+
$ {orch-cli} wait pod/claude-config-init --for=condition=Ready --timeout=120s
126+
$ {orch-cli} logs claude-config-init
127+
$ {orch-cli} delete pod claude-config-init
128+
----
129+
130+
=== Using workspaces
131+
132+
Start any workspace. The PVC auto-mounts into every workspace pod. Claude Code finds its configuration at `{prod-home}/.claude/` and `{prod-home}/.claude.json` on startup. All changes, including new MCP servers, plugins, and settings, are written directly to the PVC and available in every workspace.
133+
134+
No `postStart` commands or manual sync steps are required.
135+
136+
[WARNING]
137+
====
138+
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 xref:troubleshooting-claude-code-configuration-persistence.adoc#pvc-scheduling-failure-after-init-pod-setup[PVC scheduling failure after init pod setup].
139+
====
140+
141+
=== Verification
142+
143+
. Start a workspace and configure Claude Code (add an MCP server, install a plugin, or modify settings).
144+
. Stop and restart the workspace. Verify the configuration is preserved.
145+
. Start a different workspace. Verify the same configuration is available.
146+
147+
== Option B: Full `/tmp` copy
148+
149+
The entire PVC is mounted at `/tmp/claude`. A `postStart` command copies everything into the home directory. No init pod is required and there are no subPath limitations.
150+
151+
=== Creating the PVC
152+
153+
. Create a file `claude-config-pvc.yaml` with the following PVC definition:
154+
+
155+
====
156+
[source,yaml,subs="+quotes,+attributes"]
157+
----
158+
kind: PersistentVolumeClaim
159+
apiVersion: v1
160+
metadata:
161+
name: claude-config
162+
annotations:
163+
controller.devfile.io/mount-path: '[{"path":"/tmp/claude","subPath":"claude"}]'
164+
labels:
165+
controller.devfile.io/mount-to-devworkspace: 'true'
166+
spec:
167+
accessModes:
168+
- ReadWriteMany
169+
resources:
170+
requests:
171+
storage: 1Gi
172+
----
173+
====
174+
175+
. Apply the PVC to your {orch-namespace}:
176+
+
177+
[subs="+quotes,+attributes"]
178+
----
179+
$ {orch-cli} apply -f claude-config-pvc.yaml -n __<your_{orch-namespace}>__
180+
----
181+
182+
=== Adding a `postStart` command to copy configurations
183+
184+
Add a `postStart` command to your devfile to copy all configuration from the PVC into the home directory:
185+
186+
====
187+
[source,yaml,subs="+quotes,+attributes"]
188+
----
189+
commands:
190+
- id: init-claude-config
191+
exec:
192+
commandLine: |
193+
mkdir -p {prod-home}/.claude
194+
cp -a /tmp/claude/.claude/. {prod-home}/.claude/ 2>/dev/null || true
195+
cp /tmp/claude/.claude.json {prod-home}/.claude.json 2>/dev/null || true
196+
component: __<editor_container>__ # <1>
197+
events:
198+
postStart:
199+
- init-claude-config
200+
----
201+
<1> Replace with the name of your editor container component in the devfile.
202+
====
203+
204+
=== Syncing changes before stopping
205+
206+
Changes to both `{prod-home}/.claude/` and `{prod-home}/.claude.json` are written to the home directory, not the PVC. Sync everything back before stopping:
207+
208+
[subs="+quotes,+attributes"]
209+
----
210+
$ cp -a {prod-home}/.claude/. /tmp/claude/.claude/ && \
211+
cp {prod-home}/.claude.json /tmp/claude/.claude.json
212+
----
213+
214+
=== Verification
215+
216+
. Start a workspace and configure Claude Code.
217+
. Sync changes back to the PVC.
218+
. Start a different workspace.
219+
. Verify that the Claude Code configuration from the first workspace is available.
220+
221+
== Shared options for both variants
222+
223+
=== Filtering by workspace name
224+
225+
Control which workspaces mount the PVC by adding annotations:
226+
227+
[source,yaml,subs="+quotes,+attributes"]
228+
----
229+
annotations:
230+
controller.devfile.io/mount-to-devworkspace-include: '__<pattern>__' # <1>
231+
controller.devfile.io/mount-to-devworkspace-exclude: '__<pattern>__' # <2>
232+
----
233+
<1> Mount the PVC only to workspaces whose names match the pattern.
234+
<2> Mount the PVC to all workspaces except those whose names match the pattern.
235+
236+
Supported patterns: `*` (all), `prefix*`, `*suffix`, `*contains*`, `exact-name`. Matching is on the {devworkspace} resource name.
237+
238+
=== Concurrent workspaces
239+
240+
|===
241+
| Access mode | Behavior
242+
243+
| ReadWriteOnce (RWO)
244+
| One workspace at a time. Two workspaces on different nodes cause a multi-attach error.
245+
246+
| ReadWriteMany (RWX)
247+
| 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.
248+
|===
249+
250+
== Limitations
251+
252+
* Requires manual PVC setup per user {orch-namespace}.
253+
* Can be combined with `persistUserHome`. The dedicated PVC at `{prod-home}/.claude` and the persistent home PVC at `{prod-home}/` coexist correctly as nested mounts.
254+
* RWX storage may not be available on all clusters.
255+
* On clusters with only block storage and multi-AZ topology, the Option A init pod may cause scheduling failures. Use Option B instead.
256+
257+
.Additional resources
258+
259+
* xref:persisting-claude-code-configuration.adoc[]
260+
* xref:sharing-claude-code-configuration-with-gitops.adoc[]
261+
* xref:troubleshooting-claude-code-configuration-persistence.adoc[]
262+
* xref:requesting-persistent-storage-for-workspaces.adoc[]

0 commit comments

Comments
 (0)