Top Level Namespace
Defined Under Namespace
Modules: Wokku
Constant Summary collapse
- CONFIG_DIR =
Wokku::Config::DEFAULT_DIR
- CONFIG_FILE =
File.join(CONFIG_DIR, "config.json")
- VERSION =
Wokku::VERSION
- MCP_SERVER_NAME =
Wokku MCP commands — install / switch / logout the Wokku MCP server in Claude Code so the user’s CLI token gets passed to the plugin. Shells out to ‘claude mcp` (Claude Code CLI) so we don’t need to know Claude Code’s exact config-file layout — it changes between versions.
"wokku"- DEFAULT_API_URL =
"https://wokku.cloud/api/v1"- FRPC_VERSION =
— wokku tunnel: share a local port at https://<sub>.wokku.dev —
Path B per project_wokku_tunnel_path_decision (memory): frp gateway. Wraps a downloaded ‘frpc` (one-time bootstrap, no platform-specific gem dependency). User runs `wokku tunnel 3000`; we POST to the API to provision a TunnelSession, write a per-process frpc.toml, exec frpc, and DELETE the session on exit.
"0.62.1"
Instance Method Summary collapse
-
#api(method, path, body = nil) ⇒ Object
Top-level helper shims used by command blocks (preserved for compatibility with the existing register-DSL pattern).
- #api_token ⇒ Object
- #api_url ⇒ Object
- #claude_cli_available? ⇒ Boolean
-
#find_domain(app_id, hostname) ⇒ Object
Look up a domain row by hostname so users can pass the name they know rather than an internal id.
- #install_mcp_entry! ⇒ Object
- #load_config ⇒ Object
-
#print_cdn_state(enabled, note: nil) ⇒ Object
— Cloudflare CDN proxy toggle —.
-
#print_https_state(enabled) ⇒ Object
— HTTPS redirect toggle —.
-
#print_maintenance_state(enabled) ⇒ Object
— Maintenance mode toggle —.
- #puts_json(data) ⇒ Object
- #register(name, desc, &block) ⇒ Object
- #require_claude_cli! ⇒ Object
- #require_logged_in! ⇒ Object
-
#resolve_server(explicit: nil) ⇒ Object
Resolve which server to target for a deploy/create.
- #save_config(data) ⇒ Object
- #table(rows, headers: nil) ⇒ Object
- #tunnel_ensure_frpc! ⇒ Object
- #tunnel_frpc_arch ⇒ Object
- #tunnel_frpc_path ⇒ Object
- #tunnel_frpc_platform ⇒ Object
Instance Method Details
#api(method, path, body = nil) ⇒ Object
Top-level helper shims used by command blocks (preserved for compatibility with the existing register-DSL pattern).
76 77 78 79 80 81 |
# File 'lib/wokku.rb', line 76 def api(method, path, body = nil) Wokku.api_client.request(method, path, body) rescue Wokku::ApiClient::NotAuthenticated, Wokku::ApiClient::Timeout, Wokku::ApiClient::Unreachable, Wokku::ApiClient::Error => e abort e. end |
#claude_cli_available? ⇒ Boolean
10 11 12 |
# File 'lib/wokku/commands/mcp.rb', line 10 def claude_cli_available? system("command -v claude >/dev/null 2>&1") end |
#find_domain(app_id, hostname) ⇒ Object
Look up a domain row by hostname so users can pass the name they know rather than an internal id. Returns nil when not found or when the API returns a non-array (error envelope).
10 11 12 13 14 |
# File 'lib/wokku/helpers.rb', line 10 def find_domain(app_id, hostname) list = api(:get, "/apps/#{app_id}/domains") return nil unless list.is_a?(Array) list.find { |d| d["hostname"] == hostname } end |
#install_mcp_entry! ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/wokku/commands/mcp.rb', line 29 def install_mcp_entry! url = Wokku::Config.api_url token = Wokku::Config.api_token # Idempotent — silently no-ops if the entry doesn't exist yet. system("claude mcp remove #{Shellwords.escape(MCP_SERVER_NAME)} > /dev/null 2>&1") ok = system( "claude", "mcp", "add", MCP_SERVER_NAME, "--env", "WOKKU_API_URL=#{url}", "--env", "WOKKU_API_TOKEN=#{token}", "--", "npx", "-y", "@johannesdwicahyo/wokku-plugin" ) ok or abort "claude mcp add failed — check `claude mcp list` and retry." end |
#print_cdn_state(enabled, note: nil) ⇒ Object
— Cloudflare CDN proxy toggle —
5 6 7 8 |
# File 'lib/wokku/commands/cdn.rb', line 5 def print_cdn_state(enabled, note: nil) Wokku::Output.status "cdn: #{enabled ? 'on' : 'off'}" warn note if note end |
#print_https_state(enabled) ⇒ Object
— HTTPS redirect toggle —
5 6 7 |
# File 'lib/wokku/commands/https.rb', line 5 def print_https_state(enabled) Wokku::Output.status "https redirect: #{enabled ? 'on' : 'off'}" end |
#print_maintenance_state(enabled) ⇒ Object
— Maintenance mode toggle —
5 6 7 |
# File 'lib/wokku/commands/maintenance.rb', line 5 def print_maintenance_state(enabled) Wokku::Output.status "maintenance: #{enabled ? 'on' : 'off'}" end |
#puts_json(data) ⇒ Object
88 |
# File 'lib/wokku.rb', line 88 def puts_json(data) = Wokku::Output.puts_json(data) |
#register(name, desc, &block) ⇒ Object
89 |
# File 'lib/wokku.rb', line 89 def register(name, desc, &block) = Wokku::Registry.register(name, desc, &block) |
#require_claude_cli! ⇒ Object
14 15 16 17 18 19 20 21 22 |
# File 'lib/wokku/commands/mcp.rb', line 14 def require_claude_cli! return if claude_cli_available? abort <<~MSG The `claude` CLI is not installed. Wokku MCP commands shell out to it to write your Claude Code config. Install Claude Code (https://claude.com/claude-code) and retry. MSG end |
#require_logged_in! ⇒ Object
24 25 26 27 |
# File 'lib/wokku/commands/mcp.rb', line 24 def require_logged_in! return if Wokku::Config.api_token abort "Not logged in. Run: wokku auth:login" end |
#resolve_server(explicit: nil) ⇒ Object
Resolve which server to target for a deploy/create. Walks the precedence chain: explicit flag → env → config → auto-pick if only one server → abort with helpful error. Returns the server name or UUID (whatever was explicitly passed/configured).
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/wokku/helpers.rb', line 20 def resolve_server(explicit: nil) return explicit if explicit env = ENV["WOKKU_DEFAULT_SERVER"] return env if env && !env.empty? cfg_default = Wokku::Config.load["default_server"] return cfg_default if cfg_default servers = api(:get, "/servers") unless servers.is_a?(Array) abort "Unexpected response from /servers: #{servers.inspect[0..200]}" end abort "No servers available. Contact wokku.cloud support." if servers.empty? return servers.first["name"] if servers.size == 1 names = servers.map { |s| s["name"] }.join(", ") abort "Multiple servers available (#{names}). Pass --server NAME or set a default: wokku servers:default NAME" end |
#save_config(data) ⇒ Object
84 |
# File 'lib/wokku.rb', line 84 def save_config(data) = Wokku::Config.save(data) |
#table(rows, headers: nil) ⇒ Object
87 |
# File 'lib/wokku.rb', line 87 def table(rows, headers: nil) = Wokku::Output.table(rows, headers: headers) |
#tunnel_ensure_frpc! ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/wokku/commands/tunnel.rb', line 39 def tunnel_ensure_frpc! return tunnel_frpc_path if File.executable?(tunnel_frpc_path) warn "→ fetching tunnel helper (frpc #{FRPC_VERSION}, ~10 MB, one time)…" platform = tunnel_frpc_platform archive = "frp_#{FRPC_VERSION}_#{platform}.tar.gz" url = "https://github.com/fatedier/frp/releases/download/v#{FRPC_VERSION}/#{archive}" ext = platform.start_with?("windows") ? ".zip" : ".tar.gz" archive = archive.sub(/\.tar\.gz\z/, ext) url = url.sub(/\.tar\.gz\z/, ext) Dir.mktmpdir do |tmp| archive_path = File.join(tmp, archive) unless system("curl", "-fL", url, "-o", archive_path) abort "Failed to download frpc from #{url}" end if ext == ".zip" system("unzip", "-q", archive_path, "-d", tmp) || abort("unzip failed") else system("tar", "-C", tmp, "-xzf", archive_path) || abort("tar failed") end frpc_dir = Dir[File.join(tmp, "frp_#{FRPC_VERSION}_*")].first || abort("frpc not found in archive") src = File.join(frpc_dir, platform.start_with?("windows") ? "frpc.exe" : "frpc") FileUtils.mkdir_p(File.dirname(tunnel_frpc_path)) FileUtils.cp(src, tunnel_frpc_path) File.chmod(0o755, tunnel_frpc_path) end tunnel_frpc_path end |
#tunnel_frpc_arch ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/wokku/commands/tunnel.rb', line 31 def tunnel_frpc_arch case RbConfig::CONFIG["host_cpu"] when /arm64|aarch64/ then "arm64" when /x86_64|amd64/ then "amd64" else abort "Unsupported CPU: #{RbConfig::CONFIG['host_cpu']}" end end |
#tunnel_frpc_path ⇒ Object
18 19 20 |
# File 'lib/wokku/commands/tunnel.rb', line 18 def tunnel_frpc_path File.join(Dir.home, ".wokku", "bin", "frpc") end |
#tunnel_frpc_platform ⇒ Object
22 23 24 25 26 27 28 29 |
# File 'lib/wokku/commands/tunnel.rb', line 22 def tunnel_frpc_platform case RbConfig::CONFIG["host_os"] when /darwin/ then "darwin_#{tunnel_frpc_arch}" when /linux/ then "linux_#{tunnel_frpc_arch}" when /mswin|mingw|cygwin/ then "windows_amd64" else abort "Unsupported OS: #{RbConfig::CONFIG['host_os']}" end end |