Zero-terminal bug fix. When a user set an agent's working directory
to "~/nexus-test-01" through the UI, the path was stored verbatim in
agents.adapter_config.cwd and the downstream local adapters (claude_
local, codex_local, gemini_local, cursor, opencode_local, hermes_
local, etc.) failed to resolve the tilde — shells expand ~, child
processes don't. The user was then expected to ssh in and create the
directory by hand, which contradicts Nexus's zero-terminal charter.
Add two helpers in server/src/routes/agents.ts:
expandUserPath(candidate)
Trim, expand leading "~" or "~/" to os.homedir(), then
path.resolve() to absolute form. Null-safe on non-string input.
normalizeAdapterConfigPaths(adapterConfig) [async]
If adapterConfig.cwd is a non-empty string, expand it, assert
absolute, mkdir -p (recursive), and stat to confirm it's a
directory. Any failure becomes an unprocessable (422) error with
the reason surfaced to the UI. Logs an info line when a path is
actually changed, so the audit trail records that Nexus expanded
a user-supplied tilde.
Wire into the three existing call sites:
POST /api/companies/:companyId/agent-hires
POST /api/companies/:companyId/agents
PATCH /api/agents/:id
...all of which previously called applyCreateDefaultsByAdapterType
then secretsSvc.normalizeAdapterConfigForPersistence. Added
normalizeAdapterConfigPaths between the secrets step and
assertAdapterConfigConstraints on create + hire, and between secrets
normalization and syncInstructionsBundleConfigFromFilePath on patch.
Each call site now stores a fully resolved absolute path and is
guaranteed the directory exists on disk.
DB state for the two agents that hit this bug today (Project Manager
and Engineer on the Nexus company) was already patched out-of-band
to /home/mikkel/nexus-test-01 by a direct SQL update and mkdir. This
commit prevents recurrence for any future agent-create or agent-patch.
Not addressed here (scope creep):
- instructionsFilePath / instructionsRootPath also accept
user-provided paths but are managed by a separate subsystem;
they may need their own tilde-expansion pass if the UI ever
exposes them directly.
- No restriction on where the cwd can be. Nexus runs as the host
user and trusts the caller. A future policy could limit cwd to
$HOME or a configured workspace root, but that's a separate
decision.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>