{"id":46697244,"url":"https://github.com/cfengine/cfbs","last_synced_at":"2026-03-09T05:33:30.942Z","repository":{"id":37924584,"uuid":"71269374","full_name":"cfengine/cfbs","owner":"cfengine","description":"The CFEngine Build System","archived":false,"fork":false,"pushed_at":"2026-02-12T17:41:48.000Z","size":1593,"stargazers_count":5,"open_issues_count":0,"forks_count":13,"subscribers_count":8,"default_branch":"master","last_synced_at":"2026-02-13T01:15:00.569Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cfengine.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":null,"security":null,"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":"2016-10-18T16:39:31.000Z","updated_at":"2026-02-12T17:43:22.000Z","dependencies_parsed_at":"2023-12-12T17:58:31.851Z","dependency_job_id":"d3651127-7fdf-485b-ab24-35752aed0346","html_url":"https://github.com/cfengine/cfbs","commit_stats":{"total_commits":417,"total_committers":11,"mean_commits":37.90909090909091,"dds":0.565947242206235,"last_synced_commit":"810cff52d378f87e2f09bb503063f5af38d73603"},"previous_names":[],"tags_count":114,"template":false,"template_full_name":null,"purl":"pkg:github/cfengine/cfbs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cfengine%2Fcfbs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cfengine%2Fcfbs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cfengine%2Fcfbs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cfengine%2Fcfbs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cfengine","download_url":"https://codeload.github.com/cfengine/cfbs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cfengine%2Fcfbs/sbom","scorecard":{"id":271885,"data":{"date":"2025-08-11","repo":{"name":"github.com/cfengine/cfbs","commit":"5826165f732c060d97f8ab379de5799de539c900"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":6.3,"checks":[{"name":"Maintained","score":10,"reason":"30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":10,"reason":"all changesets reviewed","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":"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":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"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":"Token-Permissions","score":7,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/black-format.yml:14","Info: jobLevel 'contents' permission set to 'read': .github/workflows/black.yml:16","Info: jobLevel 'contents' permission set to 'read': .github/workflows/python-publish.yml:14","Info: jobLevel 'contents' permission set to 'read': .github/workflows/python-tests.yml:16","Info: jobLevel 'contents' permission set to 'read': .github/workflows/python-tests.yml:57","Info: jobLevel 'contents' permission set to 'read': .github/workflows/python-validate-test.yml:16","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/update-cfbs-manual.yml:15","Info: topLevel 'contents' permission set to 'read': .github/workflows/add_validate_build_all.yml:13","Warn: no topLevel permission defined: .github/workflows/black-format.yml:1","Warn: no topLevel permission defined: .github/workflows/black.yml:1","Warn: no topLevel permission defined: .github/workflows/python-publish.yml:1","Warn: no topLevel permission defined: .github/workflows/python-tests.yml:1","Warn: no topLevel permission defined: .github/workflows/python-validate-test.yml:1","Warn: no topLevel permission defined: .github/workflows/update-cfbs-manual.yml:1"],"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":"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":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: 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":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/add_validate_build_all.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/add_validate_build_all.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/black-format.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/black-format.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/black-format.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/black-format.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/black-format.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/black-format.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/black.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/black.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/black.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/black.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-publish.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/python-publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-publish.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/python-publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-tests.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/python-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-tests.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/python-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-tests.yml:67: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/python-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-validate-test.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/python-validate-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/update-cfbs-manual.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/update-cfbs-manual.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/update-cfbs-manual.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/update-cfbs-manual.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/update-cfbs-manual.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/cfengine/cfbs/update-cfbs-manual.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/add_validate_build_all.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/black-format.yml:25","Warn: pipCommand not pinned by hash: .github/workflows/black-format.yml:26","Warn: pipCommand not pinned by hash: .github/workflows/black.yml:30","Warn: pipCommand not pinned by hash: .github/workflows/black.yml:31","Warn: pipCommand not pinned by hash: .github/workflows/black.yml:32","Warn: pipCommand not pinned by hash: .github/workflows/python-publish.yml:23","Warn: pipCommand not pinned by hash: .github/workflows/python-publish.yml:24","Warn: pipCommand not pinned by hash: .github/workflows/python-tests.yml:32","Warn: pipCommand not pinned by hash: .github/workflows/python-tests.yml:33","Warn: pipCommand not pinned by hash: .github/workflows/python-tests.yml:34","Warn: pipCommand not pinned by hash: .github/workflows/update-cfbs-manual.yml:28","Warn: pipCommand not pinned by hash: .github/workflows/update-cfbs-manual.yml:29","Info:   0 out of  13 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   3 out of  16 pipCommand dependencies pinned"],"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":"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":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'master'","Warn: 'stale review dismissal' is disabled on branch 'master'","Warn: branch 'master' does not require approvers","Warn: codeowners review is not required on branch 'master'","Warn: 'last push approval' is disabled on branch 'master'","Warn: no status checks found to merge onto branch 'master'","Info: PRs are required in order to make changes on branch 'master'"],"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"}}]},"last_synced_at":"2025-08-17T13:36:21.275Z","repository_id":37924584,"created_at":"2025-08-17T13:36:21.275Z","updated_at":"2025-08-17T13:36:21.275Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30283936,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"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":[],"created_at":"2026-03-09T05:33:29.665Z","updated_at":"2026-03-09T05:33:30.916Z","avatar_url":"https://github.com/cfengine.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CFEngine Build System\n\nThis is a command line tool for combining multiple modules into 1 policy set to deploy on your infrastructure.\nModules can be custom promise types, JSON files which enable certain functionality, or reusable CFEngine policy.\nThe modules you use can be written by the CFEngine team, others in the community, your colleagues, or yourself.\n\n## CFEngine Build Repositories\n\n- [build-index](https://github.com/cfengine/build-index) - Index of modules\n- [build-website](https://github.com/cfengine/build-website) - Website\n- [cfbs](https://github.com/cfengine/cfbs) - Command line client\n- [modules](https://github.com/cfengine/modules) - Official modules provided by the CFEngine team\n- [module-template](https://github.com/cfengine/build-example) - Template for creating new modules\n\n## Installation\n\nRequires Python 3.5 or newer and `pip`.\n\n```\npip install cfbs\n```\n\n(or `sudo pip3 install cfbs` or whatever works with Python 3 on your system).\n\nIt is also **recommended** to install `cf-remote` if you want to deploy the policy set to remote hub(s):\n\n```\npip install cf-remote\n```\n\n### Install from sources\n\nIf you want to install an unreleased version of `cfbs`, such as the master branch, just run this inside [the git repo](https://github.com/cfengine/cfbs):\n\n```\npip install .\n```\n\n### Dependencies\n\n`cfbs` is implemented in Python and has a few dependencies:\n\n- Python 3.5 or newer\n- `git` CLI installed and in PATH\n- `rsync`\n- `autoconf` for configuring masterfiles module (typical usage but not required)\n\n## Usage\n\nHere are the basic commands to set up a repo, add dependencies, build and deploy.\n\n### Initialize a new repo\n\n```\ncfbs init\n```\n\n### List or search available modules\n\n```\ncfbs search\n```\n\nOr more specific:\n\n```\ncfbs search masterfiles\n```\n\n(`masterfiles` is the name of a module and can be replaced with whatever you are looking for).\n\n### Add a module\n\n```\ncfbs add masterfiles\n```\n\n### Build your policy set\n\n```\ncfbs build\n```\n\n### Install your policy set locally\n\n```\ncfbs install /var/cfengine/masterfiles\n```\n\n### Remove added modules\n\n```\ncfbs remove promise-type-git\n```\n\n### Remove unused dependencies\n\n```\ncfbs clean\n```\n\n### Add module input\n\n```\ncfbs input delete-files\n```\n\nThis command prompts the user for module input to configure what the module should do.\n\nOnly works for modules which accept input, indicated by the `\"input\"` key.\nThis `input` key contains the specification for what input the module accepts, if any.\n\nUser's responses are stored in `\u003cmodule-name\u003e/input.json`.\nFor completeness, the input specification is also stored with the responses.\nHere is an example of a `input.json` file with responses:\n\n```json\n[\n  {\n    \"type\": \"list\",\n    \"variable\": \"files\",\n    \"bundle\": \"delete_files\",\n    \"label\": \"Files\",\n    \"subtype\": [\n      {\n        \"key\": \"path\",\n        \"type\": \"string\",\n        \"label\": \"Path\",\n        \"question\": \"Enter path to file\"\n      },\n      {\n        \"key\": \"why\",\n        \"type\": \"string\",\n        \"label\": \"Why\",\n        \"question\": \"Why should this file be deleted?\",\n        \"default\": \"It's malicious.\"\n      }\n    ],\n    \"while\": \"Do you want the module to delete more files?\",\n    \"response\": [\n      { \"path\": \"/tmp/virus\", \"why\": \"It's malicious.\" },\n      {\n        \"path\": \"/home/alice/.ssh/authorized_keys\",\n        \"why\": \"She left the company.\"\n      }\n    ]\n  }\n]\n```\n\nThe `input.json` file is converted and merged into the main `def.json` during the build, using the `input` build step.\n\n### Deploy your policy set to a remote hub\n\n```\ncf-remote deploy\n```\n\nThis will default to the hub(s) you have spawned or saved in `cf-remote`.\nTo specify a hub manually:\n\n```\ncf-remote deploy --hub hub\n```\n\nwhere `hub` is a `cf-remote` group name, or:\n\n```\ncf-remote deploy --hub root@1.2.3.4\n```\n\n## Examples\n\nThere is an example project available here:\n\nhttps://github.com/cfengine/cfbs-example\n\n### Creating a project from scratch\n\nThese commands and output shows how you can use `cfbs` to create a new project from scratch:\n\n```\n$ mkdir demo-project\n$ cd demo-project\n$ cfbs --version\ncfbs 0.4.4\n$ cfbs init\nInitialized - edit name and description cfbs.json\nTo add your first module, type: cfbs add masterfiles\n$ cfbs add masterfiles\nAdded module: masterfiles\n$ cfbs add git\ngit is an alias for promise-type-git\nAdded module: library-for-promise-types-in-python (Dependency of promise-type-git)\nAdded module: promise-type-git\n$ cfbs build\nModules:\n001 masterfiles                         @ 28d9b933db5fc8e1dea4338669cc4fd6677646f1 (Downloaded)\n002 library-for-promise-types-in-python @ 1438ad8515267b3dd4b862cfcd63c1b9ccfb42e1 (Downloaded)\n003 promise-type-git                    @ 1438ad8515267b3dd4b862cfcd63c1b9ccfb42e1 (Downloaded)\nSteps:\n001 masterfiles                         : run './autogen.sh'\n001 masterfiles                         : delete './autogen.sh'\n001 masterfiles                         : copy './' 'masterfiles/'\n002 library-for-promise-types-in-python : copy 'cfengine.py' 'masterfiles/modules/promise_types/'\n003 promise-type-git                    : copy 'git.py' 'masterfiles/modules/promise_types/'\n003 promise-type-git                    : append 'enable.cf' 'masterfiles/services/init.cf'\nGenerating tarball...\nBuild complete, ready to deploy 🐿\n -\u003e Directory: out/masterfiles\n -\u003e Tarball:   out/masterfiles.tgz\nTo install on this machine: cfbs install\nTo deploy on remote hub(s): cf-remote deploy\n$ head out/masterfiles/modules/promise_types/git.py\nimport os\nimport subprocess\nfrom typing import Dict, Optional\nfrom cfengine import PromiseModule, ValidationError, Result\nfrom pydantic import (\n    BaseModel,\n    ValidationError as PydanticValidationError,\n    validator,\n$\n```\n\n## Reproducible builds\n\nWhen you run `cfbs build` locally, and when your hub runs it after pulling the latest changes from git, the resulting policy sets will be identical.\n(This does not extend to providing reproducibility after running arbitrary combinations of `cfbs init`, `cfbs add` commands, etc.).\nThis gives you some assurance, that what you've tested actually matches what is running on your hub(s) and thus the rest of your machines.\nCurrently, two `masterfiles.tgz` gzipped tarballs of policy sets are not bit-by-bit identical due to file metadata (modification time, etc.).\nThe file contents themselves are (should be) identical.\nThere is also no testing of reproducible builds or checking to enforce that what you built locally and what your hub built are the same.\nWe'd like to improve all of this.\nTo see the progress in this area, take a look at this JIRA ticket:\n\nhttps://northerntech.atlassian.net/browse/CFE-4102\n\n## Available commands\n\nWe expect policy writers and module authors to use the `cfbs` tooling from the command line, when working on projects, in combination with their editor of choice, much in a similar way to `git`, `cargo`, or `npm`.\nWhen humans are running the tool in a shell, manually typing in commands, we want it to be intuitive, and have helpful prompts to make it easy to use.\nHowever, we also expect some of the commands to be run inside scripts, and as part of the code and automation which deploys your policy to your hosts.\nIn these situations, prompts are undesireable, and stability is very important (you don't want the deployment to start failing).\nFor these reasons, we've outlined 2 categories of commands below.\n\n**Note:** The 2 categories below are not strict rules.\nThey are here to communicate our development philosophy and set expectations in terms of what changes to expect (and how frequent).\nWe run both user-oriented and automation-oriented commands in automated tests as well as inside Build in Mission Portal.\n\n### User-oriented / Interactive commands\n\nThese commands are centered around a user making changes to a project (manually from the shell / command line), not a computer building/deploying it:\n\n- `cfbs add`: Add a module to the project (local files/folders, prepended with `./` are also considered modules).\n- `cfbs analyse`: Same as `cfbs analyze`.\n- `cfbs analyze`: Analyze the policy set specified by the given path.\n- `cfbs clean`: Remove modules which were added as dependencies, but are no longer needed.\n- `cfbs convert`: Initialize a new CFEngine Build project based on an existing policy set.\n- `cfbs help`: Print the help menu.\n- `cfbs info`: Print information about a module.\n- `cfbs init`: Initialize a new CFEngine Build project.\n- `cfbs input`: Enter input for a module which accepts input.\n- `cfbs remove`: Remove a module from the project.\n- `cfbs search`: Search for modules in the index.\n- `cfbs show`: Same as `cfbs info`.\n- `cfbs status`: Show the status of the current project, including name, description, and modules.\n- `cfbs update`: Update modules to newer versions.\n\nThey try to help the user with interactive prompts / menus.\nYou can always add the `--non-interactive` to skip all interactive prompts (equivalent to pressing enter to use defaults).\nIn order to improve the user experience we change the behavior of these, especially when it comes to how prompts work, how they are presented to the user, what options are available, etc.\n\n**Note:** Some of the commands above are not interactive yet, but they might be in the future.\n\n### Automation-oriented / Non-interactive commands\n\nThese commands are intended to be run as part of build systems / deployment pipelines (in addition to being run by human users):\n\n- `cfbs download`: Download all modules / dependencies for the project.\n  Modules are skipped if already downloaded.\n- `cfbs build`: Build the project, combining all the modules into 1 output policy set.\n  Download modules if necessary.\n  Should work offline if things are already downloaded (by `cfbs download`).\n- `cfbs get-input`: Get input data for a module.\n  Includes both the specification for what the module accepts as well as the user's responses.\n  Can be used on modules not yet added to project to get just the specification.\n  Empty list `[]` is returned if the module was found, but it does not accept any input.\n- `cfbs install`: Run this on a hub as root to install the policy set (copy the files from `out/masterfiles` to `/var/cfengine/masterfiles`).\n- `cfbs pretty`: Run on a JSON file to pretty-format it. (May be expanded to other formats in the future).\n- `cfbs set-input`: Set input data for a module.\n  Non-interactive version of `cfbs input`, takes the input as a JSON, validates it and stores it.\n  `cfbs set-input` and `cfbs get-input` can be thought of as ways to save and load the input file.\n  Similar to `cfbs get-input` the JSON contains both the specification (what the module accepts and how it's presented to the user) as well as the user's responses (if present).\n  Expected usage is to run `cfbs get-input` to get the JSON, and then fill out the response part and run `cfbs set-input`.\n- `cfbs validate`: Used to validate the [index JSON file](https://github.com/cfengine/build-index/blob/master/cfbs.json).\n  May be expanded to validate other files and formats in the future.\n  **Note:** If you use `cfbs validate` as part of your automation, scripts, and build systems, be aware that we might add more strict validation rules in the future, so be prepared to sometimes have it fail after upgrading the version of cfbs.\n\nThey don't have interactive prompts, you can expect fewer changes to them, and backwards compatibility is much more important than with the interactive commands above.\n\n## Environment variables\n\n`cfbs` respects the following environment variables:\n\n- `CFBS_GLOBAL_DIR`: Directory where `cfbs` stores global information, such as its cache of downloaded modules.\n  - **Default:** `~/.cfengine/cfbs/`.\n  - **Usage:** `CFBS_GLOBAL_DIR=/tmp/cfbs cfbs build`.\n  - **Note:** `cfbs` still uses the current working directory for finding and building a project (`./cfbs.json`, `./out/`, etc.).\n\nAdditionally, `cfbs` runs some commands in a shell, utilizing a few programs / shell built-ins, which may be affected by environment variables:\n\n- `git`\n- `tar`\n- `unzip`\n- `rsync`\n- `mv`\n- `cat`\n- `cd`\n- `rm`\n- Commands / scripts specified in the `run` build step.\n\n## The cfbs.json format\n\nMore advanced users and module authors may need to understand, write, or edit `cfbs.json` files.\nThe format of those files and how `cfbs` uses them is explained in detail in [JSON.md](./JSON.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcfengine%2Fcfbs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcfengine%2Fcfbs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcfengine%2Fcfbs/lists"}