3030 echo ' {}' > /root/.docker-container/config.json
3131fi
3232
33+ # Download bash-preexec if it doesn't exist (required for atuin/starship)
34+ if [ ! -f ~ /.bash-preexec.sh ]; then
35+ echo " Downloading bash-preexec..."
36+ curl -sL https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~ /.bash-preexec.sh
37+ fi
38+
3339# Initialize bashrc if needed
3440if [ ! -f ~ /.bashrc ] || [ ! -s ~ /.bashrc ] || ! grep -q ' common-bashrc' ~ /.bashrc; then
3541 echo " Initializing ~/.bashrc..."
@@ -59,11 +65,11 @@ if [ -n "$DOCKER_SOCKET_PROXY" ]; then
5965fi
6066
6167# Source common bash configuration (aliases and functions)
62- source /workspace /dev-scripts/common-bashrc.sh
68+ source /usr/local/share /dev-scripts/common-bashrc.sh
6369
6470# Source the virtual environment (must use source, not bash)
65- if [ -f /workspace /dev-scripts/use-venv ]; then
66- source /workspace /dev-scripts/use-venv
71+ if [ -f /usr/local/share /dev-scripts/use-venv ]; then
72+ source /usr/local/share /dev-scripts/use-venv
6773fi
6874
6975# Load bash-preexec (required for atuin and starship to work with VS Code)
@@ -84,19 +90,26 @@ if command -v starship &> /dev/null; then
8490 eval "$(starship init bash)"
8591fi
8692
87- # Fix for VS Code shell integration overriding PROMPT_COMMAND
88- # Ensure bash-preexec hooks are called so atuin and starship work
89- if declare -F __bp_precmd_invoke_cmd &>/dev/null; then
90- # Prepend bash-preexec to PROMPT_COMMAND if not already there
91- if [[ "$PROMPT_COMMAND" != *"__bp_precmd_invoke_cmd"* ]]; then
92- PROMPT_COMMAND="__bp_precmd_invoke_cmd; $PROMPT_COMMAND"
93+ # Fix for VS Code shell integration overriding bash-preexec's DEBUG trap
94+ # VS Code loads its shell integration after bashrc, so we restore the trap on each prompt
95+ __restore_bash_preexec_trap() {
96+ if declare -F __bp_preexec_invoke_exec &>/dev/null; then
97+ local current_trap=\$(trap -p DEBUG)
98+ if [[ "\$current_trap" != *"__bp_preexec_invoke_exec"* ]]; then
99+ trap '__bp_preexec_invoke_exec "\$_"' DEBUG
100+ fi
93101 fi
102+ }
103+
104+ # Add the trap restoration to PROMPT_COMMAND
105+ if [[ "\$PROMPT_COMMAND" != *"__restore_bash_preexec_trap"* ]]; then
106+ PROMPT_COMMAND="__restore_bash_preexec_trap\${PROMPT_COMMAND:+; \$PROMPT_COMMAND}"
94107fi
95108
96109# asdf version manager
97- if [ -f "$HOME/.asdf/asdf.sh" ]; then
98- . "$HOME/.asdf/asdf.sh"
99- . "$HOME/.asdf/completions/asdf.bash"
110+ if [ -f "\ $HOME/.asdf/asdf.sh" ]; then
111+ . "\ $HOME/.asdf/asdf.sh"
112+ . "\ $HOME/.asdf/completions/asdf.bash"
100113fi
101114EOF
102115fi
@@ -108,8 +121,9 @@ if command -v atuin &> /dev/null; then
108121 # Create atuin data directory if it doesn't exist
109122 mkdir -p ~ /.local/share/atuin ~ /.config/atuin
110123
111- # Generate default config with explicit paths
112- cat > ~ /.config/atuin/config.toml << 'ATUINCONF '
124+ # Generate default config with explicit paths (only if it doesn't exist)
125+ if [ ! -f ~ /.config/atuin/config.toml ]; then
126+ cat > ~ /.config/atuin/config.toml << 'ATUINCONF '
113127## Atuin configuration for CloudHarness dev container
114128
115129## Explicitly set paths to avoid VS Code XDG_DATA_HOME issues
@@ -132,6 +146,7 @@ secrets_filter = true
132146enter_accept = true
133147history_filter = ["^secret", "^password", "AWS_SECRET", "KUBECONFIG"]
134148ATUINCONF
149+ fi
135150
136151 # Import existing bash history
137152 if [ -f ~ /.bash_history ]; then
@@ -140,6 +155,132 @@ ATUINCONF
140155 fi
141156fi
142157
158+ # Create Starship config if it doesn't exist
159+ if [ ! -f ~ /.config/starship.toml ]; then
160+ echo " Creating Starship prompt configuration..."
161+ mkdir -p ~ /.config
162+ cat > ~ /.config/starship.toml << 'STARSHIPCONF '
163+ # Starship prompt configuration for CloudHarness dev container
164+ # Documentation: https://starship.rs/config/
165+
166+ # Timeout for starship to run (in milliseconds)
167+ command_timeout = 1000
168+
169+ # Add a new line before the prompt
170+ add_newline = true
171+
172+ # Format of the prompt
173+ format = """
174+ [╭─](bold green)$username\
175+ $hostname\
176+ $directory\
177+ $git_branch\
178+ $git_status\
179+ $python\
180+ $nodejs\
181+ $docker_context\
182+ $kubernetes
183+ [╰─](bold green)$character"""
184+
185+ [character]
186+ success_symbol = "[➜](bold green)"
187+ error_symbol = "[✗](bold red)"
188+
189+ [username]
190+ style_user = "bold yellow"
191+ style_root = "bold red"
192+ format = "[$user]($style) "
193+ disabled = false
194+ show_always = true
195+
196+ [hostname]
197+ ssh_only = false
198+ format = "[@$hostname](bold blue) "
199+ disabled = false
200+
201+ [directory]
202+ truncation_length = 3
203+ truncate_to_repo = true
204+ format = "[$path]($style)[$read_only]($read_only_style) "
205+ style = "bold cyan"
206+ read_only = " 🔒"
207+
208+ [git_branch]
209+ symbol = " "
210+ format = "on [$symbol$branch]($style) "
211+ style = "bold purple"
212+
213+ [git_status]
214+ format = '([\[$all_status$ahead_behind\]]($style) )'
215+ style = "bold red"
216+ conflicted = "🏳"
217+ ahead = "⇡${count}"
218+ behind = "⇣${count}"
219+ diverged = "⇕⇡${ahead_count}⇣${behind_count}"
220+ untracked = "?${count}"
221+ stashed = "$${count}"
222+ modified = "!${count}"
223+ staged = "+${count}"
224+ renamed = "»${count}"
225+ deleted = "✘${count}"
226+
227+ [python]
228+ symbol = " "
229+ format = 'via [${symbol}${pyenv_prefix}(${version} )(\($virtualenv\) )]($style)'
230+ style = "yellow"
231+ pyenv_version_name = false
232+ detect_extensions = ["py"]
233+ detect_files = [".python-version", "Pipfile", "__pycache__", "pyproject.toml", "requirements.txt", "setup.py", "tox.ini"]
234+ detect_folders = []
235+
236+ [nodejs]
237+ symbol = " "
238+ format = "via [$symbol($version )]($style)"
239+ style = "bold green"
240+
241+ [docker_context]
242+ symbol = " "
243+ format = "via [$symbol$context]($style) "
244+ style = "blue bold"
245+ only_with_files = true
246+ detect_files = ["docker-compose.yml", "docker-compose.yaml", "Dockerfile"]
247+ detect_folders = []
248+
249+ [kubernetes]
250+ symbol = "☸ "
251+ format = 'on [$symbol$context( \($namespace\))]($style) '
252+ style = "cyan bold"
253+ disabled = false
254+ detect_files = ["k8s"]
255+ detect_folders = ["k8s"]
256+
257+ [kubernetes.context_aliases]
258+ "docker-desktop" = "🐳 desktop"
259+ "kind-.*" = "kind"
260+ "minikube" = "mini"
261+
262+ [cmd_duration]
263+ min_time = 500
264+ format = "took [$duration](bold yellow) "
265+
266+ [time]
267+ disabled = false
268+ format = '🕙[\[ $time \]]($style) '
269+ time_format = "%T"
270+ style = "bold white"
271+
272+ [memory_usage]
273+ disabled = true
274+ threshold = -1
275+ symbol = " "
276+ format = "via $symbol[${ram_pct}]($style) "
277+ style = "bold dimmed white"
278+
279+ [package]
280+ disabled = true
281+ STARSHIPCONF
282+ fi
283+
143284# Create tmux config if it doesn't exist
144285if [ ! -f ~ /.tmux.conf ]; then
145286 cat > ~ /.tmux.conf << 'EOF '
0 commit comments