Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ jobs:
fail-fast: false
matrix:
# Windows runs a focused contract; full capability coverage remains on Linux/macOS.
os: [ubuntu-latest, macos-latest, windows-latest]
# ubuntu-24.04-arm validates ARM64 Linux.
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest, windows-latest]
node: ["24"]
include:
- os: ubuntu-latest
node: "24"
profile: full
- os: ubuntu-24.04-arm
node: "24"
profile: full
- os: windows-latest
node: "24"
profile: windows
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@ jobs:
fail-fast: false
matrix:
# Windows validation is temporarily paused until its checks are reliable.
os: [ubuntu-latest, macos-latest]
# ubuntu-24.04-arm validates ARM64 Linux.
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest]
node: ["22.19.0", "24.2.0", "25", "26"]
include:
- os: ubuntu-latest
node: "22.19.0"
profile: full
- os: ubuntu-24.04-arm
node: "22.19.0"
profile: full
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ pnpm install --frozen-lockfile
pnpm verify
```

`pnpm verify` runs the complete gate list in the same order as GitHub CI. Normal PR and main-branch checks use Node.js 24 on Linux and macOS. The Linux job runs the full profile; the macOS job uses `pnpm verify --profile platform`, which omits only the duplicate TypeScript compiler check. Windows runs the focused `pnpm verify --profile windows` contract on PRs; the profile is Windows-only and fails closed elsewhere. It checks source inventory, release tooling, build boundaries, artifacts, and Windows-specific tests without running the full capability suite. Gates that depend on platform behaviour are selected by platform rather than skipped silently; run `pnpm verify --list`, `pnpm verify --profile platform --list`, or `pnpm verify --profile windows --list` to inspect each plan. Individual gates remain available as their own scripts, such as `pnpm typecheck` or `pnpm test:byok`, while you iterate.
`pnpm verify` runs the complete gate list in the same order as GitHub CI. Normal PR and main-branch checks use Node.js 24 on Linux x64, Linux ARM64 and macOS. Both Linux jobs run the full profile; the macOS job uses `pnpm verify --profile platform`, which omits only the duplicate TypeScript compiler check. Windows runs the focused `pnpm verify --profile windows` contract on PRs; the profile is Windows-only and fails closed elsewhere. It checks source inventory, release tooling, build boundaries, artifacts, and Windows-specific tests without running the full capability suite. Gates that depend on platform behaviour are selected by platform rather than skipped silently; run `pnpm verify --list`, `pnpm verify --profile platform --list`, or `pnpm verify --profile windows --list` to inspect each plan. Individual gates remain available as their own scripts, such as `pnpm typecheck` or `pnpm test:byok`, while you iterate.

`pnpm lint` (or `pnpm lint:tui`) checks TUI source and tests with the source repository's Airbnb, TypeScript, import and Prettier rules. Errors fail verification; formatting, unused variables and explicit `any` remain warnings, matching the source policy. The scripts use `--quiet` to keep existing warning debt out of CI logs; omit it when invoking ESLint directly to inspect warnings. The audited Pi engine retains its narrow style exceptions; its public facade uses the normal rules. Vendored Pi test copies are excluded. Full, platform, archive and Windows verification include this gate; docs and package-installation profiles do not.

CI writes per-gate timing and exit metadata to the Job Summary and a seven-day `verification-<os>-node-<version>-<attempt>` artifact. For a local report, set `MCODE_VERIFY_REPORT_DIR` to a directory outside the repository. Reports distinguish `PASS`, `FAIL`, intentional `SKIP`, and `NOT_RUN` after a failure. JSON is checkpointed before and after each gate; a cancelled run may leave `RUNNING`, which is not a pass. If installation fails before verification starts, no verification report is available. Reports do not collect command output, environment variables, or runtime data; read the corresponding gate's job log for failure details, including the existing bounded BYOK timeout diagnostics. CI jobs have a 15-minute verification limit and a 10-minute release-audit limit.

Existing README files, `CONTRIBUTING.md`, `.github/PULL_REQUEST_TEMPLATE.md`, Markdown under `docs/`, and media directly under `docs/assets/` use the `docs` profile when they are the only changed paths. That profile checks the source inventory and generated paths, exports the committed source, and tests release tooling. History and source-snapshot secret scans still run; platform builds and distribution scans are skipped. Mixed changes, unknown paths, missing comparisons, and any `release/` inventory change get full CI. Documentation-only changes skip the platform matrix entirely. The `verification` aggregate check always runs and rejects failed, cancelled, or unexpectedly skipped jobs. Use it together with `source-history-artifact` as required checks when configuring branch protection; this repository's automation does not change administrative settings.

`Node compatibility` runs weekly and on demand against macOS and Linux with Node 22.19.0, 24.2.0, 25 and 26. Windows remains excluded from this matrix; the PR Windows contract is a focused Node 24 check, not a substitute for the full compatibility matrix. It does not run automatically on PRs. Dispatch it on the selected branch for changes to supported Node versions, native dependencies or compatibility-sensitive verification tooling, and before a source release. This covers the minimum versions of the two supported ranges and the additional supported majors. Deferring those versions from ordinary PR checks can delay regression discovery; a known failure in a supported version still needs resolution before release. Dependabot proposes weekly Actions and npm updates, grouping Actions and development-tool minor/patch updates. External Actions use reviewed full commit SHAs, while local actions and reusable workflows come from the same checked-out revision.
`Node compatibility` runs weekly and on demand against macOS and Linux (x64 and ARM64) with Node 22.19.0, 24.2.0, 25 and 26. Windows remains excluded from this matrix; the PR Windows contract is a focused Node 24 check, not a substitute for the full compatibility matrix. It does not run automatically on PRs. Dispatch it on the selected branch for changes to supported Node versions, native dependencies or compatibility-sensitive verification tooling, and before a source release. This covers the minimum versions of the two supported ranges and the additional supported majors. Deferring those versions from ordinary PR checks can delay regression discovery; a known failure in a supported version still needs resolution before release. Dependabot proposes weekly Actions and npm updates, grouping Actions and development-tool minor/patch updates. External Actions use reviewed full commit SHAs, while local actions and reusable workflows come from the same checked-out revision.

Source candidates are requested independently through the `Source candidate` workflow; ordinary PRs and main pushes do not produce them. Its Linux/macOS archive validation is described in [Releasing](docs/releasing.md). `CLI release` builds npm-installable tar.gz packages from version tags and validates the same archive before attaching it to a GitHub Release. Its `package` verification profile tests installation of an existing archive; it does not replace full source verification. npm registry and official installer publication remain separate release processes.

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ mcode login --region global

Complete sign-in in your browser, then open `mcode` and use `/status` to check your account and `/provider` to choose a model. Run `mcode logout` to sign out.

Token Plan requires an account with available credits. Builds from this repository and the published npm CLI `@minimax-ai/code@0.4.12` default to `~/.minimax` for user data (or `~/.minimax-<profile>` when a profile is selected). `MINIMAX_DATA_DIR` or `MAVIS_DATA_DIR` can override the data directory. The installer's `~/.minimax-code` installation directory is separate from this choice. See [Accounts and data](docs/installation.md#accounts-and-data) before locating or removing configuration and sessions.
Token Plan requires an account with available credits. The published npm CLI `@minimax-ai/code@0.4.12` uses `~/.minimax` for user data. Source builds keep existing Linux installations there; new Linux installations use `$XDG_DATA_HOME/minimax` (default `~/.local/share/minimax`). macOS and Windows source builds continue to use `~/.minimax`. A selected profile appends `-<profile>` to the default directory name. `MINIMAX_DATA_DIR` or `MAVIS_DATA_DIR` can override the data directory. The installer's `~/.minimax-code` installation directory is separate from this choice. See [Accounts and data](docs/installation.md#accounts-and-data) before locating or removing configuration and sessions.

<details>
<summary>Use your own API key (BYOK)</summary>
Expand Down Expand Up @@ -197,7 +197,7 @@ rm -rf -- "$HOME/.minimax"
Remove-Item -LiteralPath "$env:USERPROFILE\.minimax" -Recurse -Force
```

