diff --git a/docs/platforms/android-client.md b/docs/platforms/android-client.md index 84f2a59..c2f8322 100644 --- a/docs/platforms/android-client.md +++ b/docs/platforms/android-client.md @@ -1,5 +1,7 @@ # Android CLI 客户端 +推荐把 Android CLI 作为 Termux DEB 分发,而不是把 CLI 当成普通 Android APK。APK 只是可选的 One UI 启动器:它不能单独运行 CLI,必须与 Termux、Termux DEB、运行命令权限和 `allow-external-apps=true` 配置一起使用。直接安装 APK 后点击图标不能替代 Termux 环境,也不会自动安装 .NET 或 `charac`。 + Android 首期支持 ARM64 设备上的 Termux 终端,CLI 使用 `linux-bionic-arm64` RID。另有独立的 .NET Android 启动器项目 `src/android/CharacAndroid.csproj`,包 ID 为 `com.nitload.charac`;Server 仍只部署在 Windows 或 Linux。 执行 `./build.ps1 --target Publish --runtime linux-bionic-arm64 --locked-restore`,或在 Linux 上使用 `bash ./build.sh`。随后运行 `./packaging/package.ps1 -Target ClientTermuxDeb`,生成 `artifacts/packages/charac_0.1.0-1_aarch64.deb`。该包面向标准包名 `com.termux` 的 apt 版 aarch64 Termux,将 Client 安装到 `$PREFIX/opt/charac`,将 `charac` 入口装到 `$PREFIX/bin`,并依赖 Termux 的 `dotnet-runtime-10.0`。在 Termux 中复制 DEB 后运行 `apt install ./charac_0.1.0-1_aarch64.deb`;当前尚未发布到 Termux 仓库,因此 `pkg install charac` 还不能从公共仓库下载它。APK 的环境检查会识别包提供的固定入口。 diff --git a/docs/platforms/deployment.md b/docs/platforms/deployment.md index f9f606b..11e84fa 100644 --- a/docs/platforms/deployment.md +++ b/docs/platforms/deployment.md @@ -39,4 +39,4 @@ Server 运行时只需 `--config /etc/charac/workspace-access.config`。这一 Client RPM 安装自包含程序到 `/opt/charac/client`,并提供 `/usr/bin/charac` 命令。Windows MSI 安装到 `Program Files\nitload\Charac Client`,把安装目录加入系统 `PATH`;新终端可运行 `charac.exe --help`。MSI 内嵌所需文件,不依赖独立 CAB。两个 Client 包均不预置登录令牌或目标配置。 RPM 尚需在目标 Fedora/RHEL 机器进行实际安装、升级、卸载和 systemd 验收;Termux DEB 尚需在真实 Android/Termux 设备上安装、启动和登录验收;MSI 尚需在正常启用 Windows Installer 服务的 Windows 机器进行安装、升级、卸载验收。当前构建环境完成了 RPM 生成及文件头检查、Termux DEB 控制字段和文件路径检查、MSI 生成及文件表反编译检查;受限环境里的 ICE 校验无法连接 Windows Installer 服务。 -Client 可在用户级 INI 的 `[client] server` 写入默认 HTTPS origin,样例见仓库根目录 `client.config.example`;Client RPM 另安装到 `/usr/share/doc/charac-client/client.config.example`,MSI 则安装到程序目录。Windows 默认读取 `%APPDATA%\Charac\client.config`;Linux/Termux 默认读取 `$XDG_CONFIG_HOME/charac/client.config`,未设置时读取 `~/.config/charac/client.config`。之后直接执行 `charac connect`(Windows 为 `charac.exe connect`);`--server ` 可临时覆盖,`--config <路径>` 可在命令前选用其他配置。该文件只存入口地址,不存 OIDC 令牌;旧版 `%APPDATA%\CharRAC`、`~/.config/char-rac` 配置在新位置不存在时仍会自动读取。Client 安装级设备凭据仍独立存于用户本地应用数据目录,不能复制到多台设备共用。 +Client 可在用户级 INI 的 `[client] server` 写入默认 HTTPS origin,样例见仓库根目录 `client.config.example`;Client RPM 另安装到 `/usr/share/doc/charac-client/client.config.example`,MSI 则安装到程序目录。Windows 默认读取 `%APPDATA%\Charac\client.config`;Linux/Termux 默认读取 `$XDG_CONFIG_HOME/charac/client.config`,未设置时读取 `~/.config/charac/client.config`。首次执行无配置的 Client 命令会自动创建默认配置目录,但不会写入服务器地址。之后可直接执行 `charac connect`(Windows 为 `charac.exe connect`),或使用更短的 `charac connect https://access.example.com`;`--server ` 可临时覆盖,`--config <路径>` 可在命令前选用其他配置。该文件只存入口地址,不存 OIDC 令牌;旧版 `%APPDATA%\CharRAC`、`~/.config/char-rac` 配置在新位置不存在时仍会自动读取。Client 安装级设备凭据仍独立存于用户本地应用数据目录,不能复制到多台设备共用。 diff --git a/src/client/ClientConfiguration.cs b/src/client/ClientConfiguration.cs index f164ec0..277b93c 100644 --- a/src/client/ClientConfiguration.cs +++ b/src/client/ClientConfiguration.cs @@ -40,10 +40,19 @@ internal static class ClientConfiguration } public static string LoadServer(string? path = null) { - path = path is null ? (File.Exists(DefaultPath) ? DefaultPath : - File.Exists(LegacyPath) ? LegacyPath : DefaultPath) : Path.GetFullPath(path); + if (path is null) + { + path = File.Exists(DefaultPath) ? DefaultPath : + File.Exists(LegacyPath) ? LegacyPath : DefaultPath; + if (path == DefaultPath) + Directory.CreateDirectory(Path.GetDirectoryName(path)!); + } + else + { + path = Path.GetFullPath(path); + } if (!File.Exists(path)) - throw new InvalidOperationException($"Client configuration not found: {path}. Create [client] server=https://your-server or pass --server."); + throw new InvalidOperationException($"Client configuration not found: {path}. The parent directory has been created; add [client] server=https://your-server or pass --server."); string? section = null; string? server = null; diff --git a/src/client/Program.cs b/src/client/Program.cs index ff75e3a..4d6e432 100644 --- a/src/client/Program.cs +++ b/src/client/Program.cs @@ -14,6 +14,17 @@ internal static class Program configPath = args[1]; args = args[2..]; } + if (args.Length >= 2 && + args[0] is "status" or "login" or "whoami" or "connect" or "run" or "attach" && + !args.Contains("--server", StringComparer.Ordinal) && + !args[1].StartsWith("--", StringComparison.Ordinal)) + { + var candidate = args[1].Contains("://", StringComparison.Ordinal) + ? args[1] + : "https://" + args[1]; + if (TryGetServerUri(candidate, out _)) + args = [args[0], "--server", candidate, .. args[2..]]; + } if (args.Length == 0 || args is ["--help"] or ["-h"]) { PrintUsage();