Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/01-bug-report.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Bug report
description: Report a reproducible problem with the Desktop app, CLI, or source build.
title: "[Bug]: "
labels: ["bug"]
labels: ["bug", "needs-triage"]
body:
- type: markdown
attributes:
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/02-feature-request.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Feature request
description: Suggest an improvement to the Desktop app, CLI, or source distribution.
title: "[Feature]: "
labels: ["enhancement"]
labels: ["enhancement", "needs-triage"]
body:
- type: dropdown
id: product
Expand Down
16 changes: 9 additions & 7 deletions .github/ISSUE_TEMPLATE/03-question.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
name: Usage question
description: Ask about the Desktop app, CLI, or building from source.
name: Usage or repository policy question
description: Ask about the Desktop app, CLI, source builds, or contribution policy.
title: "[Question]: "
labels: ["question"]
labels: ["question", "needs-triage"]
body:
- type: dropdown
id: product
attributes:
label: Product or interface
description: Leave blank if unsure or asking about repository policy.
options:
- Desktop app
- CLI - interactive TUI
- CLI - headless
- CLI - ACP
- Source build or repository tooling
validations:
required: true
required: false
- type: textarea
id: question
attributes:
Expand All @@ -25,18 +26,19 @@ body:
id: platform
attributes:
label: Platform
description: Leave blank if unknown or not applicable.
options:
- macOS
- Windows
- Linux
- WSL
- Multiple platforms
validations:
required: true
required: false
- type: textarea
id: context
attributes:
label: Version and what you have tried
description: Include documentation you followed and relevant redacted output. Do not include keys or account data.
label: Version or policy context
description: For usage questions, include your version and what you tried. For policy questions, link the relevant policy. Do not include keys or account data.
validations:
required: true
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Contribution policy
url: https://github.com/MiniMax-AI/minimax-code/blob/main/CONTRIBUTING.md
about: Everyone may report issues and suggest improvements. Pull requests are accepted only from repository collaborators; external PRs are not accepted.
- name: CLI quick start and troubleshooting
url: https://agent.minimax.io/docs/cli/quick-start
about: Installation, account regions, first tasks, and links to troubleshooting.
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/docs.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Documentation issue
description: Report missing, incorrect, or unclear documentation.
title: "[Docs] "
labels: ["documentation", "needs-triage"]
body:
- type: input
id: location
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ mcode

