Skip to content

Commit 0b8f12d

Browse files
chapterjasonclaude
andcommitted
Persist JetBrains Gateway state, drop .idea/ via global gitignore
Add a jetbrains home-persist manifest so the IDE backend Gateway downloads into ~/.cache/JetBrains/RemoteDev/dist/ (hundreds of MB per IDE) plus per-IDE settings, plugins, project indexes, and JetProfile login survive workspace restarts. Also write .idea/ to ~/.config/git/ignore in git_setup so the per-project JetBrains dir stays out of every repo the user touches without per-repo .gitignore edits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 78ce1b2 commit 0b8f12d

5 files changed

Lines changed: 56 additions & 2 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Images are published to GHCR under `ghcr.io/sourecode/coder-workspace`.
1515

1616
| Tag | Base | Adds |
1717
|---|---|---|
18-
| `base` | `debian:trixie-slim` | systemd + dockerd + `nvm` + `claude-code` + `rtk` + `context-mode` + `web-shell` + `home-persist` |
18+
| `base` | `debian:trixie-slim` | systemd + dockerd + `nvm` + `claude-code` + `rtk` + `context-mode` + `web-shell` + `home-persist` + `jetbrains` |
1919
| `node` | `:base` | named variant for future Node-specific tooling — currently identical to `base` (Node comes from nvm) |
2020
| `cpp` | `:base` | `llvm` (clang + toolchain), `cmake`, `sccache`, `/etc/profile.d/llvm-env.sh` exporting `CC`/`CXX` |
2121

