{"id":21296860,"url":"https://github.com/reddec/layout","last_synced_at":"2025-07-11T17:32:02.083Z","repository":{"id":57704092,"uuid":"488139163","full_name":"reddec/layout","owner":"reddec","description":"Generate new project from layout. Supports typed user-input, hooks, and conditions.","archived":false,"fork":false,"pushed_at":"2024-08-26T02:00:06.000Z","size":163,"stargazers_count":33,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-02T11:02:01.422Z","etag":null,"topics":["cookiecutter","layout","project-bootstrapping","project-generator"],"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/reddec.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}},"created_at":"2022-05-03T08:57:27.000Z","updated_at":"2025-03-14T14:42:47.000Z","dependencies_parsed_at":"2024-06-19T11:24:27.297Z","dependency_job_id":"4ed1f6b4-bb90-4081-a4b7-c9eef23da38a","html_url":"https://github.com/reddec/layout","commit_stats":null,"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/reddec/layout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Flayout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Flayout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Flayout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Flayout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reddec","download_url":"https://codeload.github.com/reddec/layout/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Flayout/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264862468,"owners_count":23674979,"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":["cookiecutter","layout","project-bootstrapping","project-generator"],"created_at":"2024-11-21T14:30:12.529Z","updated_at":"2025-07-11T17:32:01.792Z","avatar_url":"https://github.com/reddec.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Layout\n\nGenerate new project from layout. Supports typed user-input, hooks, and conditions.\n\nInspired by  [cookiecutter](https://github.com/cookiecutter/cookiecutter), [yeoman](https://yeoman.io), and Ansible.\n\nYou may think about it as cookicutter-ng or modern cookiecutter.\n\n## Very quick demo\n\n`layout new reddec/layout-example my-example`\n\nWill ask you questions and generate hello-world HTML page based on your answers.\n\n[![asciicast](https://user-images.githubusercontent.com/6597086/166427829-320fefc2-7131-46a3-85e8-655f5069c2a2.gif)](https://asciinema.org/a/zDPT7o2sbxOjPHoNd5z0qnxvG)\n\n## Installation\n\n- **Pre-build binary**: prepared for most OS in [releases](https://github.com/reddec/layout/releases).\n- **DEB/RPM/APK packages**:  in [releases](https://github.com/reddec/layout/releases).\n- **From source**: requires Go 1.18+, `go install github.com/reddec/layout/cmd/...@latest`\n- **Brew**: `brew install reddec/tap/layout`\n- **Docker**: (supports amd64 and arm64)\n    - `ghcr.io/reddec/layout:latest`\n    - `ghcr.io/reddec/layout:\u003cversion\u003e`\n\nNote 1: Docker image built from `scratch` and not very useful by itself. Intended to be used as part of multi-stage\nDocker build.\n\nNote 2: During cloning from GitHub you may observe SSH-key related error, which usually happens because of GitHub key\nrotation. It could be fixed by `ssh-keyscan github.com  \u003e\u003e ~/.ssh/known_hosts`\n\n## Motivation\n\nHeavily inspired by [cookiecutter](https://github.com/cookiecutter/cookiecutter) and [yeoman](https://yeoman.io),\nhowever layout offers additional features and bonuses:\n\n- single binary without runtime dependencies, compiled for all major OS\n- supports boolean variables ([yikes, cookicutter!](https://github.com/cookiecutter/cookiecutter/issues/126))\n- supports conditional\n  variables ([cookiecutter, I am again pointing to you](https://github.com/cookiecutter/cookiecutter/issues/1438))\n- supports plain includes and conditional includes (inspired by Ansible)\n- supports (and validates): string, boolean, list of strings, integer, float\n- supports versioning in case you want to lock specific version of `layout`\n- supports file source and remote Git repository (even without `git` installed!)\n- supports multiple inline hooks (with portable shell) and templated hooks\n- hooks also supports condition :-)\n- supports normal labeling for variables input (cookiecuter...)\n- supports multiple layout in one repo\n- supports `.layout.yaml` overlay file in current directory for re-using organization-wide configuration per directory\n\nI generally do not like competing with other open-source projects but this time\nI would like to say that this project is aiming to fix legacy cookiecutter's problems\nand keep the best of three worlds (including yeoman and Go).\n\nThe utility is designed to be completely universal not just in terms of supported languages\nand approaches, but also in terms of operational experience and can be used in restricted (limited to no-access to\ninternet) environment with the same convenience as in public.\n\nThis project stands on open-source atlantis shoulders:\n\n- [MVDan's protable shell](https://mvdan.cc/sh/) which allows writing inline shell script regardless of OS\n- [Tengo language](https://github.com/d5/tengo) which provides complete, simple and fast language for conditions\n- [Go-git](https://github.com/go-git/go-git) which is basically embedded go-native Git client\n- [Survey](https://github.com/AlecAivazis/survey) provides fancy terminal UI\n- [Masterminds](https://github.com/Masterminds) for supporting tools\n\n... and many many others. I love open-source, and this project is one of my little contributions.\nThat's why [license](LICENSE) for the project is Apache 2.0 which means that you may use code as you wish but please\nstate any changes (for legal details please read LICENSE file).\n\n## Documentation\n\n- Use GitHub navigation on top of README, or use search-on-page functionality in your viewer\n- Use `layout new --help` command to check usage\n\n### CLI usage\n\n#### General\n\n    Usage:\n    layout [OPTIONS] \u003cnew | show\u003e\n    \n    Create new project based on layout\n    Author: Aleksandr Baryshnikov \u003cowner@reddec.net\u003e\n    \n    Help Options:\n    -h, --help  Show this help message\n    \n    Available commands:\n    new   deploy layout\n    show  show configuration\n\n#### show\n\n    Usage:\n    layout [OPTIONS] show \u003cconfig | config-file\u003e\n    \n    Help Options:\n    -h, --help      Show this help message\n    \n    Available commands:\n    config       current config\n    config-file  location of default config file\n\n#### new\n\n    Usage:\n    layout [OPTIONS] new [new-OPTIONS] [source] [destination]\n\n    Help Options:\n    -h, --help                       Show this help message\n    \n    [new command options]\n        --version=                   Override binary version to bypass manifest restriction [$LAYOUT_VERSION]\n    -c, --config=                    Path to configuration file, use show config command to locate default location [$LAYOUT_CONFIG]\n    -u, --ui=[nice|simple]           UI mode (default: nice) [$LAYOUT_UI]\n    -d, --debug                      Enable debug mode [$LAYOUT_DEBUG]\n    -a, --ask-once                   Do not retry on wrong user input, good for automation [$LAYOUT_ASK_ONCE]\n    -D, --disable-cleanup            Disable removing created dirs in case of failure [$LAYOUT_DISABLE_CLEANUP]\n    -g, --git=[auto|native|embedded] Git client (default: auto) [$LAYOUT_GIT]\n\n* `-g,--git` (v1.2.0+) specifies git client which should be used:\n    * `native` use native Git binary (must be 2.13+)\n    * `embedded` use Golang native git client (safe mode)\n    * `auto` (default, but it can be changed in [configuration](#configuration)) in case git installed (`git` binary\n      accessible) and git version is 2.13 or higher `native` will be used, otherwise `embedded`\n\n* (v1.4.0+) if `source` is not set, const of `.layout` file in the current dir will be used for URL\n* (v1.4.0+) if `destination` is not set, the `default` URL from config will be set\n\nSince 1.4.0 it's possible to run just `layout new`.\n\n##### set\n\nSince v1.3.1\n\n    Usage:\n    layout [OPTIONS] set \u003cdefault | git\u003e\n    \n    Help Options:\n    -h, --help      Show this help message\n    \n    Available commands:\n    default  URL pattern to resolve layout\n    git      git client mode\n\n### Architecture\n\n```mermaid\nsequenceDiagram\n    User-\u003e\u003elayout: new \u003crepo\u003e \u003cdestination\u003e \n    layout-\u003e\u003erepo: fetch recursively, depth 1\n    repo-\u003e\u003elayout: data\n    layout-\u003e\u003eUser: display questions\n    layout-\u003e\u003edestination: copy and render content, execute hooks\n```\n\nLet's describe basic example.\nAssume we made demo repository as layout which located in `https://github.com/reddec/layout-example`.\n\nOnce you executes `layout new https://github.com/reddec/layout-example my-example`:\n\n1. `layout` goes to server which hosts repository (`github.com`) by desired protocol (`https`) and asks for content of\n   repository `layout-example` owned by `reddec`.\n2. (optionally) `layout` negotiates authorization protocols being aware of configuration in `.gitconfig`\n3. `layout`  makes shallow (depth 1) clone of repo to a temporary directory\n4. `layout` reads `layout.yaml` and asks questions from user\n5. `layout` creates destination directory (`my-example`) and copies data from `content` directory from cloned repo as-is\n6. `layout` executes `before` hooks\n7. `layout` renders file names and removes files and directories with empty names\n8. `layout` renders content of files except marked as ignored in `ignore` section\n9. `layout` executes `after` hooks\n10. done\n\n\u003e In reality, `layout` will first try to resolve URL as local directory, as abbreviation,\n\u003e and only at last it will decide go to remote URL\n\nBy default, for GitHub repositories host and protocol not needed. For example, instead\nof `layout new https://github.com/reddec/layout-example my-example` we can\nuse `layout new reddec/layout-example my-example`.\nSee [configuration](#configuration) for details.\n\n### Layout structure\n\nOnce repository fetched, `layout` will scan directories with `layout.yaml` files. Each directory with such file will\nbe marked as project directory.\n\nIn case there is only one project directory, then it will be automatically picked. Otherwise, user will be prompted to\npick desired project (based on `title` field).\n\nEach project directory should contain:\n\n- `layout.yaml` - main manifest file\n- `content` - content directory which will be copied to the destination\n\nValid repo structure:\n\n**one repo - one layout**:\n\n```\n/\n├── layout.yaml\n└── content\n```\n\n**one repo - many layouts** (v1.3.0+):\n\n```\n/\n├── foo\n│    └── layoutA\n│         ├── layout.yaml\n│         └── content\n└── layoutB\n    ├── layout.yaml\n    └── content\n```\n\n### Manifest\n\nCheck examples in:\n\n- https://github.com.com/reddec/layout-example\n- [test data](test-data) directory\n\n**absolute minimal example of manifest:**\n\n```yaml\n{ }\n```\n\nYes, empty object is valid manifest.\n\n**'hello world' example of manifest:**\n\n```yaml\nprompts:\n  - var: name\nafter:\n  - run: \"echo 'Hello, {{.name}}!' | wall\"\n```\n\n(*nix only, should broadcast message `Hello, \u003cyourname\u003e!`)\n\n#### Version\n\nLayout manifest supports constraints of applied layout binary version based on [semver](github.com/Masterminds/semver).\n\nIn case `version` is not specified, all versions of `layout` are allowed.\n\nFor now, I suggest pinning major version only: `~1`. `layout` is following semantic version and all version withing\none major version are backward compatible (manifest designed for `1.0.0` will work normally even in `layout`\nversion `1.9.5`, but without guarantees for `2.0.0`).\n\n#### Title and Description\n\nThere are two informational field in manifest:\n\n* `title` - short description about layout. Only title will be shown to user in case of selecting manifest in\n  multi-project repo\n* `description` - full project description\n\nBoth title and description will be shown before prompts.\n\n#### Delimiters\n\nTemplate delimiters could be overridden by in `delimiters` section. Defaults are `{{` (open), `}}` (close).\nCould be useful in case you are trying to render Go templates.\n\nExample:\n\n```yaml\n# ...\ndelimiters:\n  open: '[['\n  close: ']]'\n# ...\ncomputed:\n  - var: foo\n    value: \"[[.dirname]]\"\n# ...\n```\n\n#### Prompts\n\nPrompts are list of variables which should be asked from user.\nMinimal required field is `var: \u003cname\u003e` which unique identifies provided value\nand could be used in conditions and templates later.\n\n* `label` is used as a question which will shown to user. If not set - `var` name will be used as-is\n* `type` variable type, default is `str`. If user input can not be casted to desired type, user will be asked again (\n  unless `-a/--ask-once` provided). Supported types:\n    * `str` - user input as-is (space trimmed)\n    * `int` - user input should be 10-base 64-bit integer\n    * `float` - user input should be 10-base 64-bit float\n    * `bool` - `true` if user input (case insensitive) is `t`, `y`, `yes`, `true`, or `ok`; otherwise `false`\n    * `list` - list of strings. If options are not provided, values are comma-separated\n* `default` - default suggested value. Since v1.3.0 it can be an array, which is useful when you want to pick multiple\n  default values for `type: list`\n* `options` - allows user select single option (not `type: list`) or multiple options (type: `list`)\n* `when` - condition written in  [tengo language](https://github.com/d5/tengo) which should return boolean;\n  default `true`. Variable will not be defined (use [defaults](#defaults) if needed) and prompt will not be rendered or\n  executed if condition returned false.\n\nExample:\n\n```yaml\n# ...\nprompts:\n  # cast to integer\n  - var: age\n    label: What is your age\n    type: int\n  # conditional\n  - var: tin\n    label: What is your TIN\n    when: age \u003e 18\n  # select one\n  - var: degree\n    label: What is your highest degree\n    options:\n      - Elementary school\n      - High-School\n      - Bachelor\n      - Magister\n      - PhD\n  # select many\n  - var: source_of_income\n    label: Source of income\n    type: list\n    options:\n      - employed\n      - self-employed\n      - business\n# ...\n```\n\n#### Includes\n\n`include` is a special instruction within [`prompts`](#prompts) which loads separate yaml\nfile, relative to the current, with list of another prompts.\n\nUsed as a convenient method to group questions blocks.\n\nExample:\n\n_layout.yaml_\n\n```yaml\n# ...\nprompts:\n  - var: age\n    label: What is your age\n    type: int\n\n  - include: adult.yaml\n    when: age \u003e 18\n# ...\n```\n\n_adult.yaml_\n\n```yaml\n- var: tin\n  label: What is your TIN\n\n- var: degree\n  label: What is your highest degree\n  options:\n    - Elementary school\n    - High-School\n    - Bachelor\n    - Magister\n    - PhD\n\n- var: source_of_income\n  label: Source of income\n  type: list\n  options:\n    - employed\n    - self-employed\n    - business\n```\n\n#### Computed\n\nThe `computed:` invoked after user input and can contain conditions.\nMost often it could be useful for defining re-usable variable which depends on user-input. For example:\n\n```yaml\nprompts:\n  - var: owner\n  - var: repo\ncomputed:\n  - var: github_url\n    value: \"https://github.com/{{.owner}}/{{.repo}}\"\n```\n\n**Note**: in case variable `value` is string, then content of the field will be rendered as template. Otherwise, it will\nbe used as-is.\n\n```yaml\nprompts:\n  - var: owner\n  - var: repo\ncomputed:\n  - var: options\n    value:\n      - 1234\n      - \"option {{.repo}}\" # \u003c-- will be used as-is with brackets since value content is array, not string\n```\n\n#### Defaults\n\nThe `default:` section is similar to `computed`, however, invoked before user input and can not contain conditions.\nMost often it could be useful together with conditional include to prevent excluded variables be undefined in\nexpressions.\n\nExample:\n\n_layout.yaml_\n\n```yaml\nprompts:\n  - var: ask_name\n    type: bool\n  - include: name.yaml\n    when: ask_name\nafter:\n  - run: echo Hello {{.name}}\n    when: name != \"\"\n```\n\n_name.yaml_\n\n```yaml\n- var: name\n```\n\nIn case `ask_name` set to `false` the hook **will fail** because in hook condition `name != \"\"` used undefined variable.\n\nTo fix it, you may update manifest with defaults variables:\n\n_layout.yaml_\n\n```yaml\ndefault:\n  - var: name\n    value: \"\"\nprompts:\n  - var: ask_name\n    type: bool\n  - include: name.yaml\n    when: ask_name\nafter:\n  - run: echo Hello {{.name}}\n    when: name != \"\"\n```\n\nRules of rendering value in `default` section is the same as in [`computed`](#computed).\n\nDefaults also can be defined globally in [configuration](#configuration). Optionally, to make layout portable you may\nuse template in default section.\n\n_$XDG_CONFIG_HOME/layout/layout.yaml_\n\n```yaml\nvalues:\n  country: Global\n```\n\n_layout.yaml_\n\n```yaml\ndefault:\n  - var: country\n    value: '{{with .country}}{{.}}{{else}}my-default-country{{end}}'\n```\n\n#### Ignore\n\nIgnore list allows you define list of [glob](https://pkg.go.dev/path/filepath#Glob) patterns of paths which should not\nbe rendered as template.\n\nExample:\n\n```yaml\nignore:\n  - \"**/*.css\" # do not treat as template CSS files\n```\n\n#### Hooks\n\nHooks can be defined through inline portable shell or through templated script.\n\n* `before` hooks executed with resolved state (after user input and computed variables), before rendering paths and\n  content\n* `after` hooks executed after content rendered\n\nOptionally, a `label` could be defined to show human-friendly text during execution.\n\nWorking directory for script and inline always inside destination directory. For script invocation, path to script is\nrelative to layout content.\n\nExample:\n\n```yaml\n#...\nbefore:\n  # inline script\n  - label: Save current date\n    run: date \u003e created.txt\nafter:\n  # file script\n  - label: Say hello\n    script: hooks/hello.sh \"{{.dirname}}\"\n#...\n```\n\nContent of `hooks/hello.sh` could be (`foo` should be defined):\n\n```shell\n#!/bin/sh\n\nwall Hello \"{{.foo}}\" \"$1\"\n```\n\n### Rendering\n\nBy-default, all files in `content` directory treated as [golang template](https://pkg.go.dev/text/template), unless some\npaths added to [`ignore`](#ignore) section.\n\nAll defined variables are accessible in a root context: `var: foo` is available as `{{.foo}}`\n\nAdditional \"magic\" vairables:\n\n- `dirname` (usage: `{{.dirname}}`) - base name of destination directory, commonly used as project name\n\n#### Functions\n\n* [Sprig template utilities](http://masterminds.github.io/sprig/) available.\n    * Custom functions:\n        * `getRootFile` (v1.2.1+) - (`{{getRootFile \"myfile\"}}`) get content of file with specific name in any of root\n          folders. Example:\n\n               Current working directory: /foo/bar/xyz\n               Looking for name: .gitignore\n               Will check (and return content):\n                  /foo/bar/xyz/.gitignore\n                  /foo/bar/.gitignore\n                  /foo/.gitignore\n                  /.gitignore\n\n          If nothing found - `ErrNotExists` returned\n        * `findRootFile` (v1.3.2+) - (`{{findRootFile \"myfile\"}}`) find path to file with specific name in any of root\n          folders. Same as `getRootFile` but instead of returning content it is returning path to file.\n        * `findRootDir` (v1.3.2+) - (`{{findRootDir \"mydir\"}}`) find path to directory with specific name in any of root\n          folders. Same as `findRootFile` but instead of looking for file it is looking for directory.\n        * `findSubmatch` (v1.3.3+) - capture all regex groups with matching pattern. Example:\n\n               Pattern: foo[ ]+([^ ]+)\n               Text: foo bar foo baz\n               Returns: [bar, baz]\n\n#### Flow\n\nIn manifest, the following items also renders just before usage:\n\n- in [prompts](#prompts)\n    - label\n    - include\n    - default\n    - options\n- in [computed](#computed)\n    - value (if string)\n- in [defaults](#defaults)\n    - value (if string)\n- in [hooks](#hooks)\n    - run\n    - script\n\nDirectories and file names can contain templates too. Ex: `content/src/{{.project}}/main-{{.foo}}.go`.\n\nIn case path segment rendered to an empty string, the segment will be removed (mimics cookiecutter behaviour).\n\n### Condition expression\n\nStatement written in [tengo language](https://github.com/d5/tengo) which should return boolean.\n\nCan be used in:\n\n- [prompts](#prompts) and [includes](#includes)\n- [computed](#computed)\n- [hooks](#hooks)\n\nHelpers:\n\n- `has(seq, opt) -\u003e bool` returns true if `seq` contains value `opt`. Mostly used for checking selected options (\n  type: `list`)\n\nExample:\n\n```yaml\n# ...\nprompts:\n  - var: features\n    options:\n      - http\n      - ui\n      - js\n    type: list\n\n  - include: http.yaml\n    when: 'has(features, \"http\")'\n# ...\n```\n\n### Configuration\n\nThe global configuration file defines user-wide settings such as:\n\n* abbreviations\n* default repository template\n* global default variables\n\nIf `--config, -c` not provided, the global configuration file will be used which is located\nunder `\u003cuser config dir\u003e/layout/layout.yaml`.\nYou may check actual location by command `layout show config-file`.\n\nSpecifically:\n\n* On Unix systems, `$XDG_CONFIG_HOME/layout/layout.yaml` or `$HOME/.config` (if `$XDG_CONFIG_HOME` not set).\n* On Darwin (Mac), `$HOME/Library/Application Support/layout/layout.yaml`\n* On Windows, `%AppData%/layout/layout.yaml`\n* On Plan 9, `$home/lib/layout/layout.yaml`\n\nCurrently, it supports:\n\n* `abbreviations`: map of string -\u003e template values where key is repo shorthand and template is string with `{0}`\n  which will be replaced to the repo details. You may use abbreviations as `\u003cabbr\u003e:\u003cowner\u003e/\u003crepo\u003e`\n* `default`: template for repository without shorthand, default (if not set) is `git@github.com:{0}.git`.\n* `values`: (v1.2.0+) map of anything where key as name and value is default value (any valid YAML type)\n* `git`: (v1.3.1+) preferred git mode (same as in [cli](#new)): `auto` (default), `native`, `embedded`\n\n\u003e Hint: you may use air-gap deployment in case you stored bare repository somewhere locally.\n\nSince v1.4.0 it's possible to define overlay in the current directory `.layout.yaml`. Content from this file will\nbe merged on top of global config.\n\nExample:\n\n```yaml\ndefault: \"git@gitlab.com:{0}.git\" # sets default repo to GitLab instead of GitHub. Could be used as some-owner/some-repo\nabbreviations:\n  ex: \"ssh://git@git.example.com/{0}.git\" # could be used as ex:some-owner/some-repo\nvalues:\n  author: RedDec\n  organization: myself\n```\n\nCheck [roadmap](#roadmap) for upcoming features.\n\n## UI\n\nCurrently, layout provide two terminal UI:\n\n- `nice` (default) - colored, interactive UI, backed by [Survey](https://github.com/AlecAivazis/survey)\n- `simple` - plain STDIN/STDOUT UI, which can be useful for automation or for basic terminals\n\nYou may pick UI kind for `new` [command](#new) by flag `--ui \u003ckind\u003e` or `-u \u003ckind\u003e`.\n\nFor example, to use simple UI: `layout new -u simple reddec/layout-example my-example`.\n\n## Automation\n\n`layout` supports naive automation where input variables are fed through STDIN.\nUse `layout new -u simple -a \u003crepo\u003e \u003cdir\u003e` to simplify integration with another tools:\n\n- `-u simple` disables interactive [colorful UI](#ui)\n- `-a` enables mode \"ask once\" for `new` [command](#new) which disables retry-loop in case of malformed user input\n\n## Security and privacy\n\n**Privacy**: we (authors of layout) do not collect, process or transmit anything related to your activities to our or\nthird-party servers with one exception.\nException is the moment when you are cloning remote repository: we are not responsible for data leakage or tracking\nactivities from repo owner. We are using standard git protocol (via [go-git](https://github.com/go-git/go-git)) which\nrequires some \"trust\" to remote repository, however, this warning is not specific to only `layout`. Just be careful what\nand from where you are cloning (see below).\n\n**Security** is a bit bigger problem due to nature of idea behind the `layout`: hooks defined in manifest could\npotentially do anything in computer limited by the running user permissions. There is no universal solutions for the\nproblem, however:\n\n- (suggested) clone only from trusted repo\n- (paranoid) execute layout in minimal sandbox environment such as docker or kvm and copy result data to the host.\n\nAnyway: running `layout` under `root` privileges is a TERRIBLE IDEA, you should never do it.\n\nSee [roadmap](#roadmap) for planning related features.\n\n## Roadmap\n\n- Security\n    - clone by commit digest\n    - disable hooks during cloning, however, it may break all idea of `layout`\n- UX\n    - global before/after hooks\n    - globally disable hooks\n    - compute variables by script\n    - support `.layout` file in working path\n    - support `include` in before/after hooks\n- Delivery\n    - apt repository\n    - Arch AUR\n- Long term ideas\n    - GUI for prompts (maybe)\n    - Decentralized marketplaces/discovery repositories\n\n## Contributing\n\nPR/Issues/Feedback always welcome.\n\n### Rules\n\n- Be professional and avoid personal conflicts. I strongly believe that FOSS still can be a cross-broder collaboration\n  regardless of politics (at least we can try).\n- No CLA (contributor license agreement), no corporate bullshit - once your code is merged it's available for everyone\n  under Apache 2.0 license\n    - Do not forget to add or update Apache 2.0 header in code!\n- No one is perfect, if you have an idea/draft of code - make draft PR and let's talk about how to improve it. If you\n  can -\n  help others to complete their ideas\n- Do not demand from volunteers immediate reaction. If you want to prioritize your problem - motivate them (for example:\n  contact me directly) by donation or by any other form\n\n### Flow\n\n- Standard GitHub flow:\n    - fork\n    - make PR (draft PRs are not reviewed)\n    - ask for review -\u003e fix problems -\u003e ask review (loop)\n    - done! (PR merged)\n\nDo not hesitate to ping maintainers again and again. Maintainers are busy and your review request may sink under\nothers problems.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freddec%2Flayout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freddec%2Flayout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freddec%2Flayout/lists"}