diff --git a/cli/cfg b/cli/cfg deleted file mode 100755 index 968b4dd..0000000 --- a/cli/cfg +++ /dev/null @@ -1,166 +0,0 @@ -#!/usr/bin/env python3 -"""cfg — CLI client for the config service. - -Usage: - cfg get Read a key (personal > shared) - cfg set Write to personal scope - cfg set --shared Write to shared scope (admin) - cfg list [--scope shared|personal] List keys - cfg sync Sync all to local cache - cfg delete [--shared] Delete a key - cfg token Save auth token - -Config: ~/.config/cfg/config.json -Cache: ~/.config/cfg/cache.json -""" - -import json -import os -import sys -import urllib.request -import urllib.error -from pathlib import Path - -CONFIG_DIR = Path.home() / ".config" / "cfg" -CONFIG_FILE = CONFIG_DIR / "config.json" -CACHE_FILE = CONFIG_DIR / "cache.json" - -DEFAULT_ENDPOINT = "https://config-service.oc-fleet.workers.dev" - - -def load_config() -> dict: - if CONFIG_FILE.exists(): - return json.loads(CONFIG_FILE.read_text()) - return {} - - -def save_config(cfg: dict): - CONFIG_DIR.mkdir(parents=True, exist_ok=True) - CONFIG_FILE.write_text(json.dumps(cfg, indent=2)) - - -def get_token() -> str: - cfg = load_config() - token = cfg.get("token") or os.environ.get("CFG_TOKEN") - if not token: - print("No token configured. Run: cfg token ", file=sys.stderr) - sys.exit(1) - return token - - -def get_endpoint() -> str: - cfg = load_config() - return cfg.get("endpoint", DEFAULT_ENDPOINT) - - -def api(method: str, path: str, body: dict | None = None) -> dict: - url = f"{get_endpoint()}{path}" - data = json.dumps(body).encode() if body else None - req = urllib.request.Request(url, data=data, method=method) - req.add_header("Authorization", f"Bearer {get_token()}") - req.add_header("Content-Type", "application/json") - try: - with urllib.request.urlopen(req) as resp: - return json.loads(resp.read()) - except urllib.error.HTTPError as e: - result = json.loads(e.read()) - print(f"Error: {result.get('error', 'unknown')}", file=sys.stderr) - sys.exit(1) - - -def cmd_get(args: list[str]): - if not args: - print("Usage: cfg get ", file=sys.stderr) - sys.exit(1) - result = api("GET", f"/config/{args[0]}") - print(result["value"]) - - -def cmd_set(args: list[str]): - shared = "--shared" in args - args = [a for a in args if a != "--shared"] - if len(args) < 2: - print("Usage: cfg set [--shared] ", file=sys.stderr) - sys.exit(1) - key, value = args[0], args[1] - scope = "shared" if shared else "personal" - api("PUT", f"/config/{key}?scope={scope}", {"value": value}) - print(f"✓ Set {key} ({scope})") - - -def cmd_delete(args: list[str]): - shared = "--shared" in args - args = [a for a in args if a != "--shared"] - if not args: - print("Usage: cfg delete [--shared]", file=sys.stderr) - sys.exit(1) - scope = "shared" if shared else "personal" - api("DELETE", f"/config/{args[0]}?scope={scope}") - print(f"✓ Deleted {args[0]} ({scope})") - - -def cmd_list(args: list[str]): - scope = None - if "--scope" in args: - idx = args.index("--scope") - if idx + 1 < len(args): - scope = args[idx + 1] - path = "/config" + (f"?scope={scope}" if scope else "") - result = api("GET", path) - if "keys" in result: - for k in sorted(result["keys"]): - print(f" {k}") - elif "secrets" in result: - for k, v in sorted(result["secrets"].items()): - print(f" {k:<40} ({v['scope']})") - - -def cmd_sync(args: list[str]): - result = api("POST", "/config/sync") - # Save to cache - CONFIG_DIR.mkdir(parents=True, exist_ok=True) - cache = { - "secrets": {k: {"value": v["value"], "updatedAt": v["updated_at"]} for k, v in result["secrets"].items()}, - "lastSync": result.get("agent_id", ""), - } - CACHE_FILE.write_text(json.dumps(cache, indent=2)) - print(f"✓ Synced {len(result['secrets'])} keys") - - -def cmd_token(args: list[str]): - if not args: - print("Usage: cfg token ", file=sys.stderr) - sys.exit(1) - cfg = load_config() - cfg["token"] = args[0] - save_config(cfg) - print("✓ Token saved") - - -def main(): - if len(sys.argv) < 2: - print(__doc__) - sys.exit(0) - - cmd = sys.argv[1] - args = sys.argv[2:] - - commands = { - "get": cmd_get, - "set": cmd_set, - "delete": cmd_delete, - "list": cmd_list, - "sync": cmd_sync, - "token": cmd_token, - } - - if cmd not in commands: - print(f"Unknown command: {cmd}", file=sys.stderr) - print(__doc__) - sys.exit(1) - - commands[cmd](args) - - -if __name__ == "__main__": - main() diff --git a/cli/cfg-node b/cli/cfg.js similarity index 100% rename from cli/cfg-node rename to cli/cfg.js