{"id":26591556,"url":"https://github.com/wait4x/wait4x","last_synced_at":"2025-04-06T16:10:04.309Z","repository":{"id":37390582,"uuid":"219046009","full_name":"wait4x/wait4x","owner":"wait4x","description":"Wait4X allows you to wait for a port or a service to enter the requested state.","archived":false,"fork":false,"pushed_at":"2025-03-29T07:55:41.000Z","size":1318,"stargazers_count":565,"open_issues_count":9,"forks_count":28,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-05T05:31:31.835Z","etag":null,"topics":["cli","dns","go","golang","hacktoberfest","http","influxdata","influxdb","linux","mariadb","mongodb","mysql","postgresql","rabbitmq","redis","tcp","tool","wait-for-it","wait4x"],"latest_commit_sha":null,"homepage":"https://wait4x.dev","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wait4x.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["atkrad"]}},"created_at":"2019-11-01T19:01:28.000Z","updated_at":"2025-04-04T07:04:22.000Z","dependencies_parsed_at":"2024-01-14T19:16:49.997Z","dependency_job_id":"840fff2b-4422-40d1-b517-aeb6f4ff8105","html_url":"https://github.com/wait4x/wait4x","commit_stats":{"total_commits":467,"total_committers":8,"mean_commits":58.375,"dds":"0.41970021413276226","last_synced_commit":"84ff1e1daa891b38918902eb20891f3d9d3e2069"},"previous_names":["wait4x/wait4x"],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wait4x%2Fwait4x","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wait4x%2Fwait4x/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wait4x%2Fwait4x/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wait4x%2Fwait4x/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wait4x","download_url":"https://codeload.github.com/wait4x/wait4x/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247509219,"owners_count":20950232,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","dns","go","golang","hacktoberfest","http","influxdata","influxdb","linux","mariadb","mongodb","mysql","postgresql","rabbitmq","redis","tcp","tool","wait-for-it","wait4x"],"created_at":"2025-03-23T14:18:28.162Z","updated_at":"2025-04-06T16:10:04.284Z","avatar_url":"https://github.com/wait4x.png","language":"Go","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"logo.png\" alt=\"Wait4X Logo\" width=\"150\"\u003e\n  \u003ch1\u003eWait4X\u003c/h1\u003e\n  \u003cp\u003eA lightweight tool to wait for services to be ready\u003c/p\u003e\n\n  [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/wait4x/wait4x/ci.yaml?branch=main\u0026style=flat-square)](https://github.com/wait4x/wait4x/actions/workflows/ci.yaml)\n  [![Coverage Status](https://img.shields.io/coverallsCoverage/github/wait4x/wait4x?branch=main\u0026style=flat-square)](https://coveralls.io/github/wait4x/wait4x?branch=main)\n  [![Go Report Card](https://goreportcard.com/badge/wait4x.dev/v3?style=flat-square)](https://goreportcard.com/report/wait4x.dev/v3)\n  [![Docker Pulls](https://img.shields.io/docker/pulls/atkrad/wait4x?logo=docker\u0026style=flat-square)](https://hub.docker.com/r/wait4x/wait4x)\n  [![GitHub Downloads](https://img.shields.io/github/downloads/wait4x/wait4x/total?logo=github\u0026style=flat-square)](https://github.com/wait4x/wait4x/releases)\n  [![Packaging status](https://img.shields.io/repology/repositories/wait4x?style=flat-square)](https://repology.org/project/wait4x/versions)\n  [![Go Reference](https://img.shields.io/badge/reference-007D9C.svg?style=flat-square\u0026logo=go\u0026logoColor=white\u0026labelColor=5C5C5C)](https://pkg.go.dev/wait4x.dev/v3)\n\n\u003c/div\u003e\n\n---\n\n## 📑 Table of Contents\n\n- [📋 Overview](#-overview)\n- [✨ Features](#-features)\n- [📥 Installation](#-installation)\n- [🚀 Quick Start](#-quick-start)\n- [📖 Detailed Usage](#-detailed-usage)\n- [⚙️ Advanced Features](#️-advanced-features)\n- [📦 Go Package Usage](#-go-package-usage)\n- [🤝 Contributing](#-contributing)\n- [📄 License](#-license)\n\n## 📋 Overview\n\n**Wait4X** is a powerful, zero-dependency tool that waits for services to be ready before continuing. It supports multiple protocols and services, making it an essential component for:\n\n- **CI/CD pipelines** - Ensure dependencies are available before tests run\n- **Container orchestration** - Health checking services before application startup\n- **Deployment processes** - Verify system readiness before deploying\n- **Application initialization** - Validate external service availability\n- **Local development** - Simplify localhost service readiness checks\n\n## ✨ Features\n\n| Feature | Description |\n|---------|-------------|\n| **Multi-Protocol Support** | TCP, HTTP, DNS |\n| **Service Integrations** | Redis, MySQL, PostgreSQL, MongoDB, RabbitMQ, InfluxDB, Temporal |\n| **Reverse Checking** | Invert checks to find free ports or non-ready services |\n| **Parallel Checking** | Check multiple services simultaneously |\n| **Exponential Backoff** | Retry with increasing delays to improve reliability |\n| **CI/CD Integration** | Designed for automation workflows |\n| **Cross-Platform** | Single binary for Linux, macOS, and Windows |\n| **Go Package** | Import into your Go applications |\n| **Command Execution** | Run commands after successful checks |\n\n## 📥 Installation\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🐳 With Docker\u003c/b\u003e\u003c/summary\u003e\n\nWait4X provides automatically updated Docker images within Docker Hub:\n\n```bash\n# Pull the image\ndocker pull wait4x/wait4x:latest\n\n# Run the container\ndocker run --rm wait4x/wait4x:latest --help\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e📦 From Binary\u003c/b\u003e\u003c/summary\u003e\n\nDownload the appropriate version for your platform from the [releases page](https://github.com/wait4x/wait4x/releases):\n\n**Linux:**\n```bash\ncurl -LO https://github.com/wait4x/wait4x/releases/latest/download/wait4x-linux-amd64.tar.gz\ntar -xf wait4x-linux-amd64.tar.gz -C /tmp\nsudo mv /tmp/wait4x-linux-amd64/wait4x /usr/local/bin/\n```\n\n**macOS:**\n```bash\ncurl -LO https://github.com/wait4x/wait4x/releases/latest/download/wait4x-darwin-amd64.tar.gz\ntar -xf wait4x-darwin-amd64.tar.gz -C /tmp\nsudo mv /tmp/wait4x-darwin-amd64/wait4x /usr/local/bin/\n```\n\n**Windows:**\n```bash\ncurl -LO https://github.com/wait4x/wait4x/releases/latest/download/wait4x-windows-amd64.tar.gz\ntar -xf wait4x-windows-amd64.tar.gz\n# Move to a directory in your PATH\n```\n\n**Verify checksums:**\n```bash\ncurl -LO https://github.com/wait4x/wait4x/releases/latest/download/wait4x-linux-amd64.tar.gz.sha256sum\nsha256sum --check wait4x-linux-amd64.tar.gz.sha256sum\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e📦 From Package Managers\u003c/b\u003e\u003c/summary\u003e\n\n**Alpine Linux:**\n```bash\napk add wait4x\n```\n\n**Arch Linux (AUR):**\n```bash\nyay -S wait4x-bin\n```\n\n**NixOS:**\n```bash\nnix-env -iA nixpkgs.wait4x\n```\n\n**Windows (Scoop):**\n```bash\nscoop install wait4x\n```\n\n[![Packaging status](https://repology.org/badge/vertical-allrepos/wait4x.svg?exclude_unsupported=1)](https://repology.org/project/wait4x/versions)\n\u003c/details\u003e\n\n## 🚀 Quick Start\n\n### Basic TCP Check\n\nWait for a port to become available:\n\n```bash\nwait4x tcp localhost:3306\n```\n\n### HTTP Health Check\n\nWait for a web server with specific response:\n\n```bash\nwait4x http https://example.com/health --expect-status-code 200 --expect-body-regex '\"status\":\"UP\"'\n```\n\n### Multi-Service Check (Parallel)\n\nWait for multiple services simultaneously:\n\n```bash\nwait4x tcp 127.0.0.1:5432 127.0.0.1:6379 127.0.0.1:27017\n```\n\n### Database Readiness\n\nWait for PostgreSQL to be ready:\n\n```bash\nwait4x postgresql 'postgres://user:pass@localhost:5432/mydb?sslmode=disable'\n```\n\n### Execute After Success\n\nRun a command after services are ready:\n\n```bash\nwait4x tcp localhost:8080 -- echo \"Service is ready!\" \u0026\u0026 ./start-app.sh\n```\n\n## 📖 Detailed Usage\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🌐 HTTP Checking\u003c/b\u003e\u003c/summary\u003e\n\n### Checking with Status Code\n\nWait for an HTTP endpoint to return a specific status code:\n\n```bash\nwait4x http https://api.example.com/health --expect-status-code 200\n```\n\n### Checking Response Body with Regex\n\nWait for an HTTP endpoint to return a response that matches a regex pattern:\n\n```bash\nwait4x http https://api.example.com/status --expect-body-regex '\"status\":\\s*\"healthy\"'\n```\n\n### Checking Response Body with JSON Path\n\nWait for a specific JSON field to exist or have a specific value:\n\n```bash\nwait4x http https://api.example.com/status --expect-body-json \"services.database.status\"\n```\n\nThis uses [GJSON Path Syntax](https://github.com/tidwall/gjson#path-syntax) for powerful JSON querying.\n\n### Checking Response Body with XPath\n\nWait for an HTML/XML response to match an XPath query:\n\n```bash\nwait4x http https://example.com --expect-body-xpath \"//div[@id='status']\"\n```\n\n### Custom Request Headers\n\nSend specific headers with your HTTP request:\n\n```bash\nwait4x http https://api.example.com \\\n  --request-header \"Authorization: Bearer token123\" \\\n  --request-header \"Content-Type: application/json\"\n```\n\n### Checking Response Headers\n\nWait for a response header to match a pattern:\n\n```bash\nwait4x http https://api.example.com --expect-header \"Content-Type=application/json\"\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🔍 DNS Checking\u003c/b\u003e\u003c/summary\u003e\n\n### Check A Records\n\n```bash\n# Basic existence check\nwait4x dns A example.com\n\n# With expected IP\nwait4x dns A example.com --expected-ip 93.184.216.34\n\n# Using specific nameserver\nwait4x dns A example.com --expected-ip 93.184.216.34 -n 8.8.8.8\n```\n\n### Check AAAA Records (IPv6)\n\n```bash\nwait4x dns AAAA example.com --expected-ip \"2606:2800:220:1:248:1893:25c8:1946\"\n```\n\n### Check CNAME Records\n\n```bash\nwait4x dns CNAME www.example.com --expected-domain example.com\n```\n\n### Check MX Records\n\n```bash\nwait4x dns MX example.com --expected-domain \"mail.example.com\"\n```\n\n### Check NS Records\n\n```bash\nwait4x dns NS example.com --expected-nameserver \"ns1.example.com\"\n```\n\n### Check TXT Records\n\n```bash\nwait4x dns TXT example.com --expected-value \"v=spf1 include:_spf.example.com ~all\"\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e💾 Database Checking\u003c/b\u003e\u003c/summary\u003e\n\n### MySQL\n\n```bash\n# TCP connection\nwait4x mysql 'user:password@tcp(localhost:3306)/mydb'\n\n# Unix socket\nwait4x mysql 'user:password@unix(/var/run/mysqld/mysqld.sock)/mydb'\n```\n\n### PostgreSQL\n\n```bash\n# TCP connection\nwait4x postgresql 'postgres://user:password@localhost:5432/mydb?sslmode=disable'\n\n# Unix socket\nwait4x postgresql 'postgres://user:password@/mydb?host=/var/run/postgresql'\n```\n\n### MongoDB\n\n```bash\nwait4x mongodb 'mongodb://user:password@localhost:27017/mydb?maxPoolSize=20'\n```\n\n### Redis\n\n```bash\n# Basic connection\nwait4x redis redis://localhost:6379\n\n# With authentication and database selection\nwait4x redis redis://user:password@localhost:6379/0\n\n# Check for key existence\nwait4x redis redis://localhost:6379 --expect-key \"session:active\"\n\n# Check for key with specific value (regex)\nwait4x redis redis://localhost:6379 --expect-key \"status=^ready$\"\n```\n\n### InfluxDB\n\n```bash\nwait4x influxdb http://localhost:8086\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🚌 Message Queue Checking\u003c/b\u003e\u003c/summary\u003e\n\n### RabbitMQ\n\n```bash\nwait4x rabbitmq 'amqp://guest:guest@localhost:5672/myvhost'\n```\n\n### Temporal\n\n```bash\n# Server check\nwait4x temporal server localhost:7233\n\n# Worker check (with namespace and task queue)\nwait4x temporal worker localhost:7233 \\\n  --namespace my-namespace \\\n  --task-queue my-queue\n\n# Check for specific worker identity\nwait4x temporal worker localhost:7233 \\\n  --namespace my-namespace \\\n  --task-queue my-queue \\\n  --expect-worker-identity-regex \"worker-.*\"\n```\n\u003c/details\u003e\n\n## ⚙️ Advanced Features\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e⏱️ Timeout \u0026 Retry Control\u003c/b\u003e\u003c/summary\u003e\n\n### Setting Timeout\n\nLimit the total time Wait4X will wait:\n\n```bash\nwait4x tcp localhost:8080 --timeout 30s\n```\n\n### Setting Interval\n\nControl how frequently Wait4X retries:\n\n```bash\nwait4x tcp localhost:8080 --interval 2s\n```\n\n### Exponential Backoff\n\nUse exponential backoff for more efficient retries:\n\n```bash\nwait4x http https://api.example.com \\\n  --backoff-policy exponential \\\n  --backoff-exponential-coefficient 2.0 \\\n  --backoff-exponential-max-interval 30s\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e↔️ Reverse Checking\u003c/b\u003e\u003c/summary\u003e\n\nWait for a port to become free:\n\n```bash\nwait4x tcp localhost:8080 --invert-check\n```\n\nWait for a service to stop:\n\n```bash\nwait4x http https://service.local/health --expect-status-code 200 --invert-check\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e⚡ Command Execution\u003c/b\u003e\u003c/summary\u003e\n\nExecute commands after successful wait:\n\n```bash\nwait4x tcp localhost:3306 -- ./deploy.sh\n```\n\nChain multiple commands:\n\n```bash\nwait4x redis redis://localhost:6379 -- echo \"Redis is ready\" \u0026\u0026 ./init-redis.sh\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🔄 Parallel Checking\u003c/b\u003e\u003c/summary\u003e\n\nWait for multiple services simultaneously:\n\n```bash\nwait4x tcp localhost:3306 localhost:6379 localhost:27017\n```\n\nNote that this waits for ALL specified services to be ready.\n\u003c/details\u003e\n\n## 📦 Go Package Usage\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🔌 Installing as a Go Package\u003c/b\u003e\u003c/summary\u003e\n\nAdd Wait4X to your Go project:\n\n```bash\ngo get wait4x.dev/v3\n```\n\nImport the packages you need:\n\n```go\nimport (\n    \"context\"\n    \"time\"\n\n    \"wait4x.dev/v3/checker/tcp\"      // TCP checker\n    \"wait4x.dev/v3/checker/http\"     // HTTP checker\n    \"wait4x.dev/v3/checker/redis\"    // Redis checker\n    \"wait4x.dev/v3/waiter\"           // Waiter functionality\n)\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🌟 Example: TCP Checking\u003c/b\u003e\u003c/summary\u003e\n\n```go\n// Create a context with timeout\nctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\ndefer cancel()\n\n// Create a TCP checker\ntcpChecker := tcp.New(\"localhost:6379\", tcp.WithTimeout(5*time.Second))\n\n// Wait for the TCP port to be available\nerr := waiter.WaitContext(\n    ctx,\n    tcpChecker,\n    waiter.WithTimeout(time.Minute),\n    waiter.WithInterval(2*time.Second),\n    waiter.WithBackoffPolicy(\"exponential\"),\n)\nif err != nil {\n    log.Fatalf(\"Failed to connect: %v\", err)\n}\n\nfmt.Println(\"Service is ready!\")\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🌟 Example: HTTP with Advanced Options\u003c/b\u003e\u003c/summary\u003e\n\n```go\n// Create HTTP headers\nheaders := http.Header{}\nheaders.Add(\"Authorization\", \"Bearer token123\")\nheaders.Add(\"Content-Type\", \"application/json\")\n\n// Create an HTTP checker with validation\nchecker := http.New(\n    \"https://api.example.com/health\",\n    http.WithTimeout(5*time.Second),\n    http.WithExpectStatusCode(200),\n    http.WithExpectBodyJSON(\"status\"),\n    http.WithExpectBodyRegex(`\"healthy\":\\s*true`),\n    http.WithExpectHeader(\"Content-Type=application/json\"),\n    http.WithRequestHeaders(headers),\n)\n\n// Wait for the API to be ready\nerr := waiter.WaitContext(ctx, checker, options...)\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🌟 Example: Parallel Service Checking\u003c/b\u003e\u003c/summary\u003e\n\n```go\n// Create checkers for multiple services\ncheckers := []checker.Checker{\n    redis.New(\"redis://localhost:6379\"),\n    postgresql.New(\"postgres://user:pass@localhost:5432/db\"),\n    http.New(\"http://localhost:8080/health\"),\n}\n\n// Wait for all services in parallel\nerr := waiter.WaitParallelContext(\n    ctx,\n    checkers,\n    waiter.WithTimeout(time.Minute),\n    waiter.WithBackoffPolicy(waiter.BackoffPolicyExponential),\n)\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🌟 Example: Custom Checker Implementation\u003c/b\u003e\u003c/summary\u003e\n\n```go\n// Define your custom checker\ntype FileChecker struct {\n    filePath string\n    minSize  int64\n}\n\n// Implement Checker interface\nfunc (f *FileChecker) Identity() (string, error) {\n    return fmt.Sprintf(\"file(%s)\", f.filePath), nil\n}\n\nfunc (f *FileChecker) Check(ctx context.Context) error {\n    // Check if context is done\n    select {\n    case \u003c-ctx.Done():\n        return ctx.Err()\n    default:\n        // Continue checking\n    }\n\n    fileInfo, err := os.Stat(f.filePath)\n    if err != nil {\n        if os.IsNotExist(err) {\n            return checker.NewExpectedError(\n                \"file does not exist\",\n                err,\n                \"path\", f.filePath,\n            )\n        }\n        return err\n    }\n\n    if fileInfo.Size() \u003c f.minSize {\n        return checker.NewExpectedError(\n            \"file is smaller than expected\",\n            nil,\n            \"path\", f.filePath,\n            \"actual_size\", fileInfo.Size(),\n            \"expected_min_size\", f.minSize,\n        )\n    }\n\n    return nil\n}\n```\n\u003c/details\u003e\n\nFor more detailed examples with complete code, see the [examples/pkg](examples/pkg) directory. Each example is in its own directory with a runnable `main.go` file.\n\n## 🤝 Contributing\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e🐛 Reporting Issues\u003c/b\u003e\u003c/summary\u003e\n\nIf you encounter a bug or have a feature request, please open an issue:\n- **[Report a bug](https://github.com/wait4x/wait4x/issues/new?template=bug_report.md)**\n- **[Request a feature](https://github.com/wait4x/wait4x/issues/new?template=feature_request.md)**\n\nPlease include as much information as possible, including:\n- Wait4X version\n- Command-line arguments\n- Expected vs. actual behavior\n- Any error messages\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e💻 Code Contributions\u003c/b\u003e\u003c/summary\u003e\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feature/your-feature-name`\n3. Make your changes\n4. Add tests for your changes\n5. Run the tests: `make test`\n6. Commit your changes: `git commit -am 'Add awesome feature'`\n7. Push the branch: `git push origin feature/your-feature-name`\n8. Create a Pull Request\n\u003c/details\u003e\n\n## 📄 License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n\n```\nCopyright 2019-2025 The Wait4X Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n\n### Credits\n\nThe project logo is based on the \"Waiting Man\" character (Zhdun) and is used with attribution to the original creator.","funding_links":["https://github.com/sponsors/atkrad"],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwait4x%2Fwait4x","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwait4x%2Fwait4x","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwait4x%2Fwait4x/lists"}