diff --git a/AGENTS.md b/AGENTS.md
index 2dce927..968c33c 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,3 +1,7 @@
+---
+layout: layouts/base.njk
+---
+
# AGENTS.md
## General agent guidance
diff --git a/README.md b/README.md
index e13f59f..7946395 100644
--- a/README.md
+++ b/README.md
@@ -127,546 +127,9 @@ fi
These are the main parts of every task file script.
-## Usage
+## Examples
-Running the task file requires a shell alias: `alias task='./task'`\
-Show the available commands with `task help`.\
-From the specification the project can be installed with `task install`.\
-Execute all commands with `task all`.
-
-### Image
-
-See [taskfile.build/image](./image) for details.
-
-## Naming
-
-The naming of functions is important. There are basically two styles:
-
-1. Action + Object
-2. Object + Action
-
-The task file functions use the first style. The name of the function starts with an action followed by an object. The object name can be singular or plural.
-
-**Examples for actions**: activate, install, dev, develop, init, build, start, update, remove, delete, enable, disable, template, convert, create, edit, change, get, set, patch, fetch, generate, push, pull, import, export, list, publish, release, test, setup, prepare, restart, stop, store, restore, translate, upgrade, zip, visualize, sync, switch, run, reset, load, dump, checkout, commit, drop, deploy, handle, trigger, render, lint, uninstall, split, parse, fix, refactor, transform, cat, ls, rm, serve, help, show, filter, login, logout, encrypt, decrypt, upload, download, analyse, transpile, compile, minify, copy
-
-**Examples for objects**: env, venv, submodule, container, database, snippet, model, module, repo, mail, doc, dependency, view, user, vault, file, host, node, log, password, hash, script, requirement, part, component, system, workspace, image, process, state, platform, dir, folder, readme, overview, lang, level, request, response, result, worker, server, proxy, workflow, volume, network, package, field, value, secret, chart, node, edge, function, method, firewall, html, css, image, svg, style, query, native, group, notebook
-
-**Objects can be tools**: odoo, vupress, nodejs, zsh, bash, fish, podman, kind, minikube, helm, nvim, docker, podman, rust, python, tmux, vim, helix, system, git, pass, llm, sql, dotenv, javascript, vue, vite, astro, typescript, turbo, pnpm, eslint, jenkins, k8s, nextcloud, postgres, metabase, ansible, prometheus, grafana, hugo, deno, bun, babel, panda, gulp, grunt, electron, react, express, mongodb, angular, ionic, meteor, webpack, bower, jupyter
-
-
-
-## Style
-
-The bash scripts follow the [Bash Style Guide | ysap.sh](https://style.ysap.sh/). Have a look at the [AGENTS.md](./AGENTS.md) for details on the applied styling.
-
-## Patterns
-
-The task file showed above is very basic. Commands can have parameters and call each other. The following is a collection of more complex task file patterns.
-
-### Set default parameter
-
-Fallback to a default value for a parameter.
-
-```bash
-build() {
- local platform="amd64"
- if [[ -n "$1" ]]; then
- platform="$1"
- fi
-```
-
-### Ensure parameter is not empty
-
-Check the first param and exit if it is empty.
-
-```bash
-deploy() {
- if [[ -z "$1" ]]; then echo "\$1 is empty."; exit; fi
-```
-
-### Prompt for input
-
-Use `read` to ask for inputs.
-
-```bash
-if [[ -z "$2" ]]; then
- read -p "Enter the task description: " task_description
-else
- task_description="$2"
-fi
-```
-
-### Setup local env vars
-
-Define env vars at the beginning of the task file.
-
-```bash
-CONFIGURATION_FILE="file.conf"
-GIT_BRANCH=$(git symbolic-ref --short -q HEAD)
-```
-
-### Template with env vars
-
-Create a parameterized file from a template. Requires `envsubst`.
-
-```bash
-template-with-env() {
- echo "Template $CONFIGURATION_FILE"
-
- export CONFIGURATION_1
- export CONFIGURATION_2=${CONFIGURATION_2:="value"}
-
- envsubst < "file.conf.template" > "$CONFIGURATION_FILE"
-}
-```
-
-### Create Python virtual env
-
-Initialize Python virtual env with uv.
-
-```bash
-init-venv() {
- if [[ ! -d "venv$GIT_BRANCH" ]]; then
- echo "Init venv$GIT_BRANCH with $(uv --version)."
- uv venv "venv$GIT_BRANCH"
- fi
-}
-```
-
-### Activate Python virtual env
-
-```bash
-activate-venv() {
- echo "Source virtualenv venv$GIT_BRANCH."
- source "venv$GIT_BRANCH/bin/activate"
- echo "$(python --version) is active."
-}
-```
-
-### Call a Python script
-
-Run a Python script.
-
-```bash
-generate-password-hash() {
- activate-venv
- if [[ -z "$1" ]]; then echo "\$1 is empty."; exit; fi
- export PASSWORD_PLAIN="$1"
- bin/password-hash
-}
-```
-
-The Python script: `bin/password-hash`
-
-```python
-#!/usr/bin/env python3
-
-import os
-from passlib.context import CryptContext
-crypt_context = CryptContext(schemes=['pbkdf2_sha512', 'plaintext'], deprecated=['plaintext'])
-
-password = os.environ.get('PASSWORD_PLAIN')
-print(crypt_context.hash(password))
-```
-
-### Command with named parameters
-
-Assuming you have a `docker-compose.yml` and would like to start selected or all containers.
-
-```bash
-start() {
- if [[ "$1" =~ "db" ]]; then
- docker compose up -d db
- fi
-
- if [[ "$1" =~ "admin" ]]; then
- docker compose up -d admin
- echo "Open http://localhost:8000 url in your browser."
- fi
-
- if [[ "$1" =~ "odoo" ]]; then
- docker compose up -d odoo
- echo "Open http://localhost:8069 url in your browser."
- fi
-
- if [[ "$1" =~ "mail" ]]; then
- docker compose up -d mail
- echo "Open http://localhost:8025 url in your browser."
- fi
-}
-```
-
-Start all containers with `task start` and selected with `task start db,admin`.
-
-### Run commands in container
-
-Use `docker exec -i` to run commands in a container.
-
-```bash
-drop-db() {
- local database="$1"
- if [[ -z "$database" ]]; then
- database="example"
- fi
-
- docker exec -i db psql "postgres://odoo:odoo@localhost:5432/postgres" -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$database';"
- docker exec -i db psql "postgres://odoo:odoo@localhost:5432/postgres" -c "DROP DATABASE \"$database\";"
-}
-```
-
-### Loop over files and folders
-
-Use `for` to loop over file, folders or arrays.
-
-```bash
-render() {
- echo "Update index.html for all folders"
- for folder in ./*; do
- if [[ -f "$folder/README.md" ]]; then
- cd "$folder" || exit
- md2html README.md _site/index.html
- cd .. || exit
- fi
- done
-}
-```
-
-### Parse and convert a file
-
-With this function you can split a file into multiple parts whenever a specific keyword is matching. In this example the keyword is `!vault`.
-
-```bash
-convert-vault-file() {
- local file_path="$1"
- local temp_file=$(mktemp)
- local temp_part_file=$(mktemp)
- local write_finished=false
- local current_key=""
-
- while IFS= read -r line; do
- # Check for keyword
- if [[ "$line" =~ "!vault" ]]; then
- # Process previous vault entry if it exists
- if [[ "$write_finished" = true ]] && [[ -n "$current_key" ]] && [[ -s "$temp_part_file" ]]; then
- # Decrypt part file and write to assemble file
- ansible-vault decrypt "$temp_part_file"
- local value=$(cat "$temp_part_file")
- echo "$current_key: $value" >> "$temp_file"
- fi
-
- # Set up for new vault entry
- current_key=$(echo "$line" | cut -d':' -f1)
- # Clear the file
- : > "$temp_part_file"
- # Flag as ready to write
- write_finished=true
- else
- if [[ "$write_finished" = true ]]; then
- # Pipe into part file
- echo "$line" >> "$temp_part_file"
- fi
- done
- done < "$file_path"
-
- # Process the final vault entry
- if [[ "$write_finished" = true ]] && [[ -n "$current_key" ]] && [[ -s "$temp_part_file" ]]; then
- ansible-vault decrypt "$temp_part_file"
- local value=$(cat "$temp_part_file")
- echo "$current_key: $value" >> "$temp_file"
- fi
-
- # Output assembled file
- cat "$temp_file"
- # Cleanup temp files
- rm -f "$temp_file"
- rm -f "$temp_part_file"
-}
-```
-
-### Process data
-
-This pattern tries to match the worklow of a jupyter notebook. Create a folder with the data processing scripts:
-
-```
-scripts
-├── 01_import-mail-data
-├── 02_transform-mail-data
-└── 03_export-mail-data
-```
-
-The following function lists the scripts and asks for the number of scripts to run. Every script until the entered number is concatenated and executed.
-
-```bash
-process-data() {
- while true; do
- local scripts=($(ls scripts))
-
- echo -e "Available scripts:\n"
- for index in "${!scripts[@]}"; do
- echo "$((index+1)): ${scripts[$index]}"
- done
- echo ""
- read -p "Enter the number of scripts to run (or 'q' to quit): " user_input
- if [[ "$user_input" = "q" ]]; then
- break
- fi
-
- local temp_file=$(mktemp)
- for index in "${!scripts[@]}"; do
- if (( $user_input >= $((index+1)) )); then
- cat "scripts/${scripts[$index]}" >> "$temp_file"
- echo >> "$temp_file"
- fi
- done
-
- clear
- echo -e "\nPython Output:\n\n---"
- python "$temp_file"
- local exit_code=$?
- echo -e "---\n"
- echo -e "Exit code: $exit_code\n"
- rm "$temp_file"
- done
-}
-```
-
-## Integration
-
-The task file is intended to be integrated into the shell setup. Where applications provides a domain specific language (DSL) ensure that the DSL only calls the task file.
-
-### Completion
-
-With the output of `task help` the task commands can be completed.
-
-Completion for bash: `/etc/bash_completion.d/task_completions`
-
-```bash
-#!/usr/bin/env bash
-
-_task_completions() {
- local cur prev commands
- cur="${COMP_WORDS[COMP_CWORD]}"
- prev="${COMP_WORDS[COMP_CWORD-1]}"
-
- commands=$(./task help | grep -A999 -e '---' | awk '{print $2}' | sed 's/^[[:space:]]*//' | grep -v '^$' | tr '\n' ' ')
-
- if [[ ${COMP_CWORD} == 1 ]]; then
- COMPREPLY=( $(compgen -W "${commands}" -- "${cur}") )
- elif [[ ${COMP_CWORD} == 2 ]]; then
- COMPREPLY=( $(compgen -f -- "${cur}") )
- else
- COMPREPLY=()
- fi
-}
-
-complete -F _task_completions task
-complete -F _task_completions t
-```
-
-Completion for zsh: `~/.oh-my-zsh/completions/_task`
-
-```bash
-#compdef task t
-
-_arguments '1: :->tasks' '*: :_files'
-
-case "$state" in
- tasks)
- args=$(./task help | grep -A999 -e '---' | awk '{print $2}' | sed 's/^[[:space:]]*//' | grep -v '^$' | tr '\n' ' ')
- args="$args help"
- _arguments "1:profiles:($args)"
- ;;
-esac
-```
-
-The completion also works for task alias `alias t='./task'`.
-
-### GitHub Actions
-
-Running task file commands in GitHub Actions is highly recommended. This way you can run the same CI/CD procedures in the GitHub runner as you do on your localhost.
-
-The GitHub Actions config is simple: `.github/workflows/test.yml `
-
-```yml
-on:
- pull_request:
- branches:
- - 'main'
- push:
- branches:
- - 'main'
-
-jobs:
- task-all:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
- with:
- python-version: '3.12'
- - name: Install uv
- uses: astral-sh/setup-uv@v5
- - name: Install
- run: ./task install
- - name: Lint
- run: ./task lint
-```
-
-### Jenkins
-
-Run task file commands in Jenkins: `Jenkinsfile`
-
-```groovy
-pipeline {
-
- agent any
-
- stages {
- stage('version') {
- steps {
- script {
- currentBuild.description = sh (script: 'git log -1 --pretty=%B', returnStdout: true).trim()
- }
- sh './task version'
- }
- }
- stage('install') {
- steps {
- sh './task install'
- }
- }
- stage('lint') {
- steps {
- sh './task lint'
- }
- }
- }
-}%
-```
-
-## Example
-
-This website is built with a `task` file. Here is the source:
-
-```bash
-#!/usr/bin/env bash
-set -e
-
-help-table() {
- local cmd_width=20
- local opt_width=6
- local desc_width=42
- local column="| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n"
-
- printf "$column" 'Command' 'Option' 'Description'
- echo "|$(printf '%*s' $((cmd_width + 2)) '' | tr ' ' '-')|$(printf '%*s' $((opt_width + 2)) '' | tr ' ' '-')|$(printf '%*s' $((desc_width + 2)) '' | tr ' ' '-')|"
- printf "$column" 'all' '' 'Run all tasks.'
- printf "$column" 'build-11ty' '' 'Build the 11ty website.'
- printf "$column" 'build-image' '' 'Build Docker image.'
- printf "$column" 'commit-with-llm' '' 'Commit with llm generated commit message.'
- printf "$column" 'dev-11ty' '' 'Run 11ty server.'
- printf "$column" 'help' '[grep]' 'Show help for commands.'
- printf "$column" 'install' '' 'Install node packages.'
- printf "$column" 'lint' '' 'Lint code with prettier.'
- printf "$column" 'run' '' 'Run Docker image.'
- printf "$column" 'run-tests' '' 'Test with shellcheck.'
- printf "$column" 'serve-11tyy' '' 'Serve the 11ty output folder.'
- printf "$column" 'version' '' 'Show version of required tools.'
-}
-
-help() {
- echo
- if [[ -n "$1" ]]; then
- help-table | grep -i "$1" | column -t -s'|'
- else
- echo "task [options]"
- echo
- echo "commands:"
- echo
- help-table
- fi
- echo
-}
-
-# Static vars
-
-BUILDX_PLATFORM="linux/amd64"
-CONTAINER_REGISTRY="janikvonrotz"
-CONTAINER_TAG="taskfile.build:latest"
-DOCKERFILE="image/Dockerfile"
-
-# Import commands
-
-if [[ -d "$HOME/taskfile.build/bin" ]]; then
- for file in "$HOME/taskfile.build/bin/"*; do
- if [[ -f "$file" ]]; then
- source "$file"
- fi
- done
-fi
-
-# Project commands
-
-run() {
- echo "Open http://localhost:8080 in your browser"
- docker run -p 8080:80 \
- -e GIT_URL="https://git.taskfile.build" \
- -e TASK_COMMANDS="install,build-11ty" \
- -e CADDY_ROOT="_site" \
- janikvonrotz/taskfile.build:latest
-}
-
-install() {
- pnpm install
-}
-
-dev-11ty() {
- pnpm dlx @11ty/eleventy --serve
-}
-
-lint() {
- pnpm exec prettier . --write
-}
-
-run-tests() {
- echo "Test with shellcheck."
- shellcheck task
-}
-
-build-11ty() {
- pnpm dlx @11ty/eleventy
-}
-
-serve-11ty() {
- pnpx serve ./_site
-}
-
-version() {
- echo "eleventy: $(pnpm dlx @11ty/eleventy --version)"
-}
-
-if declare -f "$1" > /dev/null; then
- "$1" "${@:2}"
-else
- case "$1" in
- all)
- install
- build-11ty
- ;;
- *)
- echo "Unknown command: $1"
- help
- exit 1
- ;;
- esac
-fi
-```
-
-Source: [janikvonrotz/taskfile.build](https://codeberg.org/janikvonrotz/taskfile.build/src/branch/main/task)
-
-### More examples
-
-More links to the implementations of the task file standard:
+Checkout these implementations of the task file standard:
- [janikvonrotz/dotfiles](https://codeberg.org/janikvonrotz/dotfiles/src/main/task)
- [janikvonrotz/python.casa](https://codeberg.org/janikvonrotz/python.casa/src/main/task)
@@ -677,218 +140,4 @@ More links to the implementations of the task file standard:
- [Mint-System/Website](https://github.com/Mint-System/Website/blob/main/task)
- [Mint-System/Wiki](https://github.com/Mint-System/Wiki/blob/main/task)
-## Library
-
-The repository of this website provides a library of reusable functions.
-
-Clone the repository into your home folder and ensure it is updated regurarly.
-
-```bash
-clone-taskfile(){
- if [[ ! -d "$HOME/taskfile.build" ]]; then
- echo -e "\033[38;5;214mGit\033[0m: Clone taskfile repo"
- git clone https://git.taskfile.build "$HOME/taskfile.build"
- else
- echo -e "\033[38;5;214mGit\033[0m: Pull taskfile repo"
- git -C "$HOME/taskfile.build" pull
- fi
-}
-```
-
-In your task file you can import these functions from the taskfile library.
-
-```bash
-if [[ -d "$HOME/taskfile.build/bin" ]; then
- for file in "$HOME/taskfile.build/bin/"*; do
- if [[ -f "$file" ]]; then
- source "$file"
- fi
- done
-fi
-```
-
-### Task
-
-For autocomplete add the command to the help table.
-
-#### init-config-dir
-
-```bash
-printf "$column" "init-config-dir" "" "Setup task file config dir."
-```
-
-#### template-dotenv
-
-```bash
-printf "$column" "template-dotenv" "" "Generate .env from .env.template."
-```
-
-### Python
-
-Set git env vars.
-
-```bash
-GIT_BRANCH=$(git symbolic-ref --short -q HEAD)
-```
-
-#### init-venv
-
-```bash
-printf "$column" "init-venv" "" "Initialize and activate Python virtual env."
-```
-
-### Environment
-
-#### create-odoo-env
-
-```bash
-printf "$column" "create-odoo-env" "[env]" "Create env file for Odoo instance."
-```
-
-#### create-nextcloud-env
-
-```bash
-printf "$column" "create-nextcloud-env" "[env]" "Create env file for Nextcloud Instance."
-```
-
-#### list-env
-
-```bash
-printf "$column" "list-env" "" "List env files."
-```
-
-#### show-env
-
-```bash
-printf "$column" "show-env" "[env]" "Output content of the env file."
-```
-
-#### copy-env
-
-```bash
-printf "$column" "copy-env" "[env][env]" "Copy env file."
-```
-
-#### edit-env
-
-```bash
-printf "$column" "edit-env" "[env]" "Open env file in default editor."
-```
-
-#### load-env
-
-```bash
-printf "$column" "load-env" "[env]" "Load and export env file."
-```
-
-#### rename-env
-
-```bash
-printf "$column" "rename-env" "[env][env]" "Rename env file."
-```
-
-#### remove-env
-
-```bash
-printf "$column" "remove-env" "[env]" "Remove environment config."
-```
-
-#### backup-env-files
-
-```bash
-printf "$column" "backup-env-files" "[path]" "Archive and copy env files to target location."
-```
-
-#### restore-env-files
-
-```bash
-printf "$column" "restore-env-files" "[path]" "Extract and copy env files from backup file."
-```
-
-### LLM
-
-#### commit-with-llm
-
-```bash
-printf "$column" "commit-with-llm" "" "Commit with llm generated commit message."
-```
-
-#### update-with-llm
-
-```bash
-printf "$column" "update-with-llm" "[glob][prompt]" "Feed files matching glob to LLM and apply changes."
-```
-
-### Git
-
-#### update-submodule
-
-```bash
-printf "$column" "update-submodule" "" "Update git submodules."
-```
-
-### Pass
-
-Set path to pass entry.
-
-```bash
-PASS_ENTRY=$(echo "env/${PWD##*/}" | tr '[:upper:]' '[:lower:]')
-```
-
-#### save-dotenv-to-pass
-
-```bash
-printf "$column" "save-dotenv-to-pass" "" "Store content of .env in pass entry."
-```
-
-#### load-dotenv=from-pass
-
-```bash
-printf "$column" "load-dotenv=from-pass" "" "Restore content to .env from pass entry."
-```
-
-### KeePass
-
-Set path to KeePass database and entry.
-
-```bash
-KEEPASS_DATABASE_FILE="/path/to/database.kdbx"
-KEEPASS_DATABASE_KEY_FILE="/path/to/keepass.key"
-KEEPASS_ENTRY=$(echo "env/${PWD##*/}" | tr '[:upper:]' '[:lower:]')
-```
-
-#### save-dotenv-to-keepass
-
-```bash
-printf "$column" "save-dotenv-to-keepass" "" "Store content of .env in KeePass entry."
-```
-
-#### load-dotenv-from-keepass
-
-```bash
-printf "$column" "load-dotenv-from-keepass" "" "Restore content to .env from KeePass entry."
-```
-
-### Docker
-
-Set Docker env vars.
-
-```bash
-BUILDX_PLATFORM="linux/amd64"
-CONTAINER_REGISTRY="janikvonrotz"
-CONTAINER_TAG="python.casa:latest"
-DOCKERFILE="image/Dockerfile"
-DOCKER_CONFIG="$HOME/.docker/$CONTAINER_REGISTRY/"
-```
-
-#### login-docker
-
-```bash
-printf "$column" "login-docker" "[user][token]" "Run Docker login and create docker config."