{"id":36510566,"url":"https://github.com/singchia/geminio","last_synced_at":"2026-02-14T15:04:06.363Z","repository":{"id":206636367,"uuid":"412119706","full_name":"singchia/geminio","owner":"singchia","description":"A hybrid application-layer networking framework with support for messaging, RPC, bidirectional RPC, multiplexing, and maintaining client-server consistency.","archived":false,"fork":false,"pushed_at":"2026-02-07T16:50:11.000Z","size":1252,"stargazers_count":72,"open_issues_count":3,"forks_count":18,"subscribers_count":18,"default_branch":"main","last_synced_at":"2026-02-08T00:58:11.637Z","etag":null,"topics":["bidirectional-rpc","c10k","high-performance","intranet-penetration","long-connection","multiplexer","nat","network-framework","networking","networking-programmability","proxy","rpc","streaming","tcp","traversal"],"latest_commit_sha":null,"homepage":"","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/singchia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-09-30T15:28:21.000Z","updated_at":"2026-02-07T16:48:18.000Z","dependencies_parsed_at":"2024-02-08T07:25:03.122Z","dependency_job_id":"0e889679-3634-4aed-ab57-88638ab00287","html_url":"https://github.com/singchia/geminio","commit_stats":null,"previous_names":["singchia/geminio"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/singchia/geminio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singchia%2Fgeminio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singchia%2Fgeminio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singchia%2Fgeminio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singchia%2Fgeminio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/singchia","download_url":"https://codeload.github.com/singchia/geminio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singchia%2Fgeminio/sbom","scorecard":{"id":827010,"data":{"date":"2025-08-11","repo":{"name":"github.com/singchia/geminio","commit":"8fc3ae6c314d4e542badf4139b44f83128ec1da4"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.6,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":3,"reason":"4 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/14 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2024-3321 / GHSA-v778-237x-gjrc","Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T16:48:40.062Z","repository_id":206636367,"created_at":"2025-08-23T16:48:40.063Z","updated_at":"2025-08-23T16:48:40.063Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29447768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T14:10:32.461Z","status":"ssl_error","status_checked_at":"2026-02-14T14:09:49.945Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["bidirectional-rpc","c10k","high-performance","intranet-penetration","long-connection","multiplexer","nat","network-framework","networking","networking-programmability","proxy","rpc","streaming","tcp","traversal"],"created_at":"2026-01-12T02:35:16.420Z","updated_at":"2026-02-14T15:04:06.355Z","avatar_url":"https://github.com/singchia.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"./docs/geminio.png\" width=\"200\"\u003e\n\n\n\u003e A powerful application-layer network programming library for Go\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/singchia/geminio.svg)](https://pkg.go.dev/github.com/singchia/geminio)\n[![Go Report Card](https://goreportcard.com/badge/github.com/singchia/geminio)](https://goreportcard.com/report/github.com/singchia/geminio)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Platform](https://img.shields.io/badge/platform-linux%20%7C%20macos%20%7C%20windows-brightgreen.svg)](https://github.com/singchia/geminio)\n\n[English](./README.md) | [简体中文](./README_cn.md)\n\n\u003c/div\u003e\n\n---\n\n## 📖 Introduction\n\n**Geminio** is a comprehensive application-layer network programming library for Go, named after the [Doubling Charm](https://harrypotter.fandom.com/wiki/Doubling_Charm) from Harry Potter. It provides a unified interface for building network applications with features like RPC, bidirectional RPC, messaging, multi-session management, connection multiplexing, and raw connection handling.\n\nGeminio simplifies network development by abstracting away the complexity of low-level network programming, allowing developers to focus on business logic rather than connection management.\n\n## ✨ Features\n\n- 🔄 **RPC \u0026 Bidirectional RPC** - Full support for remote procedure calls with bidirectional capabilities\n- 📨 **Messaging** - Reliable message delivery with acknowledgment guarantees\n- 🔀 **Connection Multiplexing** - Multiple logical connections over a single physical connection\n- 🆔 **Connection Identification** - Unique ClientID and StreamID for connection management\n- 🔌 **Native Compatibility** - Seamless integration with Go's `net.Conn` and `net.Listener`\n- 🔁 **High Availability** - Built-in automatic reconnection mechanism for clients\n- ⚡ **High Performance** - Optimized for low latency and high throughput\n- 🛡️ **Production Ready** - Extensive testing including stress tests, chaos tests, and performance profiling\n- 📦 **Zero Dependencies** - Lightweight with minimal external dependencies\n\n## 🚀 Quick Start\n\n### Installation\n\n```bash\ngo get github.com/singchia/geminio\n```\n\n### Basic Example\n\n**Server:**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/singchia/geminio/server\"\n)\n\nfunc main() {\n    ln, err := server.Listen(\"tcp\", \"127.0.0.1:8080\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    for {\n        end, err := ln.AcceptEnd()\n        if err != nil {\n            log.Fatal(err)\n        }\n        \n        go func() {\n            msg, err := end.Receive(context.TODO())\n            if err != nil {\n                return\n            }\n            log.Printf(\"Received: %s\", string(msg.Data()))\n            msg.Done()\n        }()\n    }\n}\n```\n\n**Client:**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/singchia/geminio/client\"\n)\n\nfunc main() {\n    end, err := client.NewEnd(\"tcp\", \"127.0.0.1:8080\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer end.Close()\n\n    msg := end.NewMessage([]byte(\"Hello, Geminio!\"))\n    if err := end.Publish(context.TODO(), msg); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n## 📚 Documentation\n\n### Architecture\n\nGeminio follows a layered architecture design:\n\n\u003cimg src=\"./docs/biz-arch.png\" width=\"100%\"\u003e\n\n### Core Interfaces\n\nThe library's main abstractions are defined in `geminio.go`:\n\n```go\n// RPC interface\ntype RPCer interface {\n    NewRequest(data []byte, opts ...*options.NewRequestOptions) Request\n    Call(ctx context.Context, method string, req Request, opts ...*options.CallOptions) (Response, error)\n    CallAsync(ctx context.Context, method string, req Request, ch chan *Call, opts ...*options.CallOptions) (*Call, error)\n    Register(ctx context.Context, method string, rpc RPC) error\n}\n\n// Messaging interface\ntype Messager interface {\n    NewMessage(data []byte, opts ...*options.NewMessageOptions) Message\n    Publish(ctx context.Context, msg Message, opts ...*options.PublishOptions) error\n    PublishAsync(ctx context.Context, msg Message, ch chan *Publish, opts ...*options.PublishOptions) (*Publish, error)\n    Receive(ctx context.Context) (Message, error)\n}\n\n// Stream interface (combines RPC, Messaging, and Raw connection)\ntype Stream interface {\n    RawRPCMessager  // RPC + Messaging + net.Conn\n    StreamID() uint64\n    ClientID() uint64\n    Meta() []byte\n}\n\n// Multiplexer for managing multiple streams\ntype Multiplexer interface {\n    OpenStream(opts ...*options.OpenStreamOptions) (Stream, error)\n    AcceptStream() (Stream, error)\n    ListStreams() []Stream\n}\n\n// End is the main entry point\ntype End interface {\n    Stream      // End is also a default stream (streamID = 1)\n    Multiplexer // End can manage multiple streams\n    Close()\n}\n```\n\n## 💡 Usage Examples\n\n### Message Publishing\n\n**Server:**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/singchia/geminio/server\"\n)\n\nfunc main() {\n    ln, err := server.Listen(\"tcp\", \"127.0.0.1:8080\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    for {\n        end, err := ln.AcceptEnd()\n        if err != nil {\n            log.Fatal(err)\n        }\n        \n        go func() {\n            msg, err := end.Receive(context.TODO())\n            if err != nil {\n                return\n            }\n            log.Printf(\"Received: %s\", string(msg.Data()))\n            msg.Done()\n        }()\n    }\n}\n```\n\n**Client:**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/singchia/geminio/client\"\n)\n\nfunc main() {\n    end, err := client.NewEnd(\"tcp\", \"127.0.0.1:8080\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer end.Close()\n\n    msg := end.NewMessage([]byte(\"hello\"))\n    if err := end.Publish(context.TODO(), msg); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n### RPC\n\n**Server:**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/singchia/geminio\"\n    \"github.com/singchia/geminio/server\"\n)\n\nfunc main() {\n    ln, err := server.Listen(\"tcp\", \"127.0.0.1:8080\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    for {\n        end, err := ln.AcceptEnd()\n        if err != nil {\n            log.Fatal(err)\n        }\n        \n        go func() {\n            err := end.Register(context.TODO(), \"echo\", echo)\n            if err != nil {\n                log.Fatal(err)\n            }\n        }()\n    }\n}\n\nfunc echo(_ context.Context, req geminio.Request, rsp geminio.Response) {\n    rsp.SetData(req.Data())\n    log.Printf(\"Echo: %s\", string(req.Data()))\n}\n```\n\n**Client:**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/singchia/geminio/client\"\n)\n\nfunc main() {\n    opt := client.NewEndOptions()\n    opt.SetWaitRemoteRPCs(\"echo\")\n    \n    end, err := client.NewEnd(\"tcp\", \"127.0.0.1:8080\", opt)\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer end.Close()\n\n    rsp, err := end.Call(context.TODO(), \"echo\", end.NewRequest([]byte(\"hello\")))\n    if err != nil {\n        log.Fatal(err)\n    }\n    \n    log.Printf(\"Response: %s\", string(rsp.Data()))\n}\n```\n\n### Bidirectional RPC\n\n**Server:**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/singchia/geminio\"\n    \"github.com/singchia/geminio/server\"\n)\n\nfunc main() {\n    opt := server.NewEndOptions()\n    opt.SetWaitRemoteRPCs(\"client-echo\")\n    opt.SetRegisterLocalRPCs(\u0026geminio.MethodRPC{\"server-echo\", echo})\n\n    ln, err := server.Listen(\"tcp\", \"127.0.0.1:8080\", opt)\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    for {\n        end, err := ln.AcceptEnd()\n        if err != nil {\n            log.Fatal(err)\n        }\n        \n        go func() {\n            rsp, err := end.Call(context.TODO(), \"client-echo\", end.NewRequest([]byte(\"foo\")))\n            if err != nil {\n                log.Fatal(err)\n            }\n            log.Printf(\"Client echo: %s\", string(rsp.Data()))\n        }()\n    }\n}\n\nfunc echo(_ context.Context, req geminio.Request, rsp geminio.Response) {\n    rsp.SetData(req.Data())\n    log.Printf(\"Server echo: %s\", string(req.Data()))\n}\n```\n\n**Client:**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/singchia/geminio\"\n    \"github.com/singchia/geminio/client\"\n)\n\nfunc main() {\n    opt := client.NewEndOptions()\n    opt.SetWaitRemoteRPCs(\"server-echo\")\n    opt.SetRegisterLocalRPCs(\u0026geminio.MethodRPC{\"client-echo\", echo})\n\n    end, err := client.NewEnd(\"tcp\", \"127.0.0.1:8080\", opt)\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer end.Close()\n\n    rsp, err := end.Call(context.TODO(), \"server-echo\", end.NewRequest([]byte(\"bar\")))\n    if err != nil {\n        log.Fatal(err)\n    }\n    \n    log.Printf(\"Server echo: %s\", string(rsp.Data()))\n}\n\nfunc echo(_ context.Context, req geminio.Request, rsp geminio.Response) {\n    rsp.SetData(req.Data())\n    log.Printf(\"Client echo: %s\", string(req.Data()))\n}\n```\n\n### Multiplexing\n\n**Server:**\n\n```go\npackage main\n\nimport (\n    \"log\"\n\n    \"github.com/singchia/geminio/server\"\n)\n\nfunc main() {\n    ln, err := server.Listen(\"tcp\", \"127.0.0.1:8080\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    for {\n        end, err := ln.AcceptEnd()\n        if err != nil {\n            log.Fatal(err)\n        }\n        \n        // Open stream #1\n        sm1, err := end.OpenStream()\n        if err != nil {\n            log.Fatal(err)\n        }\n        sm1.Write([]byte(\"hello#1\"))\n        sm1.Close()\n\n        // Open stream #2\n        sm2, err := end.OpenStream()\n        if err != nil {\n            log.Fatal(err)\n        }\n        sm2.Write([]byte(\"hello#2\"))\n        sm2.Close()\n    }\n}\n```\n\n**Client:**\n\n```go\npackage main\n\nimport (\n    \"net\"\n    \"log\"\n\n    \"github.com/singchia/geminio/client\"\n)\n\nfunc main() {\n    end, err := client.NewEnd(\"tcp\", \"127.0.0.1:8080\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer end.Close()\n\n    // End can be used as net.Listener\n    ln := net.Listener(end)\n    for {\n        conn, err := ln.Accept()\n        if err != nil {\n            log.Fatal(err)\n        }\n        \n        go func(conn net.Conn) {\n            buf := make([]byte, 128)\n            n, err := conn.Read(buf)\n            if err != nil {\n                return\n            }\n            log.Printf(\"Read: %s\", string(buf[:n]))\n        }(conn)\n    }\n}\n```\n\n## 📦 More Examples\n\nCheck out the [examples](./examples) directory for more comprehensive examples:\n\n- **[Messager](./examples/messager)** - Message publishing and receiving with acknowledgment\n- **[Message Queue](./examples/mq)** - A simple message queue implementation\n- **[Chatroom](./examples/chatroom)** - Real-time chatroom example\n- **[Relay](./examples/relay)** - Network relay proxy\n- **[Intranet Penetration](./examples/traversal)** - NAT traversal example\n\n## ⚡ Performance\n\nBenchmark results (Intel Core i5-6267U @ 2.90GHz):\n\n```\ngoos: darwin\ngoarch: amd64\npkg: github.com/singchia/geminio/test/bench\ncpu: Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz\n\nBenchmarkMessage-4   \t   10117\t    112584 ns/op\t1164.21 MB/s\t    5764 B/op\t     181 allocs/op\nBenchmarkEnd-4       \t   11644\t     98586 ns/op\t1329.52 MB/s\t  550534 B/op\t      73 allocs/op\nBenchmarkStream-4    \t   12301\t     96955 ns/op\t1351.88 MB/s\t  550605 B/op\t      82 allocs/op\nBenchmarkRPC-4       \t    6960\t    165384 ns/op\t 792.53 MB/s\t   38381 B/op\t     187 allocs/op\n```\n\n## 🏗️ Design\n\nGeminio is built with a layered architecture:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"./docs/design.png\" width=\"80%\"\u003e\n\u003c/p\u003e\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n### Guidelines\n\n- Maintain consistent code style\n- Submit one feature at a time\n- Include unit tests with your code\n- Update documentation as needed\n\nFor bug reports or feature requests, please open an issue on GitHub.\n\n## 📄 License\n\nCopyright © Austin Zhai, 2023-2030\n\nLicensed under the [Apache License 2.0](./LICENSE)\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n\u003ca href=\"https://next.ossinsight.io/widgets/official/compose-activity-trends?repo_id=412119706\" target=\"_blank\" style=\"display: block\" align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://next.ossinsight.io/widgets/official/compose-activity-trends/thumbnail.png?repo_id=412119706\u0026image_size=auto\u0026color_scheme=dark\" width=\"815\" height=\"auto\"\u003e\n    \u003cimg alt=\"Activity Trends of singchia/geminio - Last 28 days\" src=\"https://next.ossinsight.io/widgets/official/compose-activity-trends/thumbnail.png?repo_id=412119706\u0026image_size=auto\u0026color_scheme=light\" width=\"815\" height=\"auto\"\u003e\n  \u003c/picture\u003e\n\u003c/a\u003e\n\nMade with [OSS Insight](https://ossinsight.io/)\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsingchia%2Fgeminio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsingchia%2Fgeminio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsingchia%2Fgeminio/lists"}