bootstrap
Adom Hydrogen (platform base)
Public Made by Adomby adom
Layer Hydrogen's workspace onto a standard Adom workstation.
← Commit history
0.5.4: MERGE code-server settings.json instead of overwriting it. The cat > ran every hook window and silently destroyed anything the user had written there, with no message and no backup.
2 files changed
+92−36
install.sh+91−34@@ -108,42 +108,99 @@ fi # because claudeCode.initialPermissionMode stays "auto", and Claude Code still # shows its own one-time consent dialog before bypass takes effect. Nothing here # pre-accepts that dialog.-log "writing code-server settings.json"+log "merging code-server settings.json (managed keys only)" install -d -m 0755 "$HOME/.local/share/code-server/User"-cat > "$HOME/.local/share/code-server/User/settings.json" <<'SETTINGS'-{- "security.workspace.trust.enabled": false,- "security.workspace.trust.untrustedFiles": "open",- "workbench.startupEditor": "none",- "workbench.activityBar.location": "default",- "workbench.activityBar.iconClickBehavior": "toggle",- "workbench.colorTheme": "Adom Studio Dark (Brighter Text)",- "editor.fontSize": 15,- "workbench.statusBar.visible": false,- "workbench.navigationControl.enabled": false,- "workbench.secondarySideBar.visible": false,- "workbench.secondarySideBar.defaultVisibility": "hidden",- "claudeCode.allowDangerouslySkipPermissions": true,- "claudeCode.initialPermissionMode": "auto",- "claudeCode.preferredLocation": "panel",- "chat.agent.enabled": false,- "chat.commandCenter.enabled": false,- "chat.agentsControl.enabled": false,- "chat.unifiedAgentsBar.enabled": false,- "github.copilot.chat.enabled": false,- "github.copilot.enable": { "*": false },- "github.gitAuthentication": false,- "git.autofetch": false,- "scm.defaultViewMode": "tree",- "security.trustedDomains": ["*"],- "workbench.trustedDomains.promptInTrustedWorkspace": false,- "remote.portsAttributes": { "8821": { "onAutoForward": "silent" } },- "remote.otherPortsAttributes": { "onAutoForward": "silent" },- "remote.autoForwardPortsSource": "hybrid",- "extensions.autoUpdate": true,- "extensions.autoCheckUpdates": true+# MERGE, NEVER OVERWRITE. This block used to `cat >` the whole file, so every+# hook window (every 30 minutes) silently destroyed anything the user had put in+# their own VS Code settings: keybinding tweaks, font choices, extension config,+# formatter rules. They are power users; they absolutely will have written other+# stuff, and it came back deleted with no message and no backup.+#+# Now: ah OWNS the keys below and re-asserts them, and EVERY OTHER KEY THE USER+# HAS IS PRESERVED UNTOUCHED. A one-time backup is taken the first time a merge+# would change anything, so a user who lost settings to the old behaviour still+# has whatever was there at the moment we started merging.+python3 - "$HOME/.local/share/code-server/User/settings.json" <<'PYSETTINGS' || true+import json, os, shutil, sys++path = sys.argv[1]++# The managed set: what ah needs true for the product to behave. Anything not in+# here belongs to the user and is never written, reordered or removed by us.+MANAGED = {+ "security.workspace.trust.enabled": False,+ "security.workspace.trust.untrustedFiles": "open",+ "workbench.startupEditor": "none",+ "workbench.activityBar.location": "default",+ "workbench.activityBar.iconClickBehavior": "toggle",+ "workbench.colorTheme": "Adom Studio Dark (Brighter Text)",+ "editor.fontSize": 15,+ "workbench.statusBar.visible": False,+ "workbench.navigationControl.enabled": False,+ "workbench.secondarySideBar.visible": False,+ "workbench.secondarySideBar.defaultVisibility": "hidden",+ # TRUE only makes the "Bypass permissions" row APPEAR in the Modes menu.+ # Adom users are power users and that choice is theirs (John 2026-08-25).+ # Auto stays the default via initialPermissionMode, and Claude Code still+ # shows its own one-time consent dialog before bypass takes effect.+ "claudeCode.allowDangerouslySkipPermissions": True,+ "claudeCode.initialPermissionMode": "auto",+ "claudeCode.preferredLocation": "panel",+ "chat.agent.enabled": False,+ "chat.commandCenter.enabled": False,+ "chat.agentsControl.enabled": False,+ "chat.unifiedAgentsBar.enabled": False,+ "github.copilot.chat.enabled": False,+ "github.copilot.enable": {"*": False},+ "github.gitAuthentication": False,+ "git.autofetch": False,+ "scm.defaultViewMode": "tree",+ "security.trustedDomains": ["*"],+ "workbench.trustedDomains.promptInTrustedWorkspace": False,+ "remote.portsAttributes": {"8821": {"onAutoForward": "silent"}},+ "remote.otherPortsAttributes": {"onAutoForward": "silent"},+ "remote.autoForwardPortsSource": "hybrid",+ "extensions.autoUpdate": True,+ "extensions.autoCheckUpdates": True, }-SETTINGS++existing, unreadable = {}, False+if os.path.exists(path):+ try:+ with open(path) as f:+ existing = json.load(f)+ if not isinstance(existing, dict):+ existing, unreadable = {}, True+ except Exception:+ # A settings.json we cannot parse is NOT a settings.json we may replace:+ # it is far more likely a user mid-edit than a corrupt file, and the old+ # behaviour would have thrown their work away. Back it up and start from+ # the managed set rather than merging into something we cannot read.+ unreadable = True++if unreadable and os.path.exists(path):+ shutil.copy2(path, path + ".unreadable.bak")+ print(" settings.json was not readable JSON: kept a copy at settings.json.unreadable.bak")+ existing = {}++merged = dict(existing)+merged.update(MANAGED)++if merged != existing:+ # One-time safety net for anyone who still has settings from before the merge.+ if os.path.exists(path) and not os.path.exists(path + ".pre-merge.bak"):+ shutil.copy2(path, path + ".pre-merge.bak")+ tmp = path + ".tmp"+ with open(tmp, "w") as f:+ json.dump(merged, f, indent=2)+ f.write("\n")+ os.replace(tmp, path) # atomic: never a half-written settings file+ kept = [k for k in existing if k not in MANAGED]+ print(" merged %d managed key(s); preserved %d of the user's own: %s"+ % (len(MANAGED), len(kept), ", ".join(sorted(kept)[:6]) or "none"))+else:+ print(" settings.json already correct, nothing written")+PYSETTINGS # 5. code-server config.yaml — silence code-server's own update nags. install -d -m 0755 "$HOME/.config/code-server"
package.json+1−2@@ -4,10 +4,9 @@ "type": "bootstrap", "title": "Adom Hydrogen (platform base)", "brief": "Layer Hydrogen's workspace onto a standard Adom workstation.",- "version": "0.5.3",+ "version": "0.5.4", "description": "Hydrogen's PLATFORM-GENERIC workspace layer on top of adom/core. Installs adom/core for the full Adom ecosystem, then adds everything common to running inside Hydrogen on ANY platform: the runtime-neutral hydrogen-* skills and the generic editor configuration (Claude Code CLI + extension, VS Code settings, trusted domains). Platform-specific layers depend on THIS: adom/hydrogen-windows-bootstrap (WSL2), adom/hydrogen-mac-bootstrap, adom/hydrogen-ubuntu-bootstrap. The reference design other orgs copy to build their own bootstrap on adom/core.", "org": "adom",- "platform": "any", "tags": [ "bootstrap", "hydrogen",