boxdown 1.0.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +135 -12
  2. package/assets/devcontainer/README.md +65 -21
  3. package/assets/devcontainer/devcontainer.json +27 -15
  4. package/assets/devcontainer/hooks/initialize.sh +76 -22
  5. package/assets/devcontainer/hooks/post-create.sh +70 -12
  6. package/assets/devcontainer/hooks/post-start.sh +20 -13
  7. package/assets/devcontainer/ssh-config-install.sh +12 -3
  8. package/assets/devcontainer/start.sh +721 -44
  9. package/assets/devcontainer/utils/coding-agent-cli-update.sh +267 -3
  10. package/assets/devcontainer/utils/deps-install.sh +68 -0
  11. package/assets/devcontainer/utils/git-config-bootstrap.sh +128 -0
  12. package/assets/devcontainer/utils/git-signing-bootstrap.sh +109 -0
  13. package/assets/devcontainer/utils/python-bootstrap.sh +69 -0
  14. package/assets/devcontainer/utils/secret-env-bootstrap.sh +22 -0
  15. package/assets/devcontainer/utils/ssh-agent-proxy-bootstrap.sh +27 -0
  16. package/assets/devcontainer/utils/ssh-agent-proxy.mjs +39 -0
  17. package/assets/devcontainer/utils/ssh-bootstrap.sh +9 -0
  18. package/dist/bin/cli.cjs +1 -1
  19. package/dist/bin/cli.mjs +1 -1
  20. package/dist/main-BDgyf2t5.cjs +5758 -0
  21. package/dist/main-J4_2Up3o.mjs +5718 -0
  22. package/dist/main-J4_2Up3o.mjs.map +1 -0
  23. package/dist/main.cjs +5 -2
  24. package/dist/main.d.cts +501 -4
  25. package/dist/main.d.cts.map +1 -1
  26. package/dist/main.d.mts +501 -4
  27. package/dist/main.d.mts.map +1 -1
  28. package/dist/main.mjs +2 -2
  29. package/docs/README.md +1 -0
  30. package/docs/architecture.md +32 -0
  31. package/docs/development.md +13 -6
  32. package/docs/features/README.md +2 -0
  33. package/docs/features/commit-signing.md +94 -0
  34. package/docs/features/generated-config-and-state.md +73 -5
  35. package/docs/features/github-auth-refresh.md +15 -2
  36. package/docs/features/lifecycle.md +103 -11
  37. package/docs/features/setup.md +66 -0
  38. package/docs/features/ssh-config-and-proxy.md +228 -7
  39. package/docs/features/start-and-shell.md +45 -5
  40. package/docs/superpowers/plans/2026-07-11-default-commit-signing.md +110 -0
  41. package/docs/superpowers/plans/2026-07-11-progress-ci-regression.md +125 -0
  42. package/docs/superpowers/plans/2026-07-17-node-ssh-agent-proxy-signing.md +132 -0
  43. package/docs/superpowers/plans/2026-07-17-runtime-secret-environment.md +174 -0
  44. package/docs/superpowers/specs/2026-07-11-default-commit-signing-design.md +416 -0
  45. package/docs/superpowers/specs/2026-07-11-progress-ci-regression-design.md +43 -0
  46. package/docs/superpowers/specs/2026-07-17-node-ssh-agent-proxy-design.md +63 -0
  47. package/docs/superpowers/specs/2026-07-17-runtime-secret-environment-design.md +194 -0
  48. package/docs/testing.md +35 -2
  49. package/docs/todo.md +2 -2
  50. package/package.json +1 -1
  51. package/src/claude-app-config.ts +304 -0
  52. package/src/cli-style.ts +43 -0
  53. package/src/codex-app-config.ts +656 -0
  54. package/src/config.ts +80 -10
  55. package/src/constants.ts +12 -0
  56. package/src/devcontainer.ts +511 -64
  57. package/src/doctor.ts +292 -30
  58. package/src/git-signing.ts +267 -0
  59. package/src/interactive-prompts.ts +692 -0
  60. package/src/list.ts +16 -2
  61. package/src/logging.ts +164 -0
  62. package/src/main.ts +1214 -63
  63. package/src/metadata.ts +52 -3
  64. package/src/package-info.ts +18 -0
  65. package/src/paths.ts +71 -11
  66. package/src/process.ts +80 -2
  67. package/src/progress.ts +593 -0
  68. package/src/purge.ts +216 -0
  69. package/src/shell.ts +25 -0
  70. package/src/ssh-config.ts +134 -16
  71. package/src/ssh-install-targets.ts +111 -0
  72. package/src/ssh-key.ts +53 -13
  73. package/src/status.ts +5 -0
  74. package/dist/main-BuEptwlL.cjs +0 -1707
  75. package/dist/main-ZFTrSVgt.mjs +0 -1685
  76. package/dist/main-ZFTrSVgt.mjs.map +0 -1
