Skip to content
Merged
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
65 changes: 65 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
fail_fast: true

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.10
Expand All @@ -10,21 +12,84 @@ repos:
files: ^python/
- repo: local
hooks:
# ── Go ──────────────────────────────────────────────────────────────
- id: gofmt
name: gofmt
entry: bash -c 'cd go && files=$(gofmt -l .); [ -z "$files" ] || gofmt -l -w $files'
language: system
files: ^go/.*\.go$
pass_filenames: false
priority: 10
- id: govet
name: go vet
entry: bash -c 'cd go && go vet ./...'
language: system
files: ^go/.*\.go$
pass_filenames: false
priority: 20
- id: gotest
name: go test
entry: bash -c 'cd go && go test ./...'
language: system
files: ^go/.*\.go$
pass_filenames: false
require_serial: true
priority: 30

# ── JS SDK (js/) ────────────────────────────────────────────────────
# Mirrors release-npm.yml: lint → type-check → test (build is covered by CI).
- id: biome-js
name: Biome (JS SDK)
entry: bash -c 'cd js && bun run lint'
language: system
files: ^js/
types_or: [javascript, ts, tsx, jsx]
pass_filenames: false
priority: 10
- id: typecheck-js
name: TypeScript (JS SDK)
entry: bash -c 'cd js && bun run type-check'
language: system
files: ^js/
types_or: [javascript, ts, tsx, jsx]
pass_filenames: false
priority: 20
- id: test-js
name: JS SDK tests
entry: bash -c 'cd js && bun run test'
language: system
files: ^js/
types_or: [javascript, ts, tsx, jsx]
pass_filenames: false
require_serial: true
priority: 30

# ── CLI (cli/) ──────────────────────────────────────────────────────
# Mirrors release-npm.yml: lint → type-check → test. CLI consumes
# @phala/cloud via workspace link to js/dist, so a stale js/dist can
# mask real issues; rebuild js before committing if you've changed it.
- id: biome-cli
name: Biome (CLI)
entry: bash -c 'cd cli && bun run lint'
language: system
files: ^cli/
types_or: [javascript, ts, tsx, jsx]
pass_filenames: false
priority: 10
- id: typecheck-cli
name: TypeScript (CLI)
entry: bash -c 'cd cli && bun run type-check'
language: system
files: ^cli/
types_or: [javascript, ts, tsx, jsx]
pass_filenames: false
priority: 20
- id: test-cli
name: CLI tests
entry: bash -c 'cd cli && bun run test'
language: system
files: ^cli/
types_or: [javascript, ts, tsx, jsx]
pass_filenames: false
require_serial: true
priority: 30
43 changes: 43 additions & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,46 @@
## [1.1.16](https://github.com/Phala-Network/phala-cloud/compare/cli-v1.1.15...cli-v1.1.16) (2026-04-10)

### fix

