id = "shadowsocksx-ng" name = "ShadowsocksX-NG" homepage = "https://github.com/shadowsocks/ShadowsocksX-NG/" # The project's own repository description, which is also the first line of # its README: it runs ss-local as a launch agent behind a macOS GUI. description = "Next Generation of ShadowsocksX: a Swift GUI over ss-local, run as a launch agent." # The app icon from the asset catalogue in the project's own repository. icon = "https://raw.githubusercontent.com/shadowsocks/ShadowsocksX-NG/master/ShadowsocksX-NG/Assets.xcassets/AppIcon.appiconset/Icon_256x256.png" # No command-line tool ships with the app, so `detect` carries the bundle # identifier. The Homebrew cask names it in `uninstall quit:` — # com.qiuyuzhou.ShadowsocksX-NG (Casks/s/shadowsocksx-ng.rb) — and the same # identifier prefixes the launch agents the app installs # (com.qiuyuzhou.shadowsocksX-NG.local and friends, from # ShadowsocksX-NG/LaunchAgentUtils.swift). executables = [] platforms = ["macos"] [installation] macos_bundle_ids = ["com.qiuyuzhou.ShadowsocksX-NG"] [dotfiles] # One file here is the user's own configuration and everything else the app # writes is either generated or a credential. # # ShadowsocksX-NG/PACUtils.swift defines the PAC rules directory as # `PACRulesDirPath = NSHomeDirectory() + "/.ShadowsocksX-NG/"` and, inside it, # `PACUserRuleFilePath = PACRulesDirPath + "user-rule.txt"` — the rules the # user edits in the "Edit User Rule for PAC" window (UserRulesController.swift # writes that file and nothing else). The two siblings are not config: # `GFWListFilePath` (gfwlist.txt) is downloaded from `GFWListURL`, and # `PACFilePath` (gfwlist.js) is generated from it on every update. paths = ["~/.ShadowsocksX-NG/user-rule.txt"] # Only the one file is listed, so there is no directory here to carve # generated content out of. exclude = [] # Both of these are credentials end to end, because a Shadowsocks server is # identified by a password. # # ~/Library/Application Support/ShadowsocksX-NG/ss-local-config.json is written # by LaunchAgentUtils.swift (`NSHomeDirectory() + APP_SUPPORT_DIR + # "ss-local-config.json"`, with APP_SUPPORT_DIR = "/Library/Application # Support/ShadowsocksX-NG/") from `ServerProfile.toJsonConfig()`, whose first # key is `conf["password"]`. It is the running proxy's own config file. # # The preferences domain is the server list itself: ServerProfileManager.swift # stores every profile under the "ServerProfiles" user default, and # ServerProfile.toDictionary() puts `d["Password"]` in each one. A property # list cannot be matched field-wise by this schema — `format` covers toml, yaml # and json only — so the whole domain is classified as a credential rather than # synced as content with the passwords inside it. The rest of the domain is # listen addresses, ports and the PAC mode, which a consumer can re-enter. # # [appData] and [preferences] are ~/Library/Application Support and # ~/Library/Preferences; the entry is macOS-only, so there is no other platform # for those roots to stand for. secret = [ "[appData]/ShadowsocksX-NG/ss-local-config.json", "[preferences]/com.qiuyuzhou.ShadowsocksX-NG.plist", ] # No machine_lines: user-rule.txt is a list of domains the user wants proxied, # which is the whole reason to carry it.