Contributing to Fluid Forge
We welcome contributions of all kinds — bug reports, feature ideas, docs improvements, and code.
Ways to Contribute
Report a Bug
Open an issue at github.com/Agenticstiger/forge-cli/issues with:
- What happened vs. what you expected
- The command you ran and its output
fluid versionandfluid doctoroutput- Your contract file (redact sensitive values)
Suggest a Feature
Start a GitHub Discussion or open an issue tagged enhancement.
Improve Documentation
The docs live in docs/ and are built with VuePress. To preview locally:
cd forge_docs
npm ci
npm run docs:dev
Edit any .md file, save, and your browser refreshes automatically.
Submit a Docs Pull Request
# 1. Fork & clone the docs repo
git clone https://github.com/<your-username>/forge_docs.git
cd forge_docs
# 2. Install dependencies
npm ci
# 3. Create a branch
git checkout -b docs/my-improvement
# 4. Preview or build locally
npm run docs:dev
npm run docs:build
# 5. Commit with conventional format
git commit -m "docs: update provider guide"
# 6. Push & open a PR
git push origin docs/my-improvement
If your docs change is the companion to a CLI change, link the related forge-cli PR in your docs PR description. We keep that link optional here because many docs updates are docs-only improvements.
What we look for in docs PRs
- The page is accurate and easy to follow
- Links still work
- Navigation and headings still make sense
npm run docs:buildpasses locallypython scripts/check_cli_docs.pyandpython scripts/check_providers.pypass against the pinned CLI
Keeping the docs in sync with the CLI
Every CLI release bumps the supported version in docs/.vuepress/cli-version.json. The cli-consistency GitHub Actions workflow installs that exact version of data-product-forge from PyPI on every PR and verifies:
fluid --versionmatches the pinnedsupportedCliVersion.- Every subcommand listed by
fluid --helphas a matchingdocs/cli/<name>.mdpage. - Every page in
docs/cli/corresponds to a real CLI command (or sits inscripts/cli-docs-allowlist.ymlwith a comment explaining why). - Every provider returned by
fluid providers --jsonhas a matchingdocs/providers/<name>.mdpage.
When a new CLI version ships:
# 1. Bump the pin
$EDITOR docs/.vuepress/cli-version.json
# 2. Install locally and run the consistency checks
pip install --upgrade "data-product-forge==$(jq -r .supportedCliVersion docs/.vuepress/cli-version.json)"
python scripts/check_cli_docs.py
python scripts/check_providers.py
# 3. The scripts will list any newly-added commands or providers — write the
# matching docs page (or, if the command should stay hidden, add it to
# scripts/cli-docs-allowlist.yml with a one-line reason).
Existing pages follow the layout in docs/cli/init.md — a one-line summary, ## Syntax, ## Key options, ## Examples, ## Notes. Match that shape for new pages so the reference reads consistently.
Build a Custom Provider
Fluid Forge is designed to be extended. See the Custom Providers Guide for the full walkthrough, but the gist is:
from fluid_provider_sdk import ApplyResult, BaseProvider, ProviderError
class MyProvider(BaseProvider):
name = "my-cloud"
def plan(self, contract):
return [{"op": "create_table", "resource_id": "demo"}]
def apply(self, actions):
if not actions:
raise ProviderError("No actions to apply")
return ApplyResult(
provider=self.name,
applied=len(actions),
failed=0,
duration_sec=0.0,
timestamp="",
results=[{"status": "ok", "op": action["op"]} for action in actions],
)
Contribute a Forge Tool (@forge_tool)
Tools are what the multi-turn copilot agent calls during a run (discover_workspace, read_sample_schema, propose_contract, …). The new @forge_tool decorator collapses tool registration to a single declaration where the Pydantic args-model is the source of truth and JSON Schema is derived from it:
from pydantic import BaseModel, Field
from fluid_build.cli.forge_tool import forge_tool
class FetchOrdersArgs(BaseModel):
since: str = Field(description="ISO-8601 lower bound, e.g. 2024-01-01")
limit: int = Field(default=100, ge=1, le=1000)
@forge_tool(
name="fetch_orders",
description="Page through the orders table since a given date.",
args_schema=FetchOrdersArgs,
workspace_root_aware=True, # security: workspace_root is dispatcher-injected
)
def fetch_orders(args: FetchOrdersArgs, *, workspace_root):
return _fetch_impl(workspace_root, args.since, args.limit)
The decorator handles registration in FORGE_TOOL_REGISTRY, JSON Schema generation, args-model validation, workspace_root injection (security boundary — the LLM cannot supply this field), and the typed-error return shape that dispatch_tool_call consumes. See the Authoring Forge Tools guide for the migration path from the legacy _register pattern, the S-013 exception-text scrubbing invariant, and the testing checklist.
Add a Catalog Adapter
Catalog adapters are the source-side complement to providers: they pull metadata FROM an existing catalog (Snowflake Horizon, Databricks Unity, BigQuery, Glue, DataHub, Data Mesh Manager) and feed it into the staged forge pipeline. Each adapter is roughly 200 LOC and follows nine reusable patterns.
A community contributor with a weekend can ship a new one. The walkthrough lives in the forge-cli repo at CONTRIBUTING.md → "Adding a Catalog Adapter".
The path covers:
- Subclass
CatalogAdapter(4 abstract methods). - Honour the nine patterns in
_patterns.py— soft-fail on optional reads, lazy SDK import, per-call client lifecycle, error translation with next-action suggestions, etc. - Add a typed
*CredentialsPydantic class withSecretStrfields. - Register the optional install extra in
pyproject.toml. - Wire the dispatch in
cli/forge_data_model.pyandcli/mcp.py. - Write the test file (templates: every existing adapter ships with one — copy the closest fit and edit).
- Pin the public API in
tests/test_public_api_stability.py. - Document the new catalog at
forge_docs/docs/cli/catalogs/<name>.md.
The seven existing adapters (snowflake, unity, bigquery, dataplex, glue, datahub, datamesh-manager) are working templates — read one front-to-back before starting.
Docs Standards
A few things that help reviewers focus on what matters in your change:
- Clarity first — practical examples and direct language help readers learn fast.
- Build cleanly —
npm run docs:buildcatches issues early so reviewers can focus on content. - Links that work — point at the published docs site and current repo URLs so nothing 404s a month from now.
- Conventional Commits —
feat:/fix:/docs:/chore:(reference); helps changelog automation pick up your work.
Code of Conduct
Be respectful, constructive, and inclusive. See CODE_OF_CONDUCT.md.
License
By contributing, you agree that your work will be licensed under Apache 2.0.
Copyright 2025-2026 Agentics Transformation Pty Ltd · Open source under Apache 2.0