← Configuration | Usage(中文) | Advanced Usage →
Basic command format:
ve <service> <action> [--Param value ...] [--header Name=Value ...] [--body json]
[--profile name] [--region region] [--endpoint endpoint] [--lang language] [--user-agent value]
[--version api-version] [--method GET|POST] [--force]
[--output json|table|table-num|text|yaml|off] [--query jmespath]Argument kinds:
- API parameters: double-dash
--Param value(enter request body/query; reserved namesbody/headerexcluded) - Public system flags (after the action):
--profile/--region/--endpoint/--lang/--user-agent/--version/--method/--force/--output/--query - Reserved double-dash controls:
--header(HTTP headers) and--body(JSON body); the controls themselves are not API parameters
System flags in API calls use double hyphens and are placed after the action. If an action exposes an exact-name API parameter (case-sensitive), the double-dash form is parsed as the API parameter.
The CLI has exactly one public flag prefix: double dash --name. System flags, API parameters and the reserved controls (--header / --body) all use double dashes.
- Help output, shell completion, error messages and documentation examples show the
--nameform only. - Conflicts are case-sensitive and resolved against the parameters the current action actually exposes:
--Regionand--Langare always API parameters. - When an action exposes an API parameter with the exact name of a system flag, the double-dash form after that action is parsed as the API parameter; use an equivalent non-flag route for the system behaviour (see Known Name Conflicts).
List supported services:
ve --helpList actions under a service:
ve ecs --helpShow action parameters:
ve ecs DescribeInstances --helpBy default, -h / --help uses concise mode and shows parameter names, types, and required status without loading the full parameter corpus. Use detail mode to include descriptions and examples:
ve ecs DescribeInstances -h --detail
ve ecs DescribeInstances --help --detailUsing --detail by itself does not trigger help.
Show version:
ve version
ve -vve docs search "object storage quick start" --service-code tos --limit 3
ve docs fetch "https://www.volcengine.com/docs/6349/74830" --max-length 1000These commands do not require login. Before the first request that passes argument validation, the CLI generates an RFC 9562 UUIDv4, saves it in ~/.volcengine/client_id, and sends it in the X-Client-Id header on documentation search and fetch requests. On Windows, the path is %USERPROFILE%\.volcengine\client_id.
- The identifier contains 122 cryptographically random bits. It does not use a MAC address, hardware serial number, or account credentials.
- A client is the local CLI configuration of one operating-system user. The identifier is reused across restarts, upgrades, logins, and profile switches. Other users or new devices generate independent identifiers.
- The file is separate from
config.jsonand login caches. Only these two documentation APIs automatically send the identifier; other APIs, User-Agent values, request bodies, and output formats retain their existing behavior. Help, version, and invalid arguments do not create the file. - First-time creation requires a writable directory and a filesystem supporting hard links, such as common Unix filesystems or Windows NTFS. Concurrent first callers publish only one complete identifier. Newly created directories and files use Unix modes
0700and0600; an existing identifier only needs to be readable. - If the identifier cannot be read, persisted, or validated, the documentation command fails without sending a request with a missing or temporary identity. Deleting
client_idcauses the next documentation call to generate a new identifier. Exclude this file when copying configuration to another device or preparing an image so client identities are not duplicated.
Call without parameters:
ve sts GetCallerIdentityCall with parameters:
ve ecs DescribeInstances --InstanceIds.1 i-1234567890abcdef0Multiple parameters:
ve rds_mysql ListDBInstanceIPLists --InstanceId mysql-xxxxxx --GroupName defaultParameter names and values are separated by spaces. The supported syntax is:
--Param value
--user-agent deployment-tool/2.1
--region cn-beijingDo not use --Param=value, --user-agent=deployment-tool/2.1, --region=cn-beijing, or --lang=ZH. Flag names and values must be separated by a space.
Public system flags use the standard double-hyphen form:
| Flag | Purpose |
|---|---|
--profile |
Use a specific profile for this invocation without changing current |
--region |
Override region for this invocation |
--endpoint |
Override endpoint for this invocation and clear endpoint resolver |
--lang |
Set the language of CLI-owned help, prompts, and errors for this invocation |
--user-agent |
Append a custom identifier to the default HTTP User-Agent for this invocation |
--version |
Set the API version for this call; if omitted, uses the bundled service version (not the CLI binary version from root ve -v / ve --version / ve version) |
--force |
Skip service/action metadata validation and force-call unlisted or newly released APIs; unlisted services require --version and a fixed endpoint (--endpoint or profile/VOLCENGINE_ENDPOINT when resolver is not standard); bundled services can fall back to metadata. Presence-only: write --force alone, not --force true |
--method |
HTTP method (GET/POST); same rules on normal and --force paths: explicit value wins, else action metadata, else GET |
--output |
API response format: json (default), table, table-num, text, yaml, off |
--query |
JMESPath expression to filter/project the full response JSON (including ResponseMetadata and Result) before formatting |
After the action, a double-dash flag whose exact case-sensitive name is exposed by that action is parsed as an API parameter. Without such a conflict, it is parsed as a system flag.
Names with different casing, such as --Region or --Endpoint, are always API parameters.
--user-agent preserves the CLI default User-Agent and appends the supplied value. Leading and trailing whitespace is removed; empty values and values containing control characters such as newlines are rejected.
ve ecs DescribeInstances --user-agent deployment-tool/2.1
ve ecs DescribeInstances \
--InstanceIds.1 i-1234567890abcdef0 \
--user-agent "inventory-sync/3.4 team/compute"| Flag | Purpose |
|---|---|
--header Name=Value |
Add an HTTP request header; repeatable; never enters the request body. Content-Type overrides metadata; last value wins for the same name |
--body json |
JSON request body for application/json style calls; mutually exclusive with other API parameters |
ve sts GetCallerIdentity --header X-Custom-Trace=abc
ve newsvc Act --force --version 2024-01-01 --endpoint open.volcengineapi.com \
--header Content-Type=application/json \
--header X-Feature=on \
--body '{"k":1}'Notes:
- Override
Content-Typewith--header Content-Type=...; forms with parameters (e.g.application/json; charset=utf-8) are still treated as JSON - With
--bodyand no metadata, Content-Type defaults toapplication/json --headercan be used with--body; headers are not flattened API params and do not conflict with--body- Blocked header names:
Host,Authorization,Content-Length(transport/signing) - Reserved names:
--headerand--bodycannot be used as ordinary API parameter names
Examples:
# Use a specific profile
ve ecs DescribeInstances --profile prod
# Use a specific profile and override region
ve ecs DescribeInstances --profile prod --region ap-southeast-1
# Override only region
ve ecs DescribeInstances --region cn-shanghai
# Specify endpoint for an STS call
ve sts GetCallerIdentity --region cn-beijing --endpoint sts.volcengineapi.comIf --profile references a profile that does not exist, the command returns an error.
Known exact-name conflicts include:
--langoni18nopenapi VideoProjectSuppressionStart: after that action--langis the API parameter; switch the CLI display language through theLC_ALL/LC_MESSAGES/LANGenvironment variables instead (see Display Language)--queryoninsight AgentChat: after that action--queryis the API parameter; keep the default JSON output and filter it downstream
The same rule applies if other actions later expose colliding names: the double-dash form after that action is the API parameter.
For an unlisted action, metadata cannot declare a collision, so --query and --output retain their public system meanings.
Use --lang EN for English or --lang ZH for Simplified Chinese. Locale forms such as en-US, en_US, zh-CN, zh_CN, and zh-Hans are also accepted. Unsupported values fall back to English.
When --lang is omitted, the CLI checks LC_ALL, LC_MESSAGES, and LANG in that order, then falls back to English. The explicit flag takes precedence and is not persisted to the configuration file.
ve sts GetCallerIdentity --lang ZH --help
ve ecs DescribeInstances --lang EN --help
ve login --lang zh-CNLanguage selection only affects text generated by the CLI. API response bodies and server-provided content are not translated or modified.
For query/form APIs, if a parameter value is a JSON object or JSON array, the CLI attempts to parse it as JSON:
ve rds_mysql ModifyDBInstanceIPList \
--InstanceId mysql-xxxxxx \
--GroupName default \
--IPList '["10.20.30.40","50.60.70.80"]'String parameters are kept as strings and are not forcibly parsed just because they look like JSON.
For APIs whose ContentType is application/json, pass a JSON body directly:
ve rds_mysql ModifyDBInstanceIPList \
--body '{"InstanceId":"mysql-xxxxxx","GroupName":"default","IPList":["10.20.30.40","50.60.70.80"]}'--body must be a JSON object or JSON array. It cannot be mixed with flattened parameters:
# Wrong: --body cannot be used together with other API parameters
ve rds_mysql ModifyDBInstanceIPList --body '{"InstanceId":"mysql-xxxxxx"}' --GroupName defaultapplication/json APIs also support dotted keys. The CLI expands them into nested JSON using metadata:
ve some_service SomeJsonAction \
--Name demo \
--Ports.1 80 \
--Ports.2 443 \
--Tags.1.Key env \
--Tags.1.Value prodArray indices are 1-based and must be contiguous. 0, negative indices, and skipped indices are errors.
Common array syntax:
ve ecs DescribeInstances --InstanceIds.1 i-123 --InstanceIds.2 i-456Array of objects:
ve some_service SomeAction \
--Filters.1.Key InstanceType \
--Filters.1.Values.1 ecs.g1.large \
--Filters.1.Values.2 ecs.g2.largeFor application/json APIs, dotted keys are restored to nested objects and arrays. For non-JSON APIs, dotted keys are preserved and handled by the service/API layer.
The CLI allows unknown API parameters to pass through to the service/API layer. Unless the parameter path itself is invalid, the CLI does not reject a parameter only because it is absent from metadata.
Example:
ve ecs DescribeInstances --NewServerSideParam valueThis is useful when the service has added a parameter but local metadata has not been updated yet.
The CLI validates services and actions against built-in metadata. If the service or action is not yet bundled, use --force to bypass validation; unlisted services also require --version and a fixed endpoint (--endpoint, or profile / VOLCENGINE_ENDPOINT when endpoint-resolver is not standard) because the CLI has no metadata from which to resolve a host. Bundled services can omit these overrides in force mode and use metadata with the same endpoint rules as normal calls. See Advanced Usage: Force Invocation.
ve newservice DescribeNewResource \
--version 2024-01-01 \
--endpoint open.volcengineapi.com \
--SomeParam value \
--forceUse current profile:
ve ecs DescribeInstancesUse a non-current profile:
ve ecs DescribeInstances --profile prodUse environment-based default credential chain:
export VOLCENGINE_ACCESS_KEY=AK
export VOLCENGINE_SECRET_KEY=SK
export VOLCENGINE_REGION=cn-beijing
ve ecs DescribeInstancesUse an OIDC profile:
ve configure set --profile ci-oidc --mode oidc --region cn-beijing \
--oidc-token-file /var/run/secrets/oidc-token \
--role-trn trn:iam::2100000000:role/CIRole
ve ecs DescribeInstances --profile ci-oidcUse an ECS instance role profile:
ve configure set --profile ecs-role --mode ecsrole --region cn-beijing --role-name MyRole
ve ecs DescribeInstances --profile ecs-roleMissing credentials:
credentials not configured, please run 've login' or 've configure set', or set VOLCENGINE_ACCESS_KEY and VOLCENGINE_SECRET_KEY environment variables
Missing region:
region not set, please set it via profile, --region flag, or VOLCENGINE_REGION environment variable
Public system flags (double-dash): --profile, --region, --endpoint, --lang, --force, --version, --method, --output, --query.
Reserved double-dash controls: --header, --body (see “Reserved Double-Dash Controls” above).
After a successful API call, the CLI prints the full response JSON (typically ResponseMetadata + Result) to stdout by default. Use system flags to control presentation:
| Flag | Description |
|---|---|
--output |
Format: json (default), table, table-num, text, yaml, off |
--query |
JMESPath applied before formatting; paths are relative to the full response (list data is usually under Result.*) |
Pipeline: raw response → [--query] → [--output] → stdout (query before format; Volcengine envelope field paths).
# Project then table (recommended for list APIs; use --query to pick the fields)
# Column order follows the multi-select hash you wrote: the hash below is
# Name, Id, Status, so the columns are Name, Id, Status.
ve ecs DescribeInstances \
--query 'Result.Instances[*].{Name:InstanceName,Id:InstanceId,Status:Status}' \
--output table
# Row numbers: table-num adds a leading # column starting at 1
ve ecs DescribeInstances \
--query 'Result.Instances[*].{Name:InstanceName,Id:InstanceId}' \
--output table-num
# Tab-separated text for awk/grep (one record per line, so `nl` numbers records)
ve sts GetCallerIdentity --query 'Result.AccountId' --output text
ve ecs DescribeInstances --query 'Result.Instances[*].{Id:InstanceId}' --output text | nl
# Without --query, table renders the full response and splits nested data into titled sections.
ve sts GetCallerIdentity --output table
# YAML
ve sts GetCallerIdentity --output yaml
# Exit code only (API call still runs)
ve ecs DescribeInstances --output offNotes:
- No field is ever dropped: every format renders exactly the data it is given, so
ResponseMetadata(withRequestId) is shown bytable/table-num/textjust as it is byjson/yaml; no renderer decides a field is uninteresting. The formats differ on exactly one point: a field whose value is an empty list or an empty object givestextnothing to put on a line, so it stays visible injson/yaml/tablebut produces notextoutput (see the empty-value bullet below; use--output jsonwhen a script must tell an absent field from an empty one).--outputonly changes layout:tablegives the envelope its own titled section,textprefixes it asRESPONSEMETADATA. Use--querywhen you want less:--query 'Result'drops the envelope,--query 'ResponseMetadata.RequestId'keeps only the request id, and--query '@'is the full response. - Nested sections:
tablesplits nested objects and record lists into separate titled sections (the title is the field path, e.g.Result.Instances.Tags[1]) instead of dumping JSON into a cell. A nested field also stays as a main-table column, where the cell reads(see section)and points at the matching section; when the same field is a scalar,nullor an empty list on some records, those values are still shown in the main table rather than being dropped because another record nests it. Section numbering starts at 1 and matches the#column oftable-num, so a section can be traced back to its record. No number is added when the parent list holds a single record. Lists of plain scalars (e.g.["sg-1","sg-2"]) stay inline in the cell. - Single-record verticalization: a single object (and any single-row result) renders as one horizontal record — a field-name header row plus a value row, matching the AWS CLI. Only when the terminal width is known and that row is wider than it, the record is transposed into a two-column
Field | Valuetable to avoid horizontal scrolling. Multi-row results and any case where the width is unknown (redirected output, pipes, failed probe) keep the horizontal layout. - Terminal width fitting: when writing to a terminal the width is detected automatically; over-wide grids shrink the widest column first and wrap cell content onto additional physical rows without discarding response values. Every column keeps a minimum readable width. Redirected or piped output is not wrapped, so each value stays on one complete line.
- Column order: with a
--querymulti-select hash ({Key:Path,...}),table/table-num/textfollow the order you wrote — for both record lists and a single object (for a single object this is the header-column order). Everything else (no--query, plain path projection, expressions such asmerge()where the order cannot be determined statically, or duplicate keys in the hash) falls back to alphabetical field order. A hint that does not match the actual fields is discarded as a whole, so ordering is never applied partially and no column is lost. The order applies to the level the hash projected; objects nested inside a projected row keep alphabetical order in bothtablesections andtextlines. Write an explicit multi-select hash when you need a fixed column order. - Row numbers:
table-numadds a leading#column to record results. A single object is one record, so it is numbered1; a list is numbered from 1 in order. Numbering starts at 1 and exists for human reference; scripts should read values via--output json/textrather than the#column. - Color: when
enableColoris on and output goes to a terminal,table/table-numstyle headers and cells; redirected output, pipes andNO_COLORdisable it. Styling never affects column widths or alignment. - Do not pipe
--output tablethroughnl:nlnumbers borders and the header too, so the numbers no longer line up with data rows. Use--output table-numfor tables, or--output text | nlfor TSV. table/table-num/textrender newlines, tabs, and terminal control characters as visible escapes so response data cannot break row/column boundaries or inject terminal controls.- For a stable human-readable output contract, booleans are rendered as
True/Falseintable,table-num, andtext;jsonandyamlkeep their native lowercasetrue/falsesyntax. - On name conflicts (e.g.
insight AgentChat--query), the double-dash form after that action is the API parameter, so the same-named system flag is unavailable for that call; see Known Name Conflicts. - Empty lists:
table/table-numprint(empty);textprints no lines (easy empty check in scripts). A missing/null--querypath printsNonein table/text. An empty object{}is not an empty list: table prints a header-only record with no value row; text prints no lines. A non-empty list made only of empty objects or empty positional records keeps one{}or[]row per record in table output (and remains numbered bytable-num), while text has no fields or values to print. textoutput is not type-distinguishing: an empty list[]and an empty object{}both print no lines; a missing/null--querypath printsNone; the literal stringNoneis also rendered asNone. Use--output jsonwhen you need unambiguous type or emptiness checks.textrecursively flattens any response: like the AWS CLI text formatter,textnever prints a JSON blob. A baretext(no--query) is flattened to TSV: an object's scalar fields become one row, and each nested object/list recurses onto its own line(s) prefixed by its UPPERCASED field path (for exampleRESULT.INSTANCELIST\t...). A list of objects shares one column set with one row per object: a field that is missing ornullon a record readsNone, and a field that is a scalar on one record but structured on another still shows its value — inline when there are no flattened lines to point at (a scalar list such as["sg-1","sg-2"], or nesting that bottoms out in empty lists/objects), otherwise(see section)pointing at the flattened lines immediately below, which is also whattableputs in that cell.Nonetherefore always means "absent or null", and(see section)never points at a line that was not printed. Deeper positional or object-list projections are expanded recursively, nested empty lists or objects do not create phantom blank rows, and object columns still follow a--querymultiselect hash. A top-level scalar list joins into a single Tab-separated row; use--queryto project into the exact one-record-per-line shape when piping tonl/grep. Nesting deeper than 8 levels is printed as compact JSON, exactly astabledoes — real responses stay far short of that, the limit only bounds a pathological one.textrow labels: the first column is the full path of the node a line came from, soawk -F'\t' '$1=="RESULT.INSTANCELIST"'selects exactly the record rows, and the record fields start at$2. Every record of one list shares the same label, and the label never depends on how many records came back:RESULT.INSTANCELIST.TAGSis the label whether the response holds one instance or fifty, so an exact$1comparison written against a one-record response keeps working in production. A nested line is attributed to its record by line order — it is emitted immediately after that record's own row — which is how the AWS CLI text formatter works too; a script tracks the last record row it saw. Onlytablenumbers its sections (Result.Instances.Tags[2]), because it prints every record before any nested section and so has no adjacent row to rely on; strip that[n]and the two formats name the same node. Note that positional TSV has no field names: for a stable, self-explanatory column set, project with a--querymultiselect hash.--output offstill sends the API request and writes nothing to stdout. It skips response-dependent--queryevaluation, but the expression's syntax, function calls, and exact-number safety rules are still validated before the request.--queryerrors are caught before the request: syntax errors, unknown function names (lenght(@)), wrong argument counts (length(@, @)), incomplete expressions (a | [0), and queries rejected by the exact-number safety rules are reported before the API is called. The message includes the original expression, a^marker under the failure, and an actionable hint; a misspelled function name suggests the closest builtin. Non-ASCII field names must be double-quoted, as in--query '"实例列表"."数据"'.- A query that passes preflight can still fail while evaluating the actual response, for example
starts_with(Result, 'x')whenResultis an object rather than a string. This happens after the API call; the process exits 1 withAPI call succeeded but response output failed. With--output off, this response-dependent evaluation is intentionally skipped. - API failures (for example HTTP 403) print the error on stderr and do not go through
--output/--query. - Exact-number queries: field selection, projection, filters, comparisons (
==/!=/</>/<=/>=),contains,max/min/sum/avg/abs/ceil/floor/to_number/sort, andmax_by/min_by/sort_byover numbers all use exact JSON decimal values, as in[?Cpu > `4`],AccountId == `2106494982`, andcontains(Result.Numbers, `9007199254740993`). Equivalent spellings such as1/1.0/1e0compare equal, integers above 2^53 are not rounded, and projection still emits the original JSON token.avgis the only operation that can round, and only when the exact result is a repeating decimal; it then keeps at least 34 significant digits. Arithmetic on a token whose decimal exponent exceeds 10000, such as1e20000, is refused with an explicit error rather than silently rounded; comparison, sorting andabsremain exact for such tokens. - YAML numbers:
--output yamlemits response integers as!!intscalars and decimal/exponent numbers as!!floatscalars while preserving the original JSON numeric token, including very large integers, long decimals, exponent spelling, and trailing zeros. Numbers are not silently rounded and long decimals are not converted to strings. YAML object keys are sorted alphabetically. The yaml.v3 encoder may indent sequences differently from earlier releases; this is a presentation-only change and the parsed YAML data is equivalent. Do not depend on byte-for-byte YAML whitespace.--querywrite order affectstable/table-num/textcolumns, not YAML key order.
← Configuration | Usage(中文) | Advanced Usage →