diff --git a/README.md b/README.md index 0b3107db..5ae1c662 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ This installs Node.js, tmux and a build toolchain if missing (node-pty ships no - **How it's reachable, your choice.** **Tailscale** (loopback bind fronted by `tailscale serve`, so you get `https://..ts.net` with a real certificate and your tailnet as the login, no password needed), **any device on your network** (`0.0.0.0`, with a strongly recommended password prompt), or **this machine only** (`127.0.0.1`, safest). Skipping the password on a network bind requires an explicit confirmation and ends with a loud warning. The highlighted default reflects what is already on the machine (Tailscale when it is already connected, your existing binding on a re-run), and a bare Enter never pulls in new software. If another app already owns `:443` on your node, Codeman goes under `https://..ts.net/codeman` or on a second port instead of replacing it. A bare `codeman web` started by hand still defaults to loopback. - **The name is yours to choose.** By default the URL uses the machine's existing tailnet name. Answering yes to the second question renames the machine to `codeman-` (which also renames it for SSH, so the default is no); `install.sh name` does it later. - **Re-run to update.** The same one-liner updates a finished install in place: local changes in `~/.codeman/app` are stashed (never discarded), and a running service is restarted and verified. If a first install was interrupted, re-running resumes the full setup instead. `install.sh status` prints the URLs and the QR code again; `install.sh update`, `install.sh tailscale` and `install.sh uninstall` also exist. -- **No administrator rights needed.** On an account without `sudo` (or a Mac account that is not an administrator), the installer downloads Node.js from nodejs.org and the tmux project's own build into `~/.codeman/runtime`, each checked against its SHA-256, and takes the source as an archive when there is no working git. `--no-admin` forces that route. Two limits: Linux needs make, a C++ compiler and python3 to be there already, and the tmux download needs macOS 15 or newer. Details in the [wiki](https://github.com/Ark0N/Codeman/wiki/Installation#without-administrator-rights). +- **No administrator rights needed.** On an account without `sudo`, one whose `sudo` rights the installer cannot confirm (outside the `sudo`, `wheel` and `admin` groups, with a password still required) or a Mac account that is not an administrator, the installer downloads Node.js from nodejs.org and the tmux project's own build into `~/.codeman/runtime`, each checked against its SHA-256, and takes the source as an archive when there is no working git. `--no-admin` forces that route and `CODEMAN_NO_ADMIN=0` turns it off. Two limits: Linux needs make, a C++ compiler and python3 to be there already, and the tmux download needs macOS 15 or newer. Details in the [wiki](https://github.com/Ark0N/Codeman/wiki/Installation#without-administrator-rights). - **Flags for the impatient.** `curl -fsSL https://getcodeman.com/install | bash -s -- --tailscale --service` answers the questions from the command line (`--lan`, `--local`, `--run`, `--no-start`, `--name `, `--port `, `--yes` too). **CI / headless:** without a terminal attached, steps that would change your system abort with instructions instead of running silently; set `CODEMAN_NONINTERACTIVE=1` to approve them for automation. You'll need at least one AI coding CLI installed — [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [OpenCode](https://opencode.ai), [Codex](https://developers.openai.com/codex/cli), [Antigravity](https://antigravity.google), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Pi](https://pi.dev), [Grok Build](https://github.com/xai-org/grok-build), [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), [OMP](https://github.com/can1357/oh-my-pi), or [GitHub Copilot CLI](https://github.com/github/copilot-cli) (any combination works; Gemini CLI is enterprise-only since Google's consumer cutover, and Antigravity is its successor). The installer detects whichever of the ten is present; if none is found, it offers to install any of them from a menu (DeepSeek excepted, since its npm package installs only a launcher with no runnable profile), or you can skip and install one yourself later. After install: diff --git a/README.zh-CN.md b/README.zh-CN.md index e8fd544e..85f9a085 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -71,6 +71,7 @@ curl -fsSL https://getcodeman.com/install | bash - **怎么访问,由你决定。** 安装器提供三种到达仪表盘的方式:**Tailscale**(环回绑定,由 `tailscale serve` 代理,得到带真实证书的 `https://<机器名>..ts.net`,用你的 tailnet 当登录,无需密码)、**局域网内任意设备**(`0.0.0.0`,会提示设置一个强烈推荐的密码),或**仅本机**(`127.0.0.1`,最安全)。绑定网络却跳过密码需要显式确认,并以醒目警告收尾。高亮的默认项反映机器上已有的状态(已在用 Tailscale 时默认 Tailscale,重跑时沿用现有绑定),直接回车绝不会引入新软件。如果你节点上的 `:443` 已被别的应用占用,Codeman 会改用 `https://<机器名>..ts.net/codeman` 或第二个端口,而不是把它替换掉。手动运行的 `codeman web` 仍默认仅环回。 - **名字由你来定。** 默认情况下,URL 用的是这台机器在 tailnet 里现有的名字。第二个问题答「是」会把机器改名为 `codeman-`(这也会改掉它在 SSH 里的名字,所以默认是「否」);之后也可以用 `install.sh name` 来改。 - **重跑即更新。** 再次运行同一条命令即可原地更新已完成的安装:`~/.codeman/app` 中的本地改动会被 stash(绝不丢弃),运行中的服务会自动重启并校验。若首次安装中途失败,重跑会继续完成完整的安装流程。`install.sh status` 会再次打印 URL 和二维码;另外还有 `install.sh update`、`install.sh tailscale` 和 `install.sh uninstall`。 +- **无需管理员权限。** 在没有 `sudo` 的账户、安装器无法确认 `sudo` 权限的账户(不在 `sudo`、`wheel`、`admin` 组内,且 `sudo` 需要密码)或不是管理员的 Mac 账户上,安装器会把 nodejs.org 的 Node.js 和 tmux 项目自己的构建下载到 `~/.codeman/runtime`,两者都会校验 SHA-256;没有可用的 git 时,则以归档包的方式获取源码。`--no-admin` 强制走这条路线,`CODEMAN_NO_ADMIN=0` 则将其关闭。两个限制:Linux 上必须已有 make、C++ 编译器和 python3,tmux 下载需要 macOS 15 或更新版本。详见 [wiki](https://github.com/Ark0N/Codeman/wiki/Installation#without-administrator-rights)。 - **给急性子的参数。** `curl -fsSL https://getcodeman.com/install | bash -s -- --tailscale --service` 直接在命令行上回答这些问题(还有 `--lan`、`--local`、`--run`、`--no-start`、`--name `、`--port `、`--yes`)。**CI / 无终端环境:** 没有终端时,涉及系统改动的步骤会带着说明中止,而不是静默执行;在自动化场景设置 `CODEMAN_NONINTERACTIVE=1` 即可批准这些步骤。 你至少需要安装一个 AI 编程 CLI —— [Claude Code](https://docs.anthropic.com/en/docs/claude-code)、[OpenCode](https://opencode.ai)、[Codex](https://developers.openai.com/codex/cli)、[Antigravity](https://antigravity.google)、[Gemini CLI](https://github.com/google-gemini/gemini-cli)、[Pi](https://pi.dev)、[Grok Build](https://github.com/xai-org/grok-build)、[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)、[OMP](https://github.com/can1357/oh-my-pi) 或 [GitHub Copilot CLI](https://github.com/github/copilot-cli)(任意组合均可;自 Google 面向消费者停售后,Gemini CLI 仅限企业版,Antigravity 是其继任者)。安装器会自动检测这十个中已安装的任意一个;若一个都没有,会给出一个菜单让你安装其中任意一个(DeepSeek 除外,它的 npm 包只装一个启动器,没有可运行的 profile),也可以选择跳过、稍后自行安装。安装完成后: diff --git a/docs/architecture-invariants.md b/docs/architecture-invariants.md index 7b6115e0..4b054bd9 100644 --- a/docs/architecture-invariants.md +++ b/docs/architecture-invariants.md @@ -1297,7 +1297,7 @@ Its CLI knowledge is a GENERATED block (`npm run generate:cli-catalog`, markers ⚠️ It executes ONLY commands from the embedded block (`CLI_INSTALL_CMD_TRUSTED`) — there is no network fetch of the catalogue at install time to worry about at all. -**No-admin route** (`--no-admin` / `CODEMAN_NO_ADMIN`, 2026-11-05). Everything Codeman writes was always under `$HOME`; administrator rights were only ever spent on prerequisites. `resolve_admin_mode` decides once per run whether those rights may be asked for: root yes; a Mac account outside the `admin` group no (unless a Homebrew it can write to exists); on Linux no without a `sudo` binary, or when the account is outside `sudo`/`wheel`/`admin` AND `sudo -n true` fails. ⚠️ It is never decided by `sudo -v`: that prompts, and a refused password from an account outside sudoers is reported to the administrator. A refused password on the system route offers this route instead of ending the run (`sudo_session_try`). +**No-admin route** (`--no-admin` / `CODEMAN_NO_ADMIN`, 2026-11-05). Everything Codeman writes was always under `$HOME`; administrator rights were only ever spent on prerequisites. `resolve_admin_mode` decides once per run whether those rights may be asked for: root yes; a Mac account outside the `admin` group no (unless a Homebrew it can write to exists); on Linux no without a `sudo` binary, or when the account is outside `sudo`/`wheel`/`admin` AND `sudo -n true` fails. ⚠️ It is never decided by `sudo -v`: that prompts, and a refused password from an account outside sudoers is reported to the administrator. A refused password on the system route offers this route instead of ending the run (`sudo_session_try`). ⚠️ The group test is a judgment, not a fact: no probe can read sudoers without reporting to the administrator, so an account sudoers lists by name, with a password, lands here too. `NO_ADMIN_REASON` must therefore say the rights could not be confirmed (`NO_ADMIN_UNCONFIRMED`), never that the account may not use `sudo`, and every message that ends or sums up the route carries `no_admin_override_hint`, which names `CODEMAN_NO_ADMIN=0` for that reason alone (`--no-admin` asked for the route; a `sudo` that is missing or refused has no way back). On this route Node.js comes from nodejs.org (`latest-v.x/SHASUMS256.txt` names the tarball AND carries its checksum, one fetch, no JSON parsing) into `~/.codeman/runtime/node`, and tmux from the tmux project's `tmux-builds` release into `~/.codeman/runtime/bin`. ⚠️ `tmux-builds` publishes no checksum file, so `tmux_build_sha256` pins all four digests of `TMUX_BUILD_VERSION`; bump the version and the digests together (the GitHub release API returns them as `digest`). ⚠️ A download is verified BEFORE it is unpacked or run, and an empty expected digest never passes. `node`, `npm`, `npx` and `tmux` are linked from `~/.local/bin` (`link_into_local_bin` refuses to replace a file that does not already point into the runtime, and uninstall removes only such links): the `codeman` launcher is `#!/usr/bin/env node`, and a non-interactive shell never reads the PATH line written to an interactive profile. The runtime's `node/bin` also goes on PATH and on the LaunchAgent's `svc_path`, since `npm install -g` puts AI CLIs beside that Node.js. diff --git a/docs/security-architecture.md b/docs/security-architecture.md index 72c2dcf0..8559fa0c 100644 --- a/docs/security-architecture.md +++ b/docs/security-architecture.md @@ -483,6 +483,15 @@ transient mount blip at launch poisons tmux's long‑lived cwd and crashes never executes. Large hand‑formatted/generated assets (`app.js`, the gesture bundle, vendored libs) are `.prettierignore`d for the style pass, but the NUL + syntax checks still cover them. +- **Installer downloads without a package manager:** on the no-admin route + (`docs/wiki/Installation.md`) `install.sh` fetches and runs software no system + package manager vetted, each checked before it is unpacked or run. The Node.js + tarball is checked against the `SHASUMS256.txt` fetched from nodejs.org over the + same TLS connection, which proves integrity, not independent provenance: the + signature on that file is not checked. The tmux build is checked against a + SHA-256 pinned per platform in the installer. `install.sh cloudflared` takes the + latest cloudflared release into `~/.local/bin` unverified, as the system routes + take the same release, because Cloudflare publishes no checksum file. --- diff --git a/docs/wiki/FAQ.md b/docs/wiki/FAQ.md index fc6fc960..def23262 100644 --- a/docs/wiki/FAQ.md +++ b/docs/wiki/FAQ.md @@ -179,12 +179,13 @@ the defaults discovers and attaches your live sessions. | Install route | Update with | | ------------- | --------------------------------------------------------------------------- | | Installer | Re-run the install one-liner, or **App Settings → System → Updates**. | +| Installer, without git | Re-run the install one-liner. The in-app updater says so instead of offering an update. | | npm | `npm update -g aicodeman` | | git clone | `git pull && npm install && npm run build`, then restart the service. | The in-app updater covers git-clone installs supervised by systemd or launchd. It stashes a dirty tree rather than discarding it, and streams progress across the restart. npm installs -report as non-updatable. +and installs without git report as non-updatable. ### Will updating kill my running sessions? diff --git a/docs/wiki/Installation.md b/docs/wiki/Installation.md index 2542c36a..8bea197f 100644 --- a/docs/wiki/Installation.md +++ b/docs/wiki/Installation.md @@ -122,6 +122,14 @@ This route is taken by itself when `sudo` is not installed, when the account is `CODEMAN_NO_ADMIN=0` switches the detection off. Nothing on this route runs `sudo`, Homebrew or the Xcode tools installer. +The group check cannot see a sudoers entry, so an account that sudoers lists by name, with +a password, takes this route too. The summary then reads `could not confirm that this +account may use sudo`, and to use `sudo` anyway: + +```bash +curl -fsSL https://getcodeman.com/install | CODEMAN_NO_ADMIN=0 bash +``` + What to know about it: - **Linux needs make, a C++ compiler and python3 to be there already.** node-pty compiles @@ -279,8 +287,10 @@ npm uninstall -g aicodeman # npm route The installer route asks before it removes `~/.codeman/runtime` (the Node.js and tmux it downloaded, if any), and keeps it by default when you installed CLIs there with -`npm install -g`. Neither removes `~/.codeman/` or `~/codeman-cases/`. Delete those by hand if you want the -state and your case folders gone as well, and check `~/codeman-cases/` first: linked cases +`npm install -g`. That folder is inside `~/.codeman/`, so saying yes to the data directory +question that follows removes it even if you kept it a step earlier, and the question says +so. By default neither route removes `~/.codeman/` or `~/codeman-cases/`. Delete those by hand +if you want the state and your case folders gone as well, and check `~/codeman-cases/` first: linked cases point at directories you already had, but cases created from scratch have their only copy there. diff --git a/docs/wiki/Running-As-A-Service.md b/docs/wiki/Running-As-A-Service.md index 88cc5518..f6fe09c7 100644 --- a/docs/wiki/Running-As-A-Service.md +++ b/docs/wiki/Running-As-A-Service.md @@ -145,6 +145,7 @@ log stream --predicate 'process == "node"' # macOS, noisy | Install route | Update with | | ------------- | ------------------------------------------------------------------------ | | Installer | Re-run the one-liner, or **App Settings → System → Updates**. | +| Installer, without git | Re-run the one-liner. The in-app updater says so instead of offering an update. | | npm | `npm update -g aicodeman` | | git clone | `git pull && npm install && npm run build`, then restart. | | Docker Compose | Re-run `Start-Codeman.sh`, or the in-app updater, which restarts the container in place. | @@ -152,8 +153,8 @@ log stream --predicate 'process == "node"' # macOS, noisy ### The in-app updater **App Settings → System → Updates**, for git-clone installs supervised by systemd or -launchd. npm installs report as non-updatable, and an unsupervised install is told to -restart manually. +launchd. npm installs and installs without git report as non-updatable, and an unsupervised +install is told to restart manually. The interesting part is that the update restarts the very process running it. So the real work runs in a **detached script that outlives the restart** and writes progress to a status diff --git a/docs/wiki/Settings-Reference.md b/docs/wiki/Settings-Reference.md index 0ba55368..e5cc54b4 100644 --- a/docs/wiki/Settings-Reference.md +++ b/docs/wiki/Settings-Reference.md @@ -38,8 +38,8 @@ as usual and tells them that server-wide settings can only be changed by an admi ### Updates Current version, a manual check, and the in-app updater. Covers git-clone installs -supervised by systemd or launchd; npm installs report as non-updatable. See -[Running As A Service](Running-As-A-Service). +supervised by systemd or launchd; npm installs and installs without git report as +non-updatable. See [Running As A Service](Running-As-A-Service). ### Terminal & Input diff --git a/docs/wiki/Troubleshooting.md b/docs/wiki/Troubleshooting.md index 5a8fba2e..25014885 100644 --- a/docs/wiki/Troubleshooting.md +++ b/docs/wiki/Troubleshooting.md @@ -353,7 +353,7 @@ On an HTTPS install, add `-k` to the curl commands and use the `https://` URL. Open an [issue](https://github.com/Ark0N/Codeman/issues) with: - OS and version. -- Install method: installer, npm, or git clone. +- Install method: installer (with or without git), npm, or git clone. - `codeman --version`. - Browser and version, if the problem is in the UI. - Which CLI the session was running, and its version.