@@ -31,6 +31,7 @@ the workspace in Coder.
3131
| `context-mode` | [`context-mode`](https://github.com/mksglu/context-mode) Claude plugin | Installed via a post-create hook so it lands in the persisted `~/.claude/plugins` |
3232
| `nvm` | [nvm](https://github.com/nvm-sh/nvm) at `/usr/local/share/nvm` | Default Node = LTS, `node`/`npm`/`npx` in `/usr/local/bin` |
3333
| `web-shell` | [web-shell](https://github.com/SoureCode/web-shell), persistent browser terminal | systemd unit, registered as a Coder app |
34+
| `jetbrains` | JetBrains Gateway remote backend persistence | Headless-only: Toolbox/Gateway runs on the user's local machine, opens a `jetbrains-gateway://` URL that SSHes in and runs `remote-dev-server.sh` here. Declares `~/.cache/JetBrains/`, `~/.config/JetBrains/`, `~/.local/share/JetBrains/`, `~/.java/.userPrefs/jetbrains/` to `home-persist` so the downloaded IDE backend, per-IDE settings, plugins, project indexes and JetProfile login survive workspace restarts. |
3435
| `home-persist` | Manifest-driven `$HOME` persistence | Reads `/etc/home-persist.d/*.json`, symlinks declared paths under `/mnt/home-persist` (per-owner volume). Add extra per-workspace paths via the `home_persist_paths` Coder parameter. See [`docs/persistence.md`](docs/persistence.md). |
3536
| `llvm` (cpp) | Clang toolchain via [apt.llvm.org](https://apt.llvm.org/) | `CC=clang`, `CXX=clang++` via `/etc/profile.d/llvm-env.sh` |
3637
| `cmake` (cpp) | CMake from [Kitware's GitHub releases](https://cmake.org/) | latest by default |

docs/persistence.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ Properties that fall out:
103103
| Source | Paths | Why |
104104
| ------------- | ----------------------------- | ------------------------------------ |
105105
| `claude-code` | `.claude/`, `.claude.json` | Login credentials, sessions, plugins |
106+
| `jetbrains` | `.cache/JetBrains/`, `.config/JetBrains/`, `.local/share/JetBrains/`, `.java/.userPrefs/jetbrains/` | The workspace is headless — Toolbox/Gateway runs on the user's local machine. Clicking the IDE button opens a `jetbrains-gateway://` URL; Gateway SSHes in and has `remote-dev-server.sh` download the IDE backend into `~/.cache/JetBrains/RemoteDev/dist/` on first connect (hundreds of MB per IDE). The three JetBrains roots keep the downloaded backend plus per-IDE `RemoteDev-<Code>/` settings, plugins, and project indexes. `.java/.userPrefs/jetbrains/` is the Java `Preferences` store the IDEs use for JetBrains Account / JetProfile login, license activation, and non-commercial-license acceptance — persisting it avoids re-login on every restart. |
106107

107108
Anything not declared is image-owned (or per-workspace-home-volume-owned)
108109
and resets on image rebuild — git config, SSH keys, bash history, caches.

main.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,13 @@ resource "coder_script" "git_setup" {
253253
git config --global commit.gpgsign true
254254
git config --global tag.gpgsign true
255255
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
256+
257+
# Global gitignore. Git auto-picks $XDG_CONFIG_HOME/git/ignore as
258+
# core.excludesFile on Linux — no extra config needed. Keeps IDE-local
259+
# project state (JetBrains .idea/) out of every repo the user touches,
260+
# without needing per-repo .gitignore edits.
261+
mkdir -p ~/.config/git
262+
printf '.idea/\n' > ~/.config/git/ignore
256263
EOT
257264
}
258265

scripts/jetbrains/install.sh

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env bash
2+
# jetbrains installer.
3+
#
4+
# How the Coder JetBrains flow works: the workspace is headless. Clicking the
5+
# IDE button in the Coder UI opens a `jetbrains-gateway://` URL that the
6+
# user's *local* Toolbox/Gateway handles; Gateway then SSHes into the
7+
# workspace and runs remote-dev-server.sh, which downloads the IDE backend
8+
# (IntelliJ IDEA, PyCharm, CLion, WebStorm, GoLand, RubyMine, PhpStorm,
9+
# Rider, DataGrip) on-demand into $HOME. Toolbox itself never runs on the
10+
# workspace. Nothing to install in the image — this script only declares the
11+
# HOME paths the remote-dev backend writes, so Gateway doesn't redownload
12+
# hundreds of MB and users don't lose settings, plugins, and project indexes
13+
# on every restart.
14+
#
15+
# JetBrains' remote-dev backend follows the XDG scheme on Linux with a
16+
# RemoteDev-<Code> subdir per IDE flavor (PS = PhpStorm, PY = PyCharm, IU =
17+
# IDEA Ultimate, CL = CLion, ...) under these three roots:
18+
#
19+
# ~/.cache/JetBrains/ — RemoteDev/dist/<build>/ (downloaded backend),
20+
# RemoteDev-<Code>/ system caches, indexes,
21+
# LocalHistory, log
22+
# ~/.config/JetBrains/ — RemoteDev-<Code>/ IDE settings, keymaps,
23+
# schemes, options, workspace, .lock
24+
# ~/.local/share/JetBrains/ — RemoteDev-<Code>/ installed plugins,
25+
# Daemon, consentOptions
26+
#
27+
# Plus the Java Preferences store the IDEs use for JetBrains Account
28+
# (JetProfile) login, license activation, and non-commercial-license
29+
# acceptance — skipping this forces re-login + re-accept every restart:
30+
#
31+
# ~/.java/.userPrefs/jetbrains/
32+
set -e
33+
34+
mkdir -p /etc/home-persist.d
35+
tee /etc/home-persist.d/jetbrains.json >/dev/null <<'EOF'
36+
{
37+
"source": "jetbrains",
38+
"paths": [
39+
".cache/JetBrains/",
40+
".config/JetBrains/",
41+
".local/share/JetBrains/",
42+
".java/.userPrefs/jetbrains/"
43+
]
44+
}
45+
EOF

src/base/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ ENV _REMOTE_USER=${USERNAME}
8080

8181
# System-wide installers run as root.
8282
RUN --mount=type=bind,source=scripts,target=/scripts \
83-
for s in context-mode home-persist; do \
83+
for s in context-mode home-persist jetbrains; do \
8484
bash "/scripts/$s/install.sh"; \
8585
done
8686

0 commit comments

Comments
 (0)