Files
Codeman/docs/wiki/Multi-User-Mode.md
T
Codeman maintainer 31c03ab62d docs(multi-user): server-wide settings writes are admin-only
api-reference gains a Settings section (GET/PUT /api/settings, the model
config, the case order and PUT /api/config, with the 403 FORBIDDEN a non-admin
gets in multi-user mode). The Multi-User Mode wiki page explains what a regular
user's App Settings save does now, Settings-Reference links it, the plan's
Settings row is marked implemented, and CLAUDE.md notes the gate for the
Multi-user paragraph and for anyone adding a settings write.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 12:18:20 +02:00

5.8 KiB

Multi-User Mode

Share one Codeman with a small trusted team. Each person gets their own login and workspace, and sessions, cases, search, and live events are scoped to their owner.

Off by default. Without the flag, behaviour is identical to single-user Codeman, because every scoping check short-circuits.

Read this before enabling it

Multi-user mode separates workspaces. It does not sandbox users from each other.

Every session still runs as the same operating system account. A determined user's agent can reach another user's files, because at the OS level they are the same user. This is a convenience and organization feature, not a security boundary.

If you need real isolation:

  • Pair each user with Docker Cases, which gives their work its own filesystem and network.
  • Or run separate Codeman instances under separate OS accounts, each with its own CODEMAN_INSTANCE.

"Small trusted team" is the honest description of who this is for.

Enabling it

codeman users add alice --admin      # create the first admin, prompts for a password
codeman web --multiuser              # or CODEMAN_MULTIUSER=1

Then manage users from the CLI or the Users entry in App Settings:

codeman users add bob                # a regular user
codeman users list
codeman users passwd bob             # reset to a one-time password
codeman users rm bob

--password-stdin reads the password from standard input, for scripts.

Accounts live in ~/.codeman/users.json with scrypt-hashed passwords, mode 0600. Administrative actions are audited to ~/.codeman/admin-audit.jsonl.

What each user gets

Thing Scope
Case space ~/codeman-users/<name>/cases, their own.
Sessions Only theirs are listed, reachable, or controllable.
Events Live event routing is per owner, and fails closed.
Search Scoped on read, including historical results.
File previews Scoped to sessions they own.
Path picker Only their own user space as a root, not the whole home directory.

Admins see everything.

Ownership threads through every list endpoint, the session lookup helper, the WebSocket layer, and file previews. A user cannot address another user's session even by id.

Server-wide settings are admin only

There is one set of server settings (~/.codeman/settings.json) for everyone: the feature switches, the run mode, respawn presets, the case order, the Cloudflare tunnel, the default models. Every user can read them, but only an admin can change them. For a regular user the settings write routes answer 403 FORBIDDEN (see the HTTP API and docs/api-reference.md).

In the browser this means:

  • App Settings → Save still keeps a regular user's per-device settings (skin, fonts, header buttons, keyboard bar and the rest of the per-device keys) on that device. If they also changed a server-wide setting, one notice says it can only be changed by an admin, and the setting keeps the server's value.
  • A regular user's run-mode pick and respawn presets are kept in that browser and not sent to the server, and their last used case is not recorded server-wide. What an admin set still loads on the next visit.
  • Reordering cases and switching the tunnel on or off are admin actions.

Per-user server settings are not part of this version.

Safer defaults for regular users

Non-admins get tighter defaults, and lifting them is an explicit per-user grant:

Default Meaning
Claude runs in auto permission mode Anthropic's classifier-guarded mode instead of skip-prompts.
Raw shell sessions require a grant A plain shell is unmediated machine access.
Skip-permissions requires a grant Same reasoning.
Cron launchCommand requires a grant It is an arbitrary command on a schedule.
Pi project trust defaults to off Trust makes Pi execute repo-local TypeScript.

These exist because the OS boundary is shared. They narrow what a normal account can do casually; they do not make the account a sandbox.

Accounts and sessions

Each user authenticates with their own name and password rather than the shared CODEMAN_PASSWORD. Logins are individually revocable: disable, reset, or delete an account at any time, and existing browser sessions can be revoked.

Gotchas

  • Enabling it does not migrate existing cases into a user space. They stay where they are, owned by whoever the ownership rules resolve them to.
  • Admins see everything, including other users' sessions. Choose admins accordingly.
  • The audit log is append-only and local. Ship it somewhere if you care about it.
  • It is not a substitute for OS accounts. Restating this because it is the one thing people get wrong.