@@ -5,27 +5,79 @@ HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
5
  DEVCONTAINER_DIR="$(cd "${HOOKS_DIR}/.." && pwd)"
6
6
 
7
7
  main() {
8
- configure_local_git
9
- install_openssh_server
10
- install_apm
11
- install_or_update_coding_agent_clis
12
- install_1password_cli
13
- install_snyk_cli
14
- run_deps_install
8
+ run_step "Configuring global Git" configure_global_git
9
+ run_step "Configuring Git commit signing" configure_git_signing
10
+ run_step "Configuring workspace Git" configure_local_git
11
+ run_step "Configuring runtime secret environment" configure_runtime_secret_environment
12
+ run_step "Installing OpenSSH server" install_openssh_server
13
+ run_step "Installing Python runtime" install_python_runtime
14
+ run_step "Installing Agent Package Manager" install_apm
15
+ run_step "Installing coding-agent CLIs" install_or_update_coding_agent_clis
16
+ run_step "Installing 1Password CLI" install_1password_cli
17
+ run_step "Installing Snyk CLI" install_snyk_cli
18
+ run_step "Installing workspace dependencies" run_deps_install
19
+ }
20
+
21
+ progress() {
22
+ if [[ "${BOXDOWN_PROGRESS:-0}" == "1" ]]; then
23
+ printf 'BOXDOWN_PROGRESS: %s\n' "$*"
24
+ fi
25
+ }
26
+
27
+ run_step() {
28
+ local label="$1"
29
+ shift
30
+
31
+ progress "$label"
32
+ "$@"
33
+ }
34
+
35
+ configure_global_git() {
36
+ bash "${DEVCONTAINER_DIR}/utils/git-config-bootstrap.sh"
37
+ }
38
+
39
+ configure_git_signing() {
40
+ bash "${DEVCONTAINER_DIR}/utils/git-signing-bootstrap.sh"
15
41
  }
16
42
 
17
43
  configure_local_git() {
18
44
  # Local git prefs only apply inside a repository; skip when there is no .git (avoids postCreate failure).
19
45
  if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
20
- git config --local commit.gpgsign false
21
- git config --local core.pager 'less -R'
22
- git config --local credential.https://github.com.helper '!gh auth git-credential'
46
+ git config --local --replace-all core.pager 'less -R'
47
+ git config --local --unset-all credential.https://github.com.helper >/dev/null 2>&1 || true
48
+ git config --local --add credential.https://github.com.helper ''
49
+ git config --local --add credential.https://github.com.helper '!gh auth git-credential'
50
+ fi
51
+ }
52
+
53
+ configure_runtime_secret_environment() {
54
+ local bashrc="${HOME}/.bashrc"
55
+ local source_line='source /opt/boxdown/devcontainer/utils/secret-env-bootstrap.sh'
56
+
57
+ touch "${bashrc}"
58
+ if ! grep -Fqx "${source_line}" "${bashrc}"; then
59
+ printf '%s\n' "${source_line}" >> "${bashrc}"
23
60
  fi
24
61
  }
25
62
 
26
63
  install_apm() {
27
64
  # Agent Package Manager: https://github.com/microsoft/apm
28
- curl -sSL https://aka.ms/apm-unix | sh
65
+ local installer
66
+
67
+ installer="$(mktemp)"
68
+ if ! curl -fsSL https://aka.ms/apm-unix -o "${installer}"; then
69
+ rm -f "${installer}"
70
+ echo "post-create: warning: could not download APM installer; skipping APM." >&2
71
+ return 0
72
+ fi
73
+
74
+ if ! sh "${installer}"; then
75
+ rm -f "${installer}"
76
+ echo "post-create: warning: APM installer failed; skipping APM." >&2
77
+ return 0
78
+ fi
79
+
80
+ rm -f "${installer}"
29
81
  }
