fix: honor --dry-run across install phases; repair repo conventions and doc drift

- spawn() now respects DRY_RUN, install.sh exports it to child phases, and
  postinstall.sh wraps every user-home mutation in run() — '--dry-run' no
  longer runs apt/install/clone or edits dotfiles for real
- gen-docs.sh chmods regenerated files to 644 (mktemp mv left them at 0600)
- make check now syntax-checks apps/, entertainment/, features/, templates/
- .gitignore protects config/authorized_keys + config/rclone.conf; drop the
  tracked empty authorized_keys and the stray 6 MB session file
- pos-system-health --send prints 'sent:' only when a platform sender exists,
  otherwise warns on stderr (notify_send is silent-fail)
- standardize sourced libs (no shebang); refresh AGENT_Context/DEV/APPS/SCRIPTS
  doc drift: notify.sh in lib lists, pos-health systemd units, tsui, scripts/,
  INTERACTIVE_CMDS list, entertainment scheduler (systemd timers only)
This commit is contained in:
Your Name
2026-08-09 03:01:58 -04:00
parent 7dff27206b
commit 16bc6685f8
16 changed files with 126 additions and 57 deletions
+6 -1
View File
@@ -20,4 +20,9 @@ Thumbs.db
compose/custom/
compose/config.env
session
# Secrets — never commit real keys/certs
config/authorized_keys
config/rclone.conf
# Stray session capture (accidentally created in the repo root)
session
+2
View File
@@ -16,6 +16,8 @@ summary (newest last).
## Done
- **2026-08-09** — Structure/convention audit fix: `--dry-run` now truly dry (`spawn()` honors `DRY_RUN`, install.sh exports it to child phases, postinstall mutations run-wrapped); `gen-docs.sh` no longer chmods regenerated files to 0600; `make check` now syntax-checks apps/entertainment/features/templates; `.gitignore` protects `config/authorized_keys` + `config/rclone.conf`; honest `--send` confirmation; docs refreshed (notify.sh in lib lists, pos-health systemd units, tsui, scripts/, INTERACTIVE_CMDS).
- **2026-08-07** — `pos system health --send` notification-only; listener `@quiet` prefix (run mapped command without replying, for commands that self-notify). `/status=@quiet pos system health --send` = exactly one digest.
## Now
+47 -29
View File
@@ -10,19 +10,19 @@
<!-- GEN:START docmap -->
| ## 1. Project Overview | 2843 |
| ## 2. Directory Structure | 44168 |
| ## 3. Installation Flow | 169220 |
| ## 4. The `pos` CLI System | 221281 |
| ## 5. Shared Library — `lib/common.sh` | 282312 |
| ## 6. Docker Compose / ScaleTail | 313355 |
| ## 7. Optional Apps (`apps/`) | 356385 |
| ## 8. Entertainment Module | 386399 |
| ## 9. Systemd Services | 400410 |
| ## 10. Configuration Files | 411434 |
| ## 11. Coding Conventions | 435467 |
| ## 12. Development Workflow | 468519 |
| ## 13. Key File Quick Reference | 520565 |
| ## 14. Common Tasks for Agents | 566590 |
| ## 2. Directory Structure | 44179 |
| ## 3. Installation Flow | 180232 |
| ## 4. The `pos` CLI System | 233293 |
| ## 5. Shared Library — `lib/common.sh` | 294325 |
| ## 6. Docker Compose / ScaleTail | 326368 |
| ## 7. Optional Apps (`apps/`) | 369398 |
| ## 8. Entertainment Module | 399412 |
| ## 9. Systemd Services | 413425 |
| ## 10. Configuration Files | 426451 |
| ## 11. Coding Conventions | 452484 |
| ## 12. Development Workflow | 485536 |
| ## 13. Key File Quick Reference | 537583 |
| ## 14. Common Tasks for Agents | 584608 |
<!-- GEN:END docmap -->
## 1. Project Overview
@@ -50,8 +50,9 @@ Linux_post_install/
├── postinstall.sh # Phase 3: PATH, bash completion, systemd services
├── lib/
│ ├── common.sh # Shared library (colors, logging, spinner, timer, run)
│ ├── common.sh # Shared library (colors, logging, spinner, timer, run, load_system_env)
│ ├── flags.sh # Feature flag store (flag_set/clear/is_set/value/list/status)
│ ├── notify.sh # Multi-platform alerting (notify_send) — sourced opt-in, silent-fails
│ └── entertainment-lib.sh # Entertainment module lib (ENABLED list, scheduler sync)
├── bin/ # CLI tools — installed to /usr/local/bin/
@@ -132,7 +133,8 @@ Linux_post_install/
│ └── utilities/
│ ├── affine.sh # AFFiNE knowledge base (AppImage)
│ ├── btop.sh # btop resource monitor (apt)
── localsend.sh # LocalSend (flatpak)
── localsend.sh # LocalSend (flatpak)
│ └── tsui.sh # Tailscale config TUI (official install script)
├── completions/
│ └── pos.bash # Bash tab-completion for the pos CLI
@@ -146,7 +148,14 @@ Linux_post_install/
├── systemd/
│ ├── autostart.service # Runs autostart.sh on boot
── ssh-agent.service # System-wide SSH agent socket
── ssh-agent.service # System-wide SSH agent socket
│ ├── pos-health.service # Runs the health digest as the installing user (triggered by timer)
│ └── pos-health.timer # Daily 08:00 trigger for the health digest (enabled when Telegram is configured)
├── scripts/ # Dev tooling
│ ├── gen-docs.sh # Regenerates code-derived doc sections + completion flags
│ ├── check-sync.sh # `make check` gate (syntax, exec bits, doc/code sync, smoke)
│ └── install-hooks.sh # Installs the opt-in pre-commit hook (`make hook`)
├── README.md # User-facing intro + quick start (links into DOC/)
@@ -157,6 +166,8 @@ Linux_post_install/
│ ├── APPS.md # Optional apps reference
│ ├── SYSTEMD.md # Systemd units + completion
│ ├── DEV.md # Developer guide
│ ├── HOWTO.md # Hands-on guides index (per-category tutorials)
│ ├── howto/ # Per-category tutorials (network, docker, media, system, ssh, usb, communication, entertainment)
│ ├── AGENT_Context_Project.md # This file — AI agent context
│ └── algorithm.md # Algorithm diagrams
@@ -176,7 +187,7 @@ User runs: ./install.sh [--apps|--full|--feature|--dry-run|--skip <phase>|--step
├─ Phase 2: install.sh (requires root)
│ └─ Copies bin/* → /usr/local/bin/ (chmod 755)
│ └─ Copies lib/common.sh + lib/flags.sh + lib/entertainment-lib.sh → /usr/local/bin/ (chmod 644)
│ └─ Copies lib/common.sh + lib/flags.sh + lib/notify.sh + lib/entertainment-lib.sh → /usr/local/bin/ (chmod 644)
│ └─ Copies x64_bin/* → /usr/local/bin/ on x86_64 (arm64_bin/ on aarch64)
│ └─ [if --feature] Copies features/* → /usr/local/bin/ (asks before overwriting),
│ then sets the matching feature flag
@@ -185,8 +196,9 @@ User runs: ./install.sh [--apps|--full|--feature|--dry-run|--skip <phase>|--step
│ └─ Configures fail2ban (SSH jail: 5 retries, 1h ban)
│ └─ PATH export in ~/.bashrc
│ └─ Bash completion for pos CLI
│ └─ Copies systemd/*.service → /etc/systemd/system/, enables them
│ (autostart.service only when the `autostart` flag is set)
│ └─ Copies systemd/*.service + systemd/*.timer → /etc/systemd/system/, enables them
│ (autostart.service only when the `autostart` flag is set;
│ pos-health.timer only when the user's Telegram config exists)
├─ Phase 4: ScaleTail clone
│ └─ Shallow-clones ScaleTail templates to /usr/local/share/linux_post_install/scale-tail
@@ -292,9 +304,10 @@ Sourced by most scripts. Provides:
| `section "title"` | Cyan-bordered section header |
| `step N T "msg"` | Numbered step header (e.g., `[1/4] Installing`) |
| `run cmd` | Executes command, respects `$DRY_RUN` |
| `spawn "msg" cmd` | Runs with animated braille spinner, elapsed time, OK/FAIL status |
| `spawn "msg" cmd` | Runs with animated braille spinner, elapsed time, OK/FAIL status; respects `$DRY_RUN` |
| `timer_start` / `timer_stop` | Elapsed time tracking |
| `confirm "prompt" [default]` | y/N or Y/n prompt |
| `load_system_env` | Loads `~/.config/linux_post_install/system.env` (env already exported wins) |
**Auto-detects TTY** — disables colors when piped.
@@ -378,7 +391,7 @@ ScaleTail provides 119+ Docker Compose templates with a Tailscale sidecar patter
### Adding a New App
1. Create `apps/<name>.sh` following the template in DOC/DEV.md
1. Create `apps/<category>/<name>.sh` following the template in DOC/DEV.md
2. It auto-appears in the interactive picker — no registration needed
---
@@ -403,8 +416,10 @@ Public-API "entertainment" plugins (weather, joke, gold) that can auto-send thei
|---------|------|---------|
| `ssh-agent.service` | `systemd/ssh-agent.service` | System-wide SSH agent, socket at `/run/ssh-agent/socket` |
| `autostart.service` | `systemd/autostart.service` | Runs `autostart.sh` on boot |
| `pos-health.service` | `systemd/pos-health.service` | Runs `pos system health --send --markdown` once (oneshot) as the installing user |
| `pos-health.timer` | `systemd/pos-health.timer` | Daily 08:00 trigger for the digest (enabled only when `~/.config/linux_post_install/telegram.env` exists) |
All `.service` files in `systemd/` are automatically copied to `/etc/systemd/system/` and enabled by `postinstall.sh`.
All `.service` files in `systemd/` are automatically copied to `/etc/systemd/system/` and enabled by `postinstall.sh` (timers too, when present).
---
@@ -418,7 +433,9 @@ All `.service` files in `systemd/` are automatically copied to `/etc/systemd/sys
### Runtime Config
- `~/.config/linux_post_install/compose.env` — Docker Compose global defaults
- `~/.config/linux_post_install/entertainment.env` — entertainment plugin defaults: weather location + `ENABLED` auto-trigger list (`plugin, interval` pairs scheduled via `pos entertainment enable/disable`, systemd user timers or cron auto-detected); auto-installed from `config/entertainment.env` by `postinstall.sh` (no clobber, template printed)
- `~/.config/linux_post_install/entertainment.env` — entertainment plugin defaults: weather location + `ENABLED` auto-trigger list (`plugin, interval` pairs scheduled via `pos entertainment enable/disable`, systemd user timers); auto-installed from `config/entertainment.env` by `postinstall.sh` (no clobber, template printed)
- `~/.config/linux_post_install/system.env` — shared "system" tool settings (loaded by `pos system health` / `pos system backup` via `load_system_env()` in `lib/common.sh`; env already exported wins over the file); template `config/system.env`
- `~/.config/linux_post_install/notify.env` — alerting platform selection (`NOTIFY_PLATFORM=telegram,matrix`, comma-separated = fan out); read by `lib/notify.sh`; template `config/notify.env`
- `~/.bashrc` — Modified by postinstall (PATH, bash completion)
### Feature Flags
@@ -521,12 +538,13 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| File | Lines | Purpose |
|------|-------|---------|
| `install.sh` | 192 | Main orchestrator — 4 phases with CLI flags, `--feature`, prebuilt arch bins |
| `preinstall.sh` | 54 | System packages + hotspot deps + yt-dlp + fail2ban |
| `postinstall.sh` | 115 | fail2ban config, PATH, bash completion, systemd (flag-gated) |
| `lib/common.sh` | 121 | Shared library |
| `install.sh` | 206 | Main orchestrator — 4 phases with CLI flags, `--feature`, prebuilt arch bins |
| `preinstall.sh` | 55 | System packages + hotspot deps + yt-dlp + fail2ban |
| `postinstall.sh` | 152 | fail2ban config, PATH, bash completion, systemd (flag-gated) |
| `lib/common.sh` | 144 | Shared library (log/warn/err/run/spawn, dry-run aware, `load_system_env`) |
| `lib/flags.sh` | 60 | Feature flag store (set/clear/is_set/value/list/status) |
| `lib/entertainment-lib.sh` | 380 | Entertainment module lib (ENABLED parsing, scheduler sync) |
| `lib/notify.sh` | 76 | Multi-platform alerting (`notify_send`) — opt-in source, silent-fails |
| `lib/entertainment-lib.sh` | 350 | Entertainment module lib (ENABLED parsing, scheduler sync) |
| `bin/flag-reader` | 58 | Inspect flags (list/status/`--raw`) |
| `bin/flag-set` | 21 | Set a flag (optionally with a value) |
| `bin/flag-clear` | 21 | Unset a flag |
@@ -553,7 +571,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| `bin/pos-ssh-load-keys` | 31 | Load all SSH keys into the agent |
| `bin/pos-system-backup` | 125 | Encrypted (AES-256) folder snapshots (tar + gpg) |
| `bin/pos-system-firewall` | 291 | Interactive UFW management |
| `bin/pos-system-health` | 254 | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
| `bin/pos-system-health` | 272 | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
| `bin/pos-system-nfs-client` | 138 | Mount NFS shares (ephemeral or persistent systemd mount units) |
| `bin/pos-system-nfs-server` | 134 | Manage the NFS kernel server (status, share/unshare exports, enable/disable) |
| `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
+1
View File
@@ -86,3 +86,4 @@ Installation methods used across the catalog:
| AFFiNE | utilities | Knowledge base (AppImage) | GitHub release → `/opt/affine` + desktop entry |
| btop | utilities | Resource monitor | `apt install btop` |
| LocalSend | utilities | Local file sharing | flatpak (installs flatpak + flathub if missing) |
| tsui | utilities | Tailscale config TUI (official install script from neuralink.com) | `curl \| bash``/usr/local/bin/tsui` |
+2 -2
View File
@@ -31,7 +31,7 @@ Each phase is independent and runs only if the corresponding script exists.
|-----------|---------|-------------|
| `bin/` | Daily-use CLI tools and wrappers | `/usr/local/bin/` |
| `apps/<category>/` | Optional desktop app installers | run on demand |
| `lib/` | Shared libraries: `common.sh` (helpers), `flags.sh` (feature flags), `entertainment-lib.sh` (entertainment scheduling) | sourced at build time |
| `lib/` | Shared libraries: `common.sh` (helpers), `flags.sh` (feature flags), `notify.sh` (multi-platform alerting), `entertainment-lib.sh` (entertainment scheduling) | sourced at build time |
| `config/` | Gitignored user config files | `~/.config/<app>/` (via postinstall) |
| `entertainment/` | Public-API plugins for the entertainment module | `/usr/local/bin` (via install.sh Phase 2) |
| `compose/` | ScaleTail templates (git submodule) | `/usr/local/share/linux_post_install/scale-tail` |
@@ -55,7 +55,7 @@ All non-interactive commands log to `~/.local/share/linux_post_install/logs/`.
**When adding a command, `bin/pos` itself has one thing to keep in sync:**
- **The usage text** (`usage()` function) — the CATEGORIES block is **auto-derived** from the `pos-*` filenames in `bin/` (no manual edit, can't drift). The EXAMPLES block is the only hand-maintained part: add a line there only if you want the tool showcased in `pos --help`.
- **`INTERACTIVE_CMDS`** (space-separated list above the dispatch loop) — commands that **read stdin** (password prompts, selection menus: `media-mp4`, `system-backup`, `usb-server`) must be added here. Everything else is piped through `tee` for logging, which would hang or swallow an interactive prompt. sudo's own password prompt is unaffected — it reads from `/dev/tty`. Trade-off: it's all-or-nothing **per script** — adding a flag-style tool with *any* prompting subcommand (e.g. `usb-server --share`) means *every* subcommand of that script skips output logging (e.g. `usb server --ls` loses the `tee` log too).
- **`INTERACTIVE_CMDS`** (space-separated list above the dispatch loop) — commands that **read stdin** (password prompts, selection menus: `system-firewall`, `media-mp4`, `system-backup`, `usb-server`, `communication-telegram-listener`) must be added here. Everything else is piped through `tee` for logging, which would hang or swallow an interactive prompt. sudo's own password prompt is unaffected — it reads from `/dev/tty`. Trade-off: it's all-or-nothing **per script** — adding a flag-style tool with *any* prompting subcommand (e.g. `usb-server --share`) means *every* subcommand of that script skips output logging (e.g. `usb server --ls` loses the `tee` log too).
### Shared Library (`lib/common.sh`)
+20 -2
View File
@@ -11,6 +11,7 @@ Everything that runs during the bootstrap install: `install.sh`, `preinstall.sh`
- [postinstall.sh — user configuration](#postinstallsh--user-configuration)
- [lib/common.sh — shared library](#libcommonsh--shared-library)
- [lib/flags.sh — feature flags](#libflagssh--feature-flags)
- [lib/notify.sh — multi-platform alerting](#libnotifysh--multi-platform-alerting)
- [features/autostart.sh — boot-time feature](#featuresautostartsh--boot-time-feature)
- [x64_bin/ — precompiled binaries](#x64_bin--precompiled-binaries)
@@ -36,7 +37,7 @@ The phases:
| # | Phase | Script/action |
|---|-------|----------------|
| 1 | preinstall | `preinstall.sh` — apt packages + yt-dlp |
| 2 | scripts | Copies `bin/*``/usr/local/bin/` (755), `lib/common.sh` + `lib/flags.sh` + `lib/entertainment-lib.sh``/usr/local/bin/` (644). Copies precompiled arch binaries from `x64_bin/` (or `arm64_bin/`) → `/usr/local/bin/`. With `--feature`: also installs `features/*` (see below) |
| 2 | scripts | Copies `bin/*``/usr/local/bin/` (755), `lib/common.sh` + `lib/flags.sh` + `lib/notify.sh` + `lib/entertainment-lib.sh``/usr/local/bin/` (644). Copies precompiled arch binaries from `x64_bin/` (or `arm64_bin/`) → `/usr/local/bin/`. With `--feature`: also installs `features/*` (see below) |
| 3 | postinstall | `postinstall.sh` — PATH, completion, SSH keys, systemd |
| 4 | scalepoint | Shallow-clones ScaleTail templates to `/usr/local/share/linux_post_install/scale-tail` |
| 5 (opt) | apps | `apps/install.sh` when `--apps` (interactive) or `--full` (all, non-interactive) |
@@ -172,10 +173,27 @@ flag_clear autostart
---
## lib/notify.sh — multi-platform alerting
**File:** `lib/notify.sh` (installed to `/usr/local/bin/notify.sh`)
**Purpose:** opt-in alerting helper for tools that announce events. Delivers to every platform in `NOTIFY_PLATFORM` via the sender contract `pos-communication-<platform> send <value> [--markdown]` (default platform: `telegram`).
Self-contained by design: defines **only** `notify_send()` + `notify_platforms()`, so sourcing it never clobbers a tool's own `log`/`warn`/`err`. **Silent-fails per platform** — a missing sender or failed send only warns and never changes the caller's exit code.
```bash
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
notify_send "Backup completed"
notify_send "**disk full**" --markdown
```
Platform selection: `~/.config/linux_post_install/notify.env` (`NOTIFY_PLATFORM=telegram,matrix`, comma-separated = fan out; env var wins over the file). Adding a platform = drop a `bin/pos-communication-<platform>` sender + list it — no change to `lib/notify.sh`.
---
## lib/entertainment-lib.sh — entertainment module
**File:** `lib/entertainment-lib.sh` (installed to `/usr/local/bin/entertainment-lib.sh`)
**Purpose:** shared logic for the `pos entertainment` tools — config (`entertainment.env`), `ENABLED` auto-trigger list parsing (`plugin, interval` pairs), plugin lookup by `# POS_PLUGIN:` marker, interval→schedule mapping, and scheduler reconciliation (systemd **user** timers when a user manager is reachable, otherwise a managed user **crontab** block).
**Purpose:** shared logic for the `pos entertainment` tools — config (`entertainment.env`), `ENABLED` auto-trigger list parsing (`plugin, interval` pairs), plugin lookup by `# POS_PLUGIN:` marker, interval→schedule mapping, and scheduler reconciliation (systemd **user** timers — the only backend; requires a reachable user manager, `ensure_linger()` enables linger if needed).
Sourced by `bin/pos-entertainment-send|config|enable|disable|status` (after `lib/common.sh`). **Plugins must not source it** — their stdout is the sent message.
+19 -1
View File
@@ -248,7 +248,25 @@ ${line}"
else
notify_send "$msg"
fi
echo "sent: POS Health — ${host} (${verdict})"
# notify_send is silent-fail by design — confirm delivery only when a
# platform sender actually exists, otherwise warn on stderr (still visible
# here since only stdout was redirected while --send ran).
delivered=0
IFS=',' read -r -a platforms <<< "$(notify_platforms)"
for p in "${platforms[@]}"; do
p="${p// /}"
[ -n "$p" ] || continue
if command -v "pos-communication-$p" &>/dev/null \
|| [ -x "$(dirname "$0")/pos-communication-$p" ] \
|| [ -x "$(dirname "$0")/../bin/pos-communication-$p" ]; then
delivered=1
fi
done
if [ "$delivered" -eq 1 ]; then
echo "sent: POS Health — ${host} (${verdict})"
else
warn "notify: no platform sender found (NOTIFY_PLATFORM=$(notify_platforms)) — digest not delivered"
fi
fi
[ "$FAILURES" -eq 0 ]
View File
+3 -1
View File
@@ -14,7 +14,9 @@ fi
source "$(dirname "$0")/lib/common.sh"
source "$(dirname "$0")/lib/flags.sh"
DRY_RUN=0
# Exported so child phases (preinstall.sh, postinstall.sh) inherit it —
# otherwise '--dry-run' silently executes them for real.
export DRY_RUN=0
RUN_APPS=0
RUN_FEATURES=0
SKIP_PHASES=""
+5 -1
View File
@@ -65,10 +65,14 @@ timer_stop() { _elapsed "$TIMER_START"; }
# ── Timed command runner ───────────────────────────────────────
# Shows a spinner while the command runs in background,
# then prints result + elapsed time.
# then prints result + elapsed time. Honors $DRY_RUN like run().
spawn() {
local msg="$1"
shift
if [ "${DRY_RUN:-0}" -eq 1 ]; then
log "(dry-run) ${msg}: $*"
return 0
fi
local start
start=$(_nano_now)
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env bash
# Shared library for the entertainment module (pos entertainment *).
# Sourced by the bin/pos-entertainment-* tools AFTER lib/common.sh.
# NOTE: plugins themselves must NOT source this — their stdout is the message.
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env bash
# lib/notify.sh — optional MULTI-PLATFORM alerting helper. Self-contained by
# design: defines ONLY notify_send() + notify_platforms() (plus internal
# helpers) so it can be sourced by tools that define their own log/warn/err
+16 -16
View File
@@ -8,9 +8,9 @@ log "Running post-install..."
# ── rclone config ──────────────────────────────────────────────
# Place your rclone.conf in config/ (gitignored) and this will install it.
if [ -f config/rclone.conf ]; then
mkdir -p "$HOME/.config/rclone"
cp config/rclone.conf "$HOME/.config/rclone/rclone.conf"
chmod 600 "$HOME/.config/rclone/rclone.conf"
run mkdir -p "$HOME/.config/rclone"
run cp config/rclone.conf "$HOME/.config/rclone/rclone.conf"
run chmod 600 "$HOME/.config/rclone/rclone.conf"
log "Installed rclone.conf"
else
warn "config/rclone.conf not found, skipping"
@@ -21,12 +21,12 @@ fi
# has not already created their own entertainment.env (no clobber).
ENT_DIR="$HOME/.config/linux_post_install"
if [ -f config/entertainment.env ]; then
mkdir -p "$ENT_DIR"
run mkdir -p "$ENT_DIR"
if [ -f "$ENT_DIR/entertainment.env" ]; then
log "entertainment.env already exists, keeping it"
else
cp config/entertainment.env "$ENT_DIR/entertainment.env"
chmod 600 "$ENT_DIR/entertainment.env"
run cp config/entertainment.env "$ENT_DIR/entertainment.env"
run chmod 600 "$ENT_DIR/entertainment.env"
log "Installed entertainment.env — set your location:"
cat "$ENT_DIR/entertainment.env"
fi
@@ -36,14 +36,14 @@ fi
# ── system + notify config templates ───────────────────────────
# Copied only if the user has not already created their own (no clobber).
mkdir -p "$ENT_DIR"
run mkdir -p "$ENT_DIR"
for tpl in system.env notify.env; do
if [ -f "config/$tpl" ]; then
if [ -f "$ENT_DIR/$tpl" ]; then
log "$tpl already exists, keeping it"
else
cp "config/$tpl" "$ENT_DIR/$tpl"
chmod 600 "$ENT_DIR/$tpl"
run cp "config/$tpl" "$ENT_DIR/$tpl"
run chmod 600 "$ENT_DIR/$tpl"
log "Installed $tpl — edit $ENT_DIR/$tpl"
fi
fi
@@ -56,7 +56,7 @@ BASHRC="$HOME/.bashrc"
if grep -qsF "$PATH_LINE" "$BASHRC" 2>/dev/null; then
log "PATH already configured"
else
echo "$PATH_LINE" >> "$BASHRC"
run echo "$PATH_LINE" >> "$BASHRC"
log "Added PATH to ~/.bashrc"
fi
@@ -66,7 +66,7 @@ COMPLETION_LINE='source /usr/local/share/bash-completion/completions/pos.bash 2>
if grep -qsF "pos.bash" "$BASHRC" 2>/dev/null; then
log "pos completion already configured"
else
echo "$COMPLETION_LINE" >> "$BASHRC"
run echo "$COMPLETION_LINE" >> "$BASHRC"
log "Added pos completion to ~/.bashrc"
fi
@@ -85,10 +85,10 @@ AUTH_FILE="$SSH_DIR/authorized_keys"
KEY_FILE="config/authorized_keys"
if [ -f "$KEY_FILE" ]; then
mkdir -p "$SSH_DIR"
chmod 700 "$SSH_DIR"
touch "$AUTH_FILE"
chmod 600 "$AUTH_FILE"
run mkdir -p "$SSH_DIR"
run chmod 700 "$SSH_DIR"
run touch "$AUTH_FILE"
run chmod 600 "$AUTH_FILE"
added=0
while IFS= read -r key; do
@@ -96,7 +96,7 @@ if [ -f "$KEY_FILE" ]; then
if grep -qsF "$key" "$AUTH_FILE" 2>/dev/null; then
log "SSH key already present"
else
echo "$key" >> "$AUTH_FILE"
run echo "$key" >> "$AUTH_FILE"
added=$((added + 1))
fi
done < "$KEY_FILE"
+1 -1
View File
@@ -2,7 +2,7 @@
set -euo pipefail
source "$(dirname "$0")/lib/common.sh"
DRY_RUN=0
DRY_RUN="${DRY_RUN:-0}"
usage() {
cat <<EOF
+2 -1
View File
@@ -12,7 +12,8 @@ note() { echo " ✗ $*"; }
# ── 1. Syntax ───────────────────────────────────────────────────
for f in bin/pos bin/pos-* lib/*.sh install.sh preinstall.sh postinstall.sh \
completions/pos.bash scripts/*.sh; do
completions/pos.bash scripts/*.sh apps/*/*.sh entertainment/*.sh \
features/*.sh templates/*.sh; do
[ -f "$f" ] || continue
bash -n "$f" 2>/dev/null || { note "syntax error in $f"; fail=1; }
done
+2
View File
@@ -169,6 +169,8 @@ regen_block() {
skip { next }
{ print }
' "$file" > "$tmp"
# mktemp creates 0600 files — mv would leave the doc/completion at 0600
chmod 644 "$tmp"
mv "$tmp" "$file"
fi
rm -f "$newfile"