Supported API formats: `openai-completions`, `openai-responses`, and `anthropic-messages`. See the [model examples](docs/examples.md#2-choose-your-own-model) for environment variable setup, connection checks, and model overrides for a single run.

Providers added this way are stored under `custom_provider` in the active profile's `config.yaml`; this is the supported path for third-party or self-hosted endpoints, while `minimax_api` stays reserved for the official MiniMax API. Relays that require `Authorization: Bearer` on an Anthropic-compatible endpoint can set custom headers in `config.yaml`; see [Third-party relays and custom auth headers](docs/examples.md#third-party-relays-and-custom-auth-headers).

</details>

### 3. Run your first task
Expand Down
2 changes: 2 additions & 0 deletions README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ mcode

支持 `openai-completions`、`openai-responses` 和 `anthropic-messages`。连接测试、单次模型切换及环境变量设置见 [模型示例](docs/examples.md#2-choose-your-own-model)。

通过该命令添加的提供方保存在当前 profile `config.yaml` 的 `custom_provider` 下;第三方或自建端点一律走这条路径,`minimax_api` 保留给官方 MiniMax API。若中转端点只提供 Anthropic 兼容接口且要求 `Authorization: Bearer` 鉴权,可在 `config.yaml` 中为提供方配置自定义 headers;见[第三方中转与自定义鉴权头](docs/examples.md#third-party-relays-and-custom-auth-headers)。

</details>

### 3. 完成第一个任务
Expand Down
55 changes: 55 additions & 0 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,65 @@ pnpm mcode provider list --json

`--api-key-env` reads the current environment variable value and stores that value in the active profile's `config.yaml`; it does not save an environment-variable reference. The file still contains plaintext credentials. On POSIX systems, config writes and temporary copies use `0600`. When loading existing files, MCode removes group/other access while preserving the owner's permissions; already-private files such as `0400` or `0600` do not require a permission change. Loading fails if an unsafe main config cannot be restricted. Older migration backups are also checked, but inspection or repair failures produce a warning identifying the directory or backup that needs manual attention rather than preventing the main config from loading. Windows file modes do not provide equivalent ACL protection; restrict access to the profile directory using Windows permissions.

### Third-party relays and custom auth headers

Providers created by `mcode provider add` are stored under `custom_provider` in the active profile's `config.yaml`. That tree is the supported home for any endpoint other than the official MiniMax API; `minimax_api` is reserved for the official endpoint and keeps its fixed authentication scheme.

Authentication follows the API format: `openai-completions` and `openai-responses` send `Authorization: Bearer <key>`, and `anthropic-messages` sends the key as `x-api-key`. A relay that expects Bearer authentication on an OpenAI-compatible endpoint therefore needs no extra configuration. If a relay only exposes an Anthropic-compatible endpoint (`/v1/messages`) and requires Bearer authentication, add explicit headers to the provider entry in `config.yaml`:

```yaml
custom_provider:
my-relay:
options:
apiKey: sk-relay-key
baseURL: https://relay.example.com
headers:
Authorization: Bearer sk-relay-key
models:
MiniMax-M2: {}
```

`api` can be omitted and defaults to `anthropic-messages`. Configured headers are sent on both connection tests and conversation requests, and they are part of the connection-test fingerprint, so editing them retires a cached test verdict. The default `x-api-key` header is still sent alongside; the relay must tolerate rather than reject it. Header values are stored in plaintext like `apiKey` and are reported by name only in provider views. After editing the file, verify with `mcode provider list` and `mcode provider test <provider-id>`.

[Live acceptance](verification.md) separately verified MiniMax Token Plan and one configured BYOK provider. This is not a guarantee for every compatible service.

## 3. Search and image input

For a custom BYOK model, declare image input support explicitly when adding the
provider. Use this only if the selected provider endpoint and model accept images:

```bash
pnpm mcode provider add --name my-vision-provider --base-url https://example.com/v1 \
--api-format openai-completions --model my-vision-model \
--api-key-env MCODE_PROVIDER_API_KEY --support-image --use
```

`--support-image` applies to every repeated `--model` and saves
`capabilities.support_image: true`. Without it, adding an unknown custom model
does not infer image support from its name. `--use` and `provider test` check
connectivity with a text request; they do not verify vision support.

For an existing provider, close MCode and add the capability to the matching model
in the active profile's `config.yaml` (normally `~/.minimax/config.yaml`; see
[Accounts and data](installation.md#accounts-and-data) for profiles and overrides).
Merge this fragment into the existing provider and keep its other settings:

```yaml
custom_provider:
my-vision-provider:
models:
my-vision-model:
capabilities:
support_image: true
```

The existing `modalities: { input: [text, image], output: [text] }` model setting
also enables image input. Either declaration is sufficient. To make a model
text-only again, remove `image` from `modalities.input` and remove or set
`capabilities.support_image` to `false`. Generic `attachment: true` alone does not
declare image input support. Restart MCode after editing configuration and select
the configured model with `/provider`, or use `exec --model` for a single run.

After signing in to MiniMax, try a task that explicitly requires search:

> Use web_search to find the official Node.js test runner documentation. Summarize how to run tests and include the source URL. If the tool is unavailable, say so.
Expand Down
46 changes: 46 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,52 @@ To locate data safely:

For tests, explicitly set `MINIMAX_DATA_DIR` to a temporary directory to keep normal sessions separate. Use `$env:MINIMAX_DATA_DIR = 'C:\path\to\test-profile'` in PowerShell or `export MINIMAX_DATA_DIR=/path/to/test-profile` in a POSIX shell.

## macOS terminal shortcuts: Ghostty Option+M

In the composer, `Alt+M` (`Option+M` on macOS) cycles permission modes through Ask, Auto, and Full access. Its binding ID is `composer.cycle-permission`. `Shift+Tab` toggles **Plan mode**, a separate setting. You can also use `/permission` to choose a permission mode and `/permission status` to inspect it without an Option shortcut.

If `Option+M` inserts `µ` instead, the terminal is sending text rather than the expected Alt shortcut. MCode preserves literal `µ` as text; it cannot safely infer a permission change from that character. The terminal must forward the modifier, or you can choose another binding.

### Configure Ghostty's Option key

Ghostty's [`macos-option-as-alt`](https://ghostty.org/docs/config/reference#macos-option-as-alt) default is **keyboard-layout dependent** when unset, not always `false`. The current reference lists U.S. Standard and U.S. International as defaulting to `true`; other layouts default to `false`. Check the active macOS input source and the configuration loaded by your installed Ghostty version.

Set this in your Ghostty configuration to send both Option keys as Alt:

```ini
macos-option-as-alt = true
```

Use `left` or `right` instead of `true` to reserve only that Option key for shortcuts and retain Unicode composition on the other side. Use the configured side when testing `Option+M`.

Follow Ghostty's [configuration locations and precedence](https://ghostty.org/docs/config#file-location): macOS-specific files load after XDG files, and later settings can override earlier ones. Inspect the loaded setting from the same Ghostty installation, without `--default`:

```bash
ghostty +show-config | awk '/^macos-option-as-alt[[:space:]]*=/'
```

If `ghostty` is not on `PATH`, use the executable inside your installed app bundle, typically `/Applications/Ghostty.app/Contents/MacOS/ghostty`. An empty or omitted value is not proof of `false`; unset behavior depends on the layout. After editing, reload Ghostty's configuration from its menu (default `Cmd+Shift+,`) and open a new terminal. This is separate from MCode's `/reload` command.

### Keep Option for text and customize MCode instead

While idle, open `/hotkeys`, select `composer.cycle-permission`, press `Enter`, press `Ctrl+X`, then press `Enter` to save. `Ctrl+X` is unused by the current default MCode bindings; check any custom terminal or multiplexer bindings too. Do not choose `Ctrl+M`: terminals commonly encode it identically to `Enter`.

Alternatively, merge this entry into `<data-dir>/tui/keybindings.json`, preserving any existing entries:

```json
{
"composer.cycle-permission": "ctrl+x"
}
```

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.

### Verify the result

With an idle composer and no open picker or permission prompt, note `/permission status`, press the configured shortcut, and check the status again. The mode should advance without inserting text. Restore your intended permission mode through `/permission` afterward. Confirm that `Shift+Tab` still toggles Plan mode and that pasting `µ` still inserts text.

If it still fails, record `mcode --version`, Ghostty's version, active keyboard layout, which Option key you pressed, the setting above, the effective `/hotkeys` entry, and whether tmux or SSH is involved. Compare with a direct Ghostty session. MCode supports both legacy ESC-prefixed Alt input and extended keyboard reports; a shell's raw-key display alone does not establish what Ghostty sends after the TUI negotiates its keyboard protocol.

## Update or remove

Save your changes, fetch a reviewed revision with Git, then repeat the frozen install and build. A source installation does not automatically become an official npm installation.
Expand Down
23 changes: 23 additions & 0 deletions docs/maintainers.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,29 @@

These are repository maintenance responsibilities, not an assertion that an account owns the product's copyright. Every PR that requires approval needs a reviewer other than the author, and security reports need a working private response path. Review maintainer additions and policy changes in a PR; do not silently grant repository access.

## Issue triage

Published source covers the standalone CLI (interactive TUI, headless and ACP). The issue tracker also collects Desktop app feedback; accepting those reports does not expand the published source scope.

Everyone may report bugs, request features, ask questions, and flag documentation problems. Code and documentation PRs are accepted only from repository collaborators. Opening an issue or having a proposal accepted does not grant collaborator access or permission to submit a PR. Do not use `good first issue` or `help wanted` while external PRs are closed.

Use these labels independently:

| Category | Labels and meaning |
| --- | --- |
| Type | `bug`: reported malfunction; `enhancement`: requested improvement; `documentation`: missing or incorrect docs; `question`: usage or project-policy question |
| Product | `desktop`: Desktop app; `cli`: standalone mcode, including TUI, headless, ACP and its source builds/tooling |
| Triage | `needs-triage`: awaiting maintainer assessment; `needs-info`: a maintainer has asked the reporter for specific missing information |

1. Start with [needs-triage](https://github.com/MiniMax-AI/minimax-code/issues?q=is%3Aissue+is%3Aopen+label%3Aneeds-triage) and [unlabelled issues](https://github.com/MiniMax-AI/minimax-code/issues?q=is%3Aissue+is%3Aopen+no%3Alabel). Templates add a type and `needs-triage`; reports created through other routes may need both added manually. A type label describes the report and does not confirm a defect or commit to implementation.
2. Confirm one primary type and apply `desktop` or `cli` from the report. Product dropdowns stay in the body; maintainers apply product labels manually. Use both only when the report establishes that both are affected. Leave product labels unset for unclear reports or repository-policy questions. The existing `tui` label may supplement `cli` for interactive-terminal-specific issues; it does not cover headless or ACP.
3. If information is missing, ask for the specific version, reproduction, or expected behavior, replace `needs-triage` with `needs-info`, and retain any known type/product labels. When the reporter replies, remove `needs-info` and reassess. Do not automatically close issues for inactivity.
4. Once assessed, remove `needs-triage` and record the next step in a comment. Assign a collaborator when someone takes responsibility; classification alone does not promise a fix or release date. For duplicates, link the original issue before closing with `duplicate`. For declined requests, explain the reason before closing with `wontfix`.

Route security reports through [Security](../SECURITY.md). Do not ask for secrets or unredacted logs in public issues. Label setup is a separate repository operation: ensure the labels above exist before merging template changes, since forms cannot create missing labels. The Feishu workflow sends notifications only; it does not perform triage.

This small label set draws on the type and information-request handling in [VS Code's triage guide](https://github.com/microsoft/vscode/wiki/Issues-Triaging) and the `needs-triage`/`needs-info` states used by [Ruff](https://github.com/astral-sh/ruff/labels). Contribution eligibility follows this repository's policy.

## Review and merge

1. Repository collaborators open an issue for substantial scope or submit a focused feature-branch PR. Other users may open issues to discuss ideas and proposals. Security details follow the private reporting process.
Expand Down
18 changes: 17 additions & 1 deletion docs/tui-capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,20 @@ Every collected diagnostic artifact, including prioritized session artifacts, is

There is no raw-attachment upload option in this flow. Prompts, conversation text, tool arguments/results, command output, workspace excerpts, raw errors and unknown fields are excluded even if they contain no recognizable credential pattern. This intentionally reduces diagnostic detail: reproducing an exact response or inspecting an original stack is not possible from these uploads. Future raw attachments would require a separate, explicit review and consent surface describing their contents and scope.

The regression tests use temporary synthetic files and intercepted HTTP only. They decrypt the final automatic-report request as a receiver would, and unzip the actual feedback PUT body after real session-report collection. They do not validate production ingestion, retention policies, live services, or other platforms.
## Interactive startup model

Use `mcode -m <provider-id>/<model-id>` or
`mcode "Fix the failing tests" --model <provider-id>/<model-id>` to select the
model for the startup Session. References use the same syntax as `exec --model`,
including `custom_provider:<id>/<model-id>`, model IDs containing `/`, and the
optional `#variant` suffix. The provider must already be configured and the model
must be available to Runtime; invalid references fail before the initial prompt runs.

Without a resume option, this creates a new Session even when no prompt is given.
With `--session <id>` or `--continue`, it updates the opened Session's model before
submitting the prompt. The selection is saved with that Session, so later turns
and resumes keep it. It does not change the global default, and `/new` returns to
the configured default. Omitting `--model` preserves existing startup behavior.
The untargeted `--session` picker cannot be combined with `--model`; provide an ID
or use `--continue` instead. If opening or continuing a Session fails, the override
and initial prompt are not applied.
4 changes: 3 additions & 1 deletion packages/agent-modules/permission/src/tools/fs-permission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -687,8 +687,10 @@ function isProtectedRuntimeRead(
// at credentials must not turn its destination into a trusted asset root.
const readableAsset =
within(canonicalPath, path.join(canonicalRoot, 'skills')) ||
within(canonicalPath, path.join(canonicalRoot, '.builtin-skills')) ||
(context.agentName != null &&
within(canonicalPath, path.join(canonicalRoot, 'agents', context.agentName, 'workspace'))) ||
(within(canonicalPath, path.join(canonicalRoot, 'agents', context.agentName, 'workspace')) ||
within(canonicalPath, path.join(canonicalRoot, 'agents', context.agentName, 'skills')))) ||
isInternalWhitelistedPath(canonicalPath, {
...context,
dataDir: canonicalRoot,
Expand Down
Loading
Loading