30
82
 
31
83
  install_or_update_coding_agent_clis() {
@@ -37,6 +89,10 @@ install_openssh_server() {
37
89
  bash "${DEVCONTAINER_DIR}/utils/ssh-bootstrap.sh" install
38
90
  }
39
91
 
92
+ install_python_runtime() {
93
+ bash "${DEVCONTAINER_DIR}/utils/python-bootstrap.sh" install
94
+ }
95
+
40
96
  install_snyk_cli() {
41
97
  # https://docs.snyk.io/snyk-cli/install-the-snyk-cli
42
98
  local url
@@ -64,4 +120,6 @@ run_deps_install() {
64
120
  bash "${DEVCONTAINER_DIR}/utils/deps-install.sh"
65
121
  }
66
122
 
67
- main "$@"
123
+ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
124
+ main "$@"
125
+ fi
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env bash
2
2
  # post-start: runs after each container start (postStartCommand in devcontainer.json).
3
- # Naming matches post-create.sh; extend with more steps as needed (e.g. source scripts from .devcontainer/utils/).
3
+ set -euo pipefail
4
+
5
+ DEVCONTAINER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
6
+ bash "${DEVCONTAINER_DIR}/utils/git-signing-bootstrap.sh"
4
7
 
5
8
  set -euo pipefail
6
9
 
@@ -8,9 +11,22 @@ HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
11
  DEVCONTAINER_DIR="$(cd "${HOOKS_DIR}/.." && pwd)"
9
12
 
10
13
  main() {
11
- configure_sshd_runtime
12
- refresh_coding_agent_clis
13
- remove_ephemeral_env_file_if_present
14
+ run_step "Preparing SSH runtime" configure_sshd_runtime
15
+ run_step "Refreshing coding-agent CLIs" refresh_coding_agent_clis
16
+ }
17
+
18
+ progress() {
19
+ if [[ "${BOXDOWN_PROGRESS:-0}" == "1" ]]; then
20
+ printf 'BOXDOWN_PROGRESS: %s\n' "$*"
21
+ fi
22
+ }
23
+
24
+ run_step() {
25
+ local label="$1"
26
+ shift
27
+
28
+ progress "$label"
29
+ "$@"
14
30
  }
15
31
 
16
32
  configure_sshd_runtime() {
@@ -22,13 +38,4 @@ refresh_coding_agent_clis() {
22
38
  echo "post-start: warning: one or more coding-agent CLI refreshes failed." >&2
23
39
  }
24
40
 
25
- # When initializeCommand + runArgs inject secrets via .env.development, remove the file
26
- # after start so it is not left on disk and tooling that assumes absence does not break.
27
- remove_ephemeral_env_file_if_present() {
28
- local env_file=".env.development"
29
- if [[ -f "$env_file" ]]; then
30
- rm -f "$env_file"
31
- fi
32
- }
33
-
34
41
  main "$@"
@@ -89,11 +89,20 @@ write_ssh_config_block() {
89
89
  chmod 0600 "$SSH_CONFIG"
90
90
 
91
91
  tmp_file="$(mktemp)"
92
- awk -v begin="$BEGIN_MARKER" -v end="$END_MARKER" '
92
+ if ! awk -v begin="$BEGIN_MARKER" -v end="$END_MARKER" '
93
93
  $0 == begin { skip = 1; next }
94
- $0 == end { skip = 0; next }
94
+ $0 == end && skip { skip = 0; next }
95
+ skip && $0 ~ /^# (BEGIN|END) [A-Za-z0-9_.-]+ (boxdown )?devcontainer ssh$/ { exit 43 }
95
96
  !skip { print }
96
- ' "$SSH_CONFIG" > "$tmp_file"
97
+ END {
98
+ if (skip) {
99
+ exit 42
100
+ }
101
+ }
102
+ ' "$SSH_CONFIG" > "$tmp_file"; then
103
+ rm -f "$tmp_file"
104
+ die "Refusing to update SSH config for ${HOST_ALIAS}: found \"${BEGIN_MARKER}\" without matching \"${END_MARKER}\" or with an overlapping managed marker. Repair the config manually before running Boxdown again."
105
+ fi
97
106
 
98
107
  start_script_quoted="$(ssh_config_quote "$START_SCRIPT")"
99
108
  key_path_quoted="$(ssh_config_quote "$SSH_KEY_PATH")"