{"id":35458581,"url":"https://github.com/chalk-ai/chalk-go","last_synced_at":"2026-04-28T22:03:05.727Z","repository":{"id":147937888,"uuid":"610426779","full_name":"chalk-ai/chalk-go","owner":"chalk-ai","description":"Go client for Chalk","archived":false,"fork":false,"pushed_at":"2026-04-19T06:21:13.000Z","size":15013,"stargazers_count":8,"open_issues_count":14,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-04-19T08:24:43.769Z","etag":null,"topics":["data","data-pipeline","feature-engineering"],"latest_commit_sha":null,"homepage":"https://chalk.ai","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/chalk-ai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-06T18:50:04.000Z","updated_at":"2026-04-19T01:51:43.000Z","dependencies_parsed_at":"2024-02-02T23:30:40.937Z","dependency_job_id":"6f5fdcb3-7ef5-4360-a546-b0bbbd8607fd","html_url":"https://github.com/chalk-ai/chalk-go","commit_stats":null,"previous_names":[],"tags_count":681,"template":false,"template_full_name":null,"purl":"pkg:github/chalk-ai/chalk-go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chalk-ai%2Fchalk-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chalk-ai%2Fchalk-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chalk-ai%2Fchalk-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chalk-ai%2Fchalk-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chalk-ai","download_url":"https://codeload.github.com/chalk-ai/chalk-go/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chalk-ai%2Fchalk-go/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32400873,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T19:38:08.556Z","status":"ssl_error","status_checked_at":"2026-04-28T19:37:55.688Z","response_time":56,"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":["data","data-pipeline","feature-engineering"],"created_at":"2026-01-03T07:21:18.594Z","updated_at":"2026-04-28T22:03:05.685Z","avatar_url":"https://github.com/chalk-ai.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Go Reference](https://pkg.go.dev/badge/github.com/chalk-ai/chalk-go.svg)](https://pkg.go.dev/github.com/chalk-ai/chalk-go)\n[![Test](https://github.com/chalk-ai/chalk-go/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/chalk-ai/chalk-go/actions/workflows/test.yml)\n\n# Go Chalk\n\nThe official [Chalk](https://chalk.ai) client library.\n\n## Usage\n\n### Installation\n\nMake sure your project is using Go modules (it will have a `go.mod` file in its\nroot if it already is):\n\n``` sh\ngo mod init \u003cmodule-path\u003e\n```\n\nThen reference `chalk-go` in your Go program:\n\n``` go\nimport (\n    \"github.com/chalk-ai/chalk-go\"\n)\n```\n\nRun any of the normal `go` commands (`build`/`install`/`test`). The Go\ntoolchain will resolve and fetch the `chalk-go` module automatically.\n\nAlternatively, you can explicitly add the dependency:\n\n```bash\ngo get -u github.com/chalk-ai/chalk-go\n```\n\nThis library requires Go 1.24.6 or later.\n\n### Codegen\n\nChalk generates Go structs from your Python feature definitions, which makes it\neasy to use your features from Go.\n\nRun the codegen command inside your Chalk project to generate a\nfile containing your generated structs, then copy that file into\nyour Go project.\n\n```sh\nchalk codegen go --out=\u003cOUTPUT_FILEPATH\u003e\n```\n\nYou can read more in the [CLI docs](https://docs.chalk.ai/cli?command=codegen_go).\n\n### Connect to Chalk\n\nCreate a client using `NewClient`.\nThe returned client gets its configuration from the first available source in this order:\n\n1. Overrides configured by passing a `*chalk.ClientConfig`:\n    ```go\n    client, err := chalk.NewClient(\n        ctx,\n        \u0026chalk.ClientConfig{\n            ClientId:      \"id-89140a6614886982a6782106759e30\",\n            ClientSecret:  \"sec-b1ba98e658d7ada4ff4c7464fb0fcee65fe2cbd86b3dd34141e16f6314267b7b\",\n            ApiServer:     \"https://api.chalk.ai\",\n            EnvironmentId: \"qa\",\n            Branch:        \"jorges-december\",\n        },\n    )\n    ```\n2. Environment variables:\n    - `CHALK_ACTIVE_ENVIRONMENT`\n    - `CHALK_API_SERVER`\n    - `CHALK_CLIENT_ID`\n    - `CHALK_CLIENT_SECRET`\n    ```go\n    client, err := chalk.NewClient(ctx)\n    ```\n3. The file `~/.chalk.yml`, which is created and updated when you run `chalk login`:\n    ```go\n    client, err := chalk.NewClient(ctx)\n    ```\n\n### gRPC Client\nTo use gRPC as the underlying protocol for communication with Chalk:\n```go\n// Create a client\nclient, err := chalk.NewGRPCClient(\n\tctx,\n\t\u0026chalk.GRPCClientConfig{Branch: \"my-branch\"},\n)\n\n// Online query\nvar users []User\nres, err := client.OnlineQueryBulk(\n\tctx,\n\tchalk.OnlineQueryParams{}.\n\t\tWithInput(Features.User.Id, []string{\"u273489056\"}).\n\t\tWithInput(Features.User.Transactions, [][]Transaction{\n\t\t\t{\n\t\t\t\t{Id: utils.ToPtr(\"txn8f76\"), Amount: utils.ToPtr(13.23)},\n\t\t\t\t{Id: utils.ToPtr(\"txn546d\"), Amount: utils.ToPtr(48.95)},\n\t\t\t},\n\t\t}).\n\t\tWithOutputs(Features.User.Id, Features.User.WeightedScore),\n)\nif err != nil {\n\treturn errors.Wrap(err, \"querying weighted score\")\n}\nif err = res.UnmarshalInto(\u0026users); err != nil {\n\treturn errors.Wrap(err, \"unmarshalling into users\")\n}\nfmt.Printf(\"user %s has weighted score %v\\n\", users[0].Id, users[0].WeightedScore)\n\n\n// Multi-namespace online query\ntype underwriting struct {\n\tUser\n\tLoan\n}\n\nres, err := client.OnlineQueryBulk(\n    context.Background(),\n    chalk.OnlineQueryParams{}.\n        WithInput(Features.User.Id, []string{\"u273489056\"}).\n        WithInput(Features.Loan.Id, []string{\"l273489056\"}).\n        WithOutputs(\n            Features.User.Id,\n            Features.User.WeightedScore,\n            Features.Loan.Id,\n            Features.Loan.ApprovalStatus,\n        ),\n)\nif err != nil {\n\treturn errors.Wrap(err, \"querying weighted score and loan approval status\")\n}\n\nvar root []underwriting\nif err = res.UnmarshalInto(\u0026root); err != nil {\n\treturn errors.Wrap(err, \"unmarshalling into underwriting\")\n}\nfmt.Printf(\"user %s has weighted score %v\\n\", root[0].User.Id, root[0].User.WeightedScore)\nfmt.Printf(\"loan %s has approval status %v\\n\", root[0].Loan.Id, root[0].Loan.ApprovalStatus)\n```\n\n### Online Query\n\nQuery online features using the generated feature structs. Access results in the\nreturned object or by passing a pointer to a variable with the correct type.\n\n```go\nuser := User{}\n_, err = client.OnlineQuery(\n    context.Background(),\n    chalk.OnlineQueryParams{}.\n        WithInput(Features.User.Id, \"u273489057\").\n        WithInput(Features.User.Transactions, []Transaction{\n            {Id: utils.ToPtr(\"sd8f76\"), Amount: utils.ToPtr(13.23)},\n            {Id: utils.ToPtr(\"jk546d\"), Amount: utils.ToPtr(48.95)},\n        }).\n        WithOutputs(Features.User.Id, Features.User.LastName),\n    \u0026user,\n)\n```\n\n### Named Queries\n\nIf your deployment contains [named queries](https://docs.chalk.ai/docs/best-practices#create-named-queries-for-your-commonly-executed-queries),\nyou can specify a query name instead of outputs when making a query.\n\n```go\nuser := User{}\n_, err = client.OnlineQuery(\n    context.Background(),\n    chalk.OnlineQueryParams{}.\n        WithInput(Features.User.Id, \"u273489057\").\n        WithQueryName(\"user_underwriting_features\"),\n    \u0026user,\n)\n```\n\n### Offline Query\n\nWhen executing an offline query, a dataset is returned and can be downloaded as parquet files using the `DownloadData` method.\n\n```go\nres, err := client.OfflineQuery(\n    context.Background(),\n    chalk.OfflineQueryParams{}.\n        WithInput(Features.User.Id, []any{...}).\n        WithOutputs(Features.User),\n)\nif err != nil {\n    return err\n}\n\nerr = res.Revisions[0].DownloadData(\u003cFILE_DIRECTORY\u003e)\n```\n\n### Upload Features\n\nChalk allows you to synchronously persist features directly to your online and offline stores.\n\n```go\nres, err := client.UploadFeatures(\n    context.Background(),\n    chalk.UploadFeaturesParams{\n        Inputs: map[any]any{\n            Features.User.Id: []string{\"user-1\", \"user-2\"},\n            \"user.last_name\": []string{\"Borges\", \"Paris\"},\n        },\n    },\n)\n```\n\n### Update Aggregates\n\nNote: This method is available only when using the gRPC client. See [gRPC Client](#grpc-client) for more information.\n\nYou can easily update your windowed aggregation feature values with `UpdateAggregates`. For example, with this feature\ndefinition:\n```python\n@features\nclass User:\n    id: str\n    txns: \"DataFrame[Transaction]\"\n    txn_amount_total: Windowed[int] = windowed(\n        \"30d\",\n        \"90d\",\n        materialization={\n            \"bucket_duration\": \"1d\",\n        },\n        expression=_.txns[_.amount].sum(),\n    )\n\n@features\nclass Transaction:\n    id: Primary[str]\n    amount: float\n    user_id: str\n```\nThen to update the `txn_amount_total` feature, you would upload features corresponding to that aggregation:\n```go\nres, err := client.UpdateAggregates(\n    context.Background(),\n    chalk.UpdateAggregatesParams{\n        Inputs: map[any]any{\n            \"transaction.id\": []string{\"txn-1\", \"txn-2\"},\n            \"transaction.user_id\": []string{\"user-1\", \"user-2\"},\n            \"transaction.amount\": []float64{100.0, 200.0},\n            \"transaction.__chalk_observed_at__\": []time.Time{time.Now(), time.Now()},\n        },\n    },\n)\n```\nNote that if you have an explicit `FeatureTime` feature specified, you can provide that in place of the\n`__chalk_observed_at__` column.\n\n### Querying against a branch\n\nTo query against a branch, create a `Client` with `Branch` specified, then make\nqueries using that client.\n```go\nclient, err := chalk.NewClient(\n\tcontext.Background(),\n\t\u0026chalk.ClientConfig{\n\t\tBranch:        \"jorges-december\",\n\t},\n)\n```\n\n### Configuring Logging\n\nBy default, Chalk logs error messages only (which are sent to `stderr`).\nConfigure default logging using the global `DefaultLeveledLogger` variable:\n\n```go\nchalk.DefaultLeveledLogger = \u0026chalk.StdOutLeveledLogger{\n    Level: chalk.LevelInfo,\n}\n```\n\n\u003c!-- Or on a per-client basis:\n\n```go\nconfig := \u0026chalk.ClientConfig{\n    Logger: \u0026chalk.StdOutLeveledLogger{\n        Level: chalk.LevelInfo,\n    },\n}\nclient := chalk.Client(config)\n``` --\u003e\n\nIt's also possible to use non-Chalk leveled loggers. Chalk expects loggers to\ncomply with the following interface:\n\n```go\ntype LeveledLogger interface {\n    Debugf(format string, v ...interface{})\n    Errorf(format string, v ...interface{})\n    Infof(format string, v ...interface{})\n    Warnf(format string, v ...interface{})\n}\n```\n\nSome loggers like Logrus and Zap's `SugaredLogger`\nsupport this interface natively, so it's possible to set\n`DefaultLeveledLogger` to a `*logrus.Logger` or `*zap.SugaredLogger` directly.\nTo use other loggers, you may need a shim layer.\n\n\n## Querying for expressions\n\nWith the gRPC client, you can also query expressions that are not part of your\nfeature set.\n\n```go\nclient, err := chalk.NewGRPCClient(ctx)\nresult, err := client.OnlineQueryBulk(\n    ctx,\n    chalk.OnlineQueryParams{}.\n        WithInput(\"user.id\", []int{1}).\n        WithOutputs(\"user.id\").\n        WithOutputExprs(\n            expr.FunctionCall(\n                \"jaccard_similarity\",\n                expr.Col(\"name\"),\n                expr.Col(\"email\"),\n            ).\n                As(\"name_email_sim\"),\n            expr.DataFrame(\"transactions\").\n                Filter(expr.Col(\"amount\").Gt(expr.Float(400000.0))).\n                Agg(\"count\").\n                As(\"user_transaction_count\"),\n        ),\n)\nrow, err := result.GetRow(0)\nfor feature, value := range row.Features {\n    fmt.Printf(\"Feature: %s, Value: %+v\\n\", feature, value.Value)\n}\n```\n\nThis API allows for computing both scalar expressions (like `jaccard_similarity` above)\nas well as aggregations over `DataFrames` (like `user_transaction_count` above).\n\nThe script above prints:\n\n```text\nFeature: user.id, Value: 1\nFeature: name_email_sim, Value: 0.4375\nFeature: user_transaction_count, Value: 0\n```\n\nNote that the `.As(...)` method gives the\nname of the expression in the returned result.\n\n## Contributing\n\nWe'd love to accept your patches. If you submit a pull request, please keep the\nfollowing guidelines in mind:\n\n1. Fork the repo, develop and test your code changes.\n2. Ensure your code adheres to the existing style.\n3. Ensure that your code has an appropriate set of tests that pass.\n4. Submit a pull request.\n\n\n### Development\n\nClone the Git repo from [github.com/chalk-ai/chalk-go](https://github.com/chalk-ai/chalk-go).\n\n1. All patches must be `go fmt` compatible.\n2. All types, structs, and functions should be documented.\n\n### Testing\n\nTo execute the tests: `go test ./...`. Ensure all tests pass.\n\n## License\n\nApache 2.0 - See [LICENSE](LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchalk-ai%2Fchalk-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchalk-ai%2Fchalk-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchalk-ai%2Fchalk-go/lists"}