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
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Container-side Python runtime setup for the repo-local devcontainer workflow.
4
+
5
+ set -euo pipefail
6
+
7
+ PYTHON_PACKAGES=(python3 python3-venv python3-pip pipx)
8
+
9
+ progress() {
10
+ if [ "${BOXDOWN_PROGRESS:-0}" = "1" ]; then
11
+ printf 'BOXDOWN_PROGRESS: %s\n' "$*"
12
+ fi
13
+ }
14
+
15
+ as_root() {
16
+ if [ "$(id -u)" -eq 0 ]; then
17
+ "$@"
18
+ else
19
+ sudo "$@"
20
+ fi
21
+ }
22
+
23
+ python_runtime_ready() {
24
+ command -v python3 >/dev/null 2>&1 || return 1
25
+ python3 -m venv --help >/dev/null 2>&1 || return 1
26
+ python3 -m pip --version >/dev/null 2>&1 || return 1
27
+ command -v pipx >/dev/null 2>&1 || return 1
28
+ }
29
+
30
+ apt_lists_present() {
31
+ find /var/lib/apt/lists -mindepth 1 -type f -name '*_Packages*' -print -quit 2>/dev/null | grep -q .
32
+ }
33
+
34
+ install_python_packages() {
35
+ as_root env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "${PYTHON_PACKAGES[@]}"
36
+ }
37
+
38
+ install_python_runtime() {
39
+ if python_runtime_ready; then
40
+ return 0
41
+ fi
42
+
43
+ progress "Installing Python runtime packages"
44
+ if ! apt_lists_present; then
45
+ as_root apt-get update
46
+ fi
47
+
48
+ if ! install_python_packages; then
49
+ as_root apt-get update
50
+ install_python_packages
51
+ fi
52
+
53
+ as_root rm -rf /var/lib/apt/lists/*
54
+ python_runtime_ready
55
+ }
56
+
57
+ main() {
58
+ case "${1:-install}" in
59
+ install)
60
+ install_python_runtime
61
+ ;;
62
+ *)
63
+ echo "Usage: $(basename "$0") [install]" >&2
64
+ return 1
65
+ ;;
66
+ esac
67
+ }
68
+
69
+ main "$@"
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+ # Shell bootstrap for Boxdown runtime-mounted secret environment files.
3
+
4
+ SECRET_ENV_DIR="${BOXDOWN_SECRET_ENV_DIR:-/run/boxdown/secrets}"
5
+
6
+ export_if_present() {
7
+ local name="$1"
8
+ local path="${SECRET_ENV_DIR}/${name}"
9
+ local value
10
+
11
+ [[ -r "${path}" ]] || return 0
12
+ IFS= read -r value < "${path}" || true
13
+
14
+ if [[ -n "${value}" ]]; then
15
+ export "${name}=${value}"
16
+ fi
17
+ }
18
+
19
+ export_if_present ANTHROPIC_API_KEY
20
+ export_if_present SNYK_TOKEN
21
+ export_if_present OP_SERVICE_ACCOUNT_TOKEN
22
+ unset value
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ # Expose a root-only forwarded SSH-agent socket to the non-root container user.
3
+
4
+ set -euo pipefail
5
+
6
+ SOURCE_SOCKET="${BOXDOWN_GIT_SIGNING_SOURCE_SOCKET:-/run/boxdown/ssh-agent.sock}"
7
+ TARGET_SOCKET="${SSH_AUTH_SOCK:-/run/boxdown/ssh-agent-node.sock}"
8
+ PROXY_SCRIPT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/ssh-agent-proxy.mjs"
9
+
10
+ if ssh-add -L >/dev/null 2>&1; then
11
+ exit 0
12
+ fi
13
+
14
+ if ! command -v sudo >/dev/null 2>&1 || ! command -v node >/dev/null 2>&1; then
15
+ exit 1
16
+ fi
17
+
18
+ sudo -n node "${PROXY_SCRIPT}" --source "${SOURCE_SOCKET}" --target "${TARGET_SOCKET}" --uid "$(id -u)" --gid "$(id -g)" >/dev/null 2>&1 &
19
+
20
+ for _ in $(seq 1 20); do
21
+ if [[ -S "${TARGET_SOCKET}" ]] && ssh-add -L >/dev/null 2>&1; then
22
+ exit 0
23
+ fi
24
+ sleep 0.1
25
+ done
26
+
27
+ exit 1
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { chmodSync, chownSync, existsSync, unlinkSync } from 'node:fs'
4
+ import { createConnection, createServer } from 'node:net'
5
+
6
+ function option (name) {
7
+ const index = process.argv.indexOf(name)
8
+ return index === -1 ? undefined : process.argv[index + 1]
9
+ }
10
+
11
+ const source = option('--source')
12
+ const target = option('--target')
13
+ const uid = Number(option('--uid'))
14
+ const gid = Number(option('--gid'))
15
+
16
+ if (source === undefined || target === undefined || !Number.isInteger(uid) || !Number.isInteger(gid)) {
17
+ process.stderr.write('ssh-agent-proxy: expected --source, --target, --uid, and --gid.\n')
18
+ process.exit(2)
19
+ }
20
+
21
+ if (existsSync(target)) unlinkSync(target)
22
+
23
+ const server = createServer((client) => {
24
+ const upstream = createConnection(source)
25
+ client.pipe(upstream)
26
+ upstream.pipe(client)
27
+ client.on('error', () => upstream.destroy())
28
+ upstream.on('error', () => client.destroy())
29
+ })
30
+
31
+ server.on('error', (error) => {
32
+ process.stderr.write(`ssh-agent-proxy: ${error.message}\n`)
33
+ process.exit(1)
34
+ })
35
+
36
+ server.listen(target, () => {
37
+ chmodSync(target, 0o600)
38
+ chownSync(target, uid, gid)
39
+ })
@@ -11,6 +11,12 @@ SSH_USER="${DEVCONTAINER_SSH_USER:-node}"
11
11
  PUBLIC_KEY_FILE="${DEVCONTAINER_SSH_PUBLIC_KEY_FILE:-${WORKSPACE_FOLDER}/.devcontainer/.ssh/id_ed25519.pub}"
12
12
  OPENSSH_CONFIGURE_TIMEOUT_SECONDS="${DEVCONTAINER_OPENSSH_CONFIGURE_TIMEOUT_SECONDS:-180}"
13
13
 
14
+ progress() {
15
+ if [ "${BOXDOWN_PROGRESS:-0}" = "1" ]; then
16
+ printf 'BOXDOWN_PROGRESS: %s\n' "$*"
17
+ fi
18
+ }
19
+
14
20
  as_root() {
15
21
  if [ "$(id -u)" -eq 0 ]; then
16
22
  "$@"
@@ -98,10 +104,12 @@ ensure_openssh_server_configured() {
98
104
 
99
105
  install_openssh_server() {
100
106
  if [ ! -x /usr/sbin/sshd ]; then
107
+ progress "Installing openssh-server packages"
101
108
  as_root apt-get update
102
109
  as_root env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends openssh-server
103
110
  fi
104
111
 
112
+ progress "Configuring openssh-server"
105
113
  ensure_openssh_server_configured
106
114
  }
107
115
 
@@ -164,6 +172,7 @@ ensure_runtime_ready() {
164
172
  return 1
165
173
  fi
166
174
 
175
+ progress "Preparing SSH daemon runtime"
167
176
  ensure_openssh_server_configured
168
177
  as_root ssh-keygen -A
169
178
  as_root install -d -m 0755 /run/sshd
package/dist/bin/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_main = require('../main-BuEptwlL.cjs');
2
+ const require_main = require('../main-BDgyf2t5.cjs');
3
3
 
4
4
  //#region src/bin/cli.ts
5
5
  require_main.runCli().then((exitCode) => {
package/dist/bin/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as runCli } from "../main-ZFTrSVgt.mjs";
2
+ import { o as runCli } from "../main-J4_2Up3o.mjs";
3
3
 
4
4
  //#region src/bin/cli.ts
5
5
  runCli().then((exitCode) => {