A profile uses `~/.minimax-<profile>`; `MINIMAX_DATA_DIR` or `MAVIS_DATA_DIR` can select a different location. Remove only the specific directories you intend to discard, without wildcard deletion. Remove any MCode-specific environment variable assignments you added to shell profiles or user environment settings if you no longer need them.
A profile appends `-<profile>` to its default directory name. New Linux source installations use `$XDG_DATA_HOME/minimax` (default `~/.local/share/minimax`); `MINIMAX_DATA_DIR` or `MAVIS_DATA_DIR` can select a different location. Remove only the specific directories you intend to discard, without wildcard deletion. Remove any MCode-specific environment variable assignments you added to shell profiles or user environment settings if you no longer need them.

## What you can do

Expand Down
4 changes: 2 additions & 2 deletions README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ mcode login --region global

在浏览器中完成登录,再启动 `mcode`,通过 `/status` 检查账号、通过 `/provider` 选择模型。退出登录使用 `mcode logout`。

Token Plan 需要账号与可用额度。从本仓库构建的版本与已发布的 npm CLI `@minimax-ai/code@0.4.12` 均默认将用户数据保存在 `~/.minimax`(选择 profile 时为 `~/.minimax-<profile>`)。`MINIMAX_DATA_DIR` 或 `MAVIS_DATA_DIR` 可以覆盖数据目录。安装脚本使用的 `~/.minimax-code` 安装目录与数据目录的选择是两回事。查找或删除配置和会话前,请参阅[账号与数据](docs/installation.md#accounts-and-data)。
Token Plan 需要账号与可用额度。已发布的 npm CLI `@minimax-ai/code@0.4.12` 将用户数据保存在 `~/.minimax`。从本仓库构建的版本会保留 Linux 现有安装的数据目录;Linux 全新安装使用 `$XDG_DATA_HOME/minimax`(默认为 `~/.local/share/minimax`),macOS 和 Windows 仍使用 `~/.minimax`。选择 profile 时,在默认目录名后追加 `-<profile>`。`MINIMAX_DATA_DIR` 或 `MAVIS_DATA_DIR` 可以覆盖数据目录。安装脚本使用的 `~/.minimax-code` 安装目录与数据目录的选择是两回事。查找或删除配置和会话前,请参阅[账号与数据](docs/installation.md#accounts-and-data)。

<details>
<summary>使用自己的 API Key(BYOK)</summary>
Expand Down Expand Up @@ -197,7 +197,7 @@ rm -rf -- "$HOME/.minimax"
Remove-Item -LiteralPath "$env:USERPROFILE\.minimax" -Recurse -Force
```

profile 使用 `~/.minimax-<profile>`;`MINIMAX_DATA_DIR` 或 `MAVIS_DATA_DIR` 可以指定其他位置。只删除确定不再需要的具体目录,不要使用通配符批量删除。如果不再需要自行添加的 MCode 环境变量,也请从 shell 配置或用户环境变量设置中移除对应赋值。
profile 会在默认目录名后追加 `-<profile>`。Linux 全新源码安装使用 `$XDG_DATA_HOME/minimax`(默认为 `~/.local/share/minimax`);`MINIMAX_DATA_DIR` 或 `MAVIS_DATA_DIR` 可以指定其他位置。只删除确定不再需要的具体目录,不要使用通配符批量删除。如果不再需要自行添加的 MCode 环境变量,也请从 shell 配置或用户环境变量设置中移除对应赋值。

## 可以做什么

Expand Down
9 changes: 6 additions & 3 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,12 @@ Source builds and the published npm CLI use the same default user data directory
| CLI artifact | Default user data directory |
| --- | --- |
| Published npm `@minimax-ai/code@0.4.12` | `~/.minimax` |
| Build from this repository | `~/.minimax` |
| Build from this repository on Linux (new installation) | `$XDG_DATA_HOME/minimax`, or `~/.local/share/minimax` |
| Existing Linux installation, or macOS / Windows source build | `~/.minimax` |

The npm 0.4.12 default was checked against the [public registry artifact](https://registry.npmjs.org/@minimax-ai/code/0.4.12) on 2026-09-19, with its SHA-512 integrity verified. This applies to that published version, including local npm dependencies; do not infer the default of another release from its version label alone. A selected profile uses `~/.minimax-<profile>`. The source default is defined in [`data-dir.ts`](../packages/tui/src/runtime/data-dir.ts). Login state, provider configuration such as `config.yaml`, caches, and sessions belong to the selected data directory.
The npm 0.4.12 default was checked against the [public registry artifact](https://registry.npmjs.org/@minimax-ai/code/0.4.12) on 2026-09-19, with its SHA-512 integrity verified. This applies to that published version, including local npm dependencies; do not infer the default of another release from its version label alone. A selected profile appends `-<profile>` to the selected default directory name. The source default is defined in [`data-dir.ts`](../packages/tui/src/runtime/data-dir.ts). Login state, provider configuration such as `config.yaml`, caches, and sessions belong to the selected data directory.

Following the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir/latest/), Linux source builds accept only an absolute `XDG_DATA_HOME`; unset, empty, or relative values fall back to `~/.local/share`. Existing `~/.minimax` directories and symlinks remain authoritative, even when XDG also contains data. Older `~/.mavis` installations retain the existing migration to `~/.minimax`; the CLI performs that migration before exporting its runtime directory. Existing installations are not automatically relocated to XDG, so active databases and old shell PATH entries keep their location. New XDG installations retain a `.mavis` compatibility link.

Both accept a non-empty `MINIMAX_DATA_DIR`, falling back to a non-empty `MAVIS_DATA_DIR`, before the default. The [macOS / Linux / WSL installer](https://filecdn.minimax.chat/public/install.sh) installs the npm package under `~/.minimax-code` by default (`MCODE_INSTALL_DIR` changes the installation location). It does not set either data-directory override. Installation files and user data are separate concerns, even when their directories have the same name.

Expand Down Expand Up @@ -132,7 +135,7 @@ Alternatively, merge this entry into `<data-dir>/tui/keybindings.json`, preservi
}
```

For the default profile this is `~/.minimax/tui/keybindings.json`; [profiles and data-directory overrides](#accounts-and-data) change the path. Create the `tui` directory if needed. After editing the file, run `/reload` while idle with no pending interaction or queued message, or restart MCode. This replaces `Alt+M`; use `["alt+m", "ctrl+x"]` as the value to retain both bindings. `/hotkeys` shows the effective binding.
For the default profile this is `<data-directory>/tui/keybindings.json` (for example, `~/.minimax/tui/keybindings.json` or `~/.local/share/minimax/tui/keybindings.json`); [profiles and data-directory overrides](#accounts-and-data) change the path. Create the `tui` directory if needed. After editing the file, run `/reload` while idle with no pending interaction or queued message, or restart MCode. This replaces `Alt+M`; use `["alt+m", "ctrl+x"]` as the value to retain both bindings. `/hotkeys` shows the effective binding.

### Verify the result

Expand Down
36 changes: 28 additions & 8 deletions packages/config/src/data-dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,28 @@ function basenameForProfile(base: string, profile?: string | null): string {
return profile ? `${base}-${profile}` : base;
}

/** Default for new Linux installations; existing installations keep their location. */
export function getPrimaryDataDirPath(homeDir?: string, profile?: string | null): string {
return path.join(resolveHomeDir(homeDir), basenameForProfile(NEW_DATA_DIR_BASENAME, profile));
const resolvedHomeDir = resolveHomeDir(homeDir);
const previousPrimary = path.join(
resolvedHomeDir,
basenameForProfile(NEW_DATA_DIR_BASENAME, profile),
);
if (process.platform !== 'linux') return previousPrimary;

const xdgDataHome = process.env.XDG_DATA_HOME;
const dataHome = xdgDataHome && path.isAbsolute(xdgDataHome)
? xdgDataHome
: path.join(resolvedHomeDir, '.local', 'share');
const primary = path.join(dataHome, basenameForProfile('minimax', profile));
// Do not relocate a live database, hide existing data, or mistake an inaccessible
// directory / dangling symlink for a fresh install. Older .mavis installations
// retain the existing migration to .minimax. A compat link from an earlier XDG
// startup must not cause the next startup to switch back to .minimax.
if (pathState(previousPrimary).kind !== 'missing') return previousPrimary;
const legacy = getLegacyDataDirPath(resolvedHomeDir, profile);
if (pathState(legacy).kind !== 'missing' && !isLinkTo(legacy, primary)) return previousPrimary;
return primary;
}

export function getLegacyDataDirPath(homeDir?: string, profile?: string | null): string {
Expand Down Expand Up @@ -298,6 +318,13 @@ function resolveDataDirPair(
return newDir;
}

if (newState.kind === 'link' || newState.kind === 'other') {
logger.warn(
`Primary data dir path ${newDir} exists but is not a directory; using it without migration`,
);
return newDir;
}

if (newState.kind === 'directory') {
const newContent = contentState(newDir);
const legacyContent =
Expand Down Expand Up @@ -369,13 +396,6 @@ function resolveDataDirPair(
return legacyDir;
}

if (newState.kind === 'link' || newState.kind === 'other') {
logger.warn(
`Primary data dir path ${newDir} exists but is not a directory; using it without migration`,
);
return newDir;
}

ensurePrimaryDir(newDir, logger);
ensureCompatLink(legacyDir, newDir, logger, nowMs);
return newDir;
Expand Down
Loading
Loading