* **cli:** correct deploy --commit requirements in --help ([157f103](https://github.com/Phala-Network/phala-cloud/commit/157f103bb4033cc49abdacc6541d28db15b8a82b))

### refactor

* clarify --help strings and unify --transaction-hash option ([0749dc0](https://github.com/Phala-Network/phala-cloud/commit/0749dc0bc193697ef44d1ac86069d689838b9f58))
## [1.1.15](https://github.com/Phala-Network/phala-cloud/compare/cli-v1.1.14...cli-v1.1.15) (2026-04-10)

### feat

* **cli:** add profiles command aliases (list, rm, mv) ([b46dbc7](https://github.com/Phala-Network/phala-cloud/commit/b46dbc7c46ef30e5829edaee1e72ddaec9041b2b))
* **cli:** add profiles use, rename, delete subcommands ([3a7ab22](https://github.com/Phala-Network/phala-cloud/commit/3a7ab22e5635aa4906cf0e22d41d07141ffdea86))
* **cli:** add renameProfile utility to credentials ([1e07a24](https://github.com/Phala-Network/phala-cloud/commit/1e07a24f847d86b7c5c08050f4d91a7bc447e5fe))
* **cli:** unify global option handling ([8dc77c1](https://github.com/Phala-Network/phala-cloud/commit/8dc77c19c5ddd241e4baeb568981563f670b857f))

### fix

* **cli:** add two-phase replicate flow with on-chain approval ([a77a011](https://github.com/Phala-Network/phala-cloud/commit/a77a011e47e34129c3a5b17c9adcd7f60ee3bec8))
* **cli:** improve replicate output formatting and error display ([87cd7c8](https://github.com/Phala-Network/phala-cloud/commit/87cd7c8bff9c963219da4f03201f26ca2b57e966))
* **cli:** resolve app_id ambiguity with --compose-hash in replicate ([15ff65d](https://github.com/Phala-Network/phala-cloud/commit/15ff65d20a86702c519df63df4b86989832152f1))
* **cli:** show full values in on-chain registration error ([600cb66](https://github.com/Phala-Network/phala-cloud/commit/600cb66b9c8732a9e89fe296fc01d117a6d3f012))
* **cli:** show on-chain status before requiring private key in replicate ([986f1ac](https://github.com/Phala-Network/phala-cloud/commit/986f1acd6b925e452a0608c8fc91717822363d0f))
* **cli:** strip app_ prefix when matching cvm list by app_id ([fcfed6e](https://github.com/Phala-Network/phala-cloud/commit/fcfed6e7dab1a609ff09e52c2a1448ea1c3f4fc4))
* **cli:** support universal cvm ids for replicate ([5fa84ba](https://github.com/Phala-Network/phala-cloud/commit/5fa84ba486cb3329e6b222bbc8a4edf03e1a41a3))
* **cli:** use app CVMs endpoint for compose-hash disambiguation ([2f2266a](https://github.com/Phala-Network/phala-cloud/commit/2f2266a7ab0ffb93c94d458298ec5082111e402c))
* **cli:** use correct pubkey source for CVM replicate env encryption ([2b3b98b](https://github.com/Phala-Network/phala-cloud/commit/2b3b98b9fdcd369f94887a05cea1827978cddeb1))
* **cli:** use instance-level cvm replication ([fd0cb03](https://github.com/Phala-Network/phala-cloud/commit/fd0cb0352c35987606d1efe901fb6a6b305b6319))
* **cli:** use plaintext output for cvm replicate ([1a9ba68](https://github.com/Phala-Network/phala-cloud/commit/1a9ba688895a3334cae4a69defc3f4d429062841))
* **cli:** use sdk private key flow in allow-devices ([d697761](https://github.com/Phala-Network/phala-cloud/commit/d697761a30a7b19cbbefff61ed0b74d82ae94ae4))
* **sdk:** chain resolution, owner pre-check, and ABI error definitions ([0c6a50c](https://github.com/Phala-Network/phala-cloud/commit/0c6a50c7fc57370ecb61359f34f04210c645ca18))

### refactor

* add `phala help <topic>` subcommand with bundled topics ([8880334](https://github.com/Phala-Network/phala-cloud/commit/88803342ad4a5506642d3d517be55361659b1b0e))
* add RPC timeout + retry hint for allow-devices ([7a20577](https://github.com/Phala-Network/phala-cloud/commit/7a20577545e3da42bd37017574db962f5fc953f6))
* add transaction progress logging and RPC transport timeouts ([29849a2](https://github.com/Phala-Network/phala-cloud/commit/29849a283025fe74543254e75afae888ab29f848))
* allow direct app identifier in allow-devices to avoid CVM ambiguity ([a440bed](https://github.com/Phala-Network/phala-cloud/commit/a440bedb6334c87ed3b2bf82a6813421ee5204a4))
* log RPC URL before blockchain operations ([c9956b2](https://github.com/Phala-Network/phala-cloud/commit/c9956b22b0fe1c7a66b13f9b7bc04051600fb1f4))
* skip device list in allow-devices ls when allowAnyDevice is on ([597bbb4](https://github.com/Phala-Network/phala-cloud/commit/597bbb4be1e69d1832093ee167bf69eda801e3e2))
* unify --private-key / --rpc-url and add ETH_RPC_URL fallback ([162ff8a](https://github.com/Phala-Network/phala-cloud/commit/162ff8a0451ca799061534d3eb9711a85aebd1af))
## [1.1.14](https://github.com/Phala-Network/phala-cloud/compare/cli-v1.1.13...cli-v1.1.14) (2026-03-27)

### feat
Expand Down
72 changes: 72 additions & 0 deletions cli/docs/help/topics/envs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Environment Variables

All environment variables recognized by the Phala CLI. Command-line flags always take precedence over environment variables when both are set.

## Authentication

- `PHALA_CLOUD_API_KEY` — API token. Overrides the token stored by `phala login`.
- `PHALA_CLOUD_API_PREFIX` — API base URL. Default: `https://cloud-api.phala.com/api/v1`.

The `@phala/cloud` JS SDK also reads both directly when `createClient()` is
called without explicit config.

## On-chain KMS

These variables apply to `deploy`, `allow-devices`, `cvms replicate`, and
`envs update` when the CVM uses Ethereum or Base KMS:

- `PRIVATE_KEY` — Private key for signing on-chain transactions.
Precedence: `--private-key` > `PRIVATE_KEY`.
- `ETH_RPC_URL` — RPC endpoint. Follows the foundry/cast convention, so an
existing `ETH_RPC_URL` from those tools works automatically.
Precedence: `--rpc-url` > `ETH_RPC_URL` > chain default.

Example:

export ETH_RPC_URL=https://mainnet.base.org
export PRIVATE_KEY=0x...
phala deploy --kms base

## Debug logging

`DEBUG` has two independent consumers that behave differently:

- **CLI debug output** — any non-empty value enables the CLI's own debug
messages on stderr (gray prefix).
- **API request logging** — the `@phala/cloud` JS SDK uses the `debug` npm
package with namespace `phala::api-client`. Set `DEBUG=phala::api-client`
to print every HTTP request in cURL-like format (method, URL, headers,
body).

Examples:

# CLI debug only
DEBUG=1 phala deploy

# API request cURL logging (also triggers CLI debug, since "phala::api-client" is truthy)
DEBUG=phala::api-client phala deploy

# Everything
DEBUG=* phala deploy

## Self-update

- `PHALA_UPDATE_CHANNEL` — Release channel for `phala self update` (e.g. `latest`, `beta`).
- `PHALA_DISABLE_UPDATE_CHECK` — Any truthy value disables the background update notice.
- `CI` — Standard CI flag. Any truthy value disables the update notice.

## Miscellaneous

- `CLOUD_URL` — Override the Phala Cloud portal URL used in printed links.
Default: `https://cloud.phala.com`.

## Internal (undocumented)

- `PHALA_CLOUD_DIR` — Override the credentials directory. Default: `~/.phala-cloud`.
Testing only.

## See also

- `phala api --help` for API-specific flags and env vars
- `phala login --help` for authentication flow
- `phala deploy --help` for on-chain KMS flags
5 changes: 3 additions & 2 deletions cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "phala",
"version": "1.1.14",
"version": "1.1.16",
"description": "CLI for Managing Phala Cloud Services",
"author": {
"name": "Phala Network",
Expand All @@ -27,7 +27,8 @@
"pha": "./dist/index.js"
},
"scripts": {
"build": "tsup && bun link",
"build": "bun run gen:help && tsup && bun link",
"gen:help": "bun run scripts/gen-help-topics.ts",
"test": "bun test",
"test:e2e": "bun test test/e2e-full/",
"test:interface": "bun test test/interface-compat/",
Expand Down
112 changes: 112 additions & 0 deletions cli/scripts/gen-help-topics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/usr/bin/env bun
/**
* Generate src/commands/help/topics.generated.ts from docs/help/topics/*.md.
*
* Each .md file becomes one help topic. The topic name is the file basename
* (without extension). The description is the first non-empty, non-heading
* line of the file.
*
* Run: bun run gen:help
*/
import { spawnSync } from "node:child_process";
import { readFileSync, readdirSync, writeFileSync } from "node:fs";
import { dirname, join, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const ROOT = resolve(__dirname, "..");
const TOPICS_DIR = join(ROOT, "docs", "help", "topics");
const OUT_FILE = join(ROOT, "src", "commands", "help", "topics.generated.ts");

interface Topic {
name: string;
description: string;
content: string;
}

function extractDescription(content: string): string {
for (const rawLine of content.split("\n")) {
const line = rawLine.trim();
if (line === "") continue;
if (line.startsWith("#")) continue;
return line;
}
return "";
}

function collectTopics(): Topic[] {
const entries = readdirSync(TOPICS_DIR, { withFileTypes: true });
const topics: Topic[] = [];
for (const entry of entries) {
if (!entry.isFile()) continue;
if (!entry.name.endsWith(".md")) continue;
const name = entry.name.replace(/\.md$/, "");
const content = readFileSync(join(TOPICS_DIR, entry.name), "utf-8");
topics.push({
name,
description: extractDescription(content),
content,
});
}
topics.sort((a, b) => a.name.localeCompare(b.name));
return topics;
}

function serializeString(value: string): string {
// Use JSON.stringify for safe escaping of quotes, backslashes, newlines, etc.
return JSON.stringify(value);
}

function render(topics: Topic[]): string {
const header = [
"// AUTO-GENERATED by scripts/gen-help-topics.ts — do not edit manually.",
"// Run `bun run gen:help` to regenerate after editing docs/help/topics/*.md.",
"",
"export interface HelpTopic {",
"\treadonly name: string;",
"\treadonly description: string;",
"\treadonly content: string;",
"}",
"",
"export const helpTopics: Readonly<Record<string, HelpTopic>> = Object.freeze({",
];
const body: string[] = [];
for (const topic of topics) {
body.push(`\t${JSON.stringify(topic.name)}: Object.freeze({`);
body.push(`\t\tname: ${serializeString(topic.name)},`);
body.push(`\t\tdescription: ${serializeString(topic.description)},`);
body.push(`\t\tcontent: ${serializeString(topic.content)},`);
body.push("\t}),");
}
const footer = ["});", ""];
return [...header, ...body, ...footer].join("\n");
}

function formatWithBiome(file: string): void {
// Run biome on just this file so the generated output matches the
// project's formatting rules and `bun run fmt` stays idempotent.
const result = spawnSync(
"bunx",
["biome", "format", "--write", relative(ROOT, file)],
{
cwd: ROOT,
stdio: "inherit",
},
);
if (result.status !== 0) {
process.exit(result.status ?? 1);
}
}

function main(): void {
const topics = collectTopics();
const output = render(topics);
writeFileSync(OUT_FILE, output, "utf-8");
formatWithBiome(OUT_FILE);
console.log(
`Generated ${OUT_FILE} (${topics.length} topic${topics.length === 1 ? "" : "s"})`,
);
}

main();
Loading