Directories as templates and storage layers
Updated 5 November 2026
Templates form a tree, and the tree itself is part of the description: a directory can be a template and carry the common conditions for everything inside it.
Directory as a template
The properties of a directory are described in the .calculate_directory file inside it. It is an ordinary template header: one line (or several continued with \):
/var/calculate/templates/merge/.calculate_directory
# Calculate append=skip env=install ac_install_merge==on
The directory header is inherited by all the templates inside: they need not repeat the env= or ac_* conditions if these are common. This is the main way not to bloat headers. There is a catch with path= - it works only when the directory itself takes part in the merge (without append=skip). A directory with append=skip drops out of the chain - together with its path=, so a file without its own path= ends up where the name of the remaining directory chain directs it.
Directories have the same parameters available as files, but the set is narrower: append=, path=, name=, link=, chmod=, chown=, mirror, subvolume, autoupdate, env=, module=, merge=, postmerge=, rebuild=, restart=, start=, stop=. format=, comment=, symbolic, protected, force, run=, exec= do not apply to a directory.
A directory allows append=join|remove|skip|clear, while append=replace only together with link= (see below):
- append=skip - the directory is not transferred to the system (this is usually what you need); along with it its path= does not enter the result path either;
- append=clear - clear the contents of the configuration directory;
- append=remove - remove the directory;
- append=join together with link= - transfer the contents of another directory into the created one.
link= on a directory combines only with append=join or append=replace (with replace the files of the target are deleted before copying).
Лишние директории
A directory without .calculate_directory is not an error, but there is no rule for it either: the utilities will create it in the system. If you put templates in a new subdirectory, do not forget # Calculate append=skip - otherwise, together with the configuration, a "junk" directory will appear in /etc or in the home directory, and when merging as an unprivileged user the engine will also try to change its owner. For a first-level directory in the user store /var/calculate/templates, append=skip alone is not enough: it also needs the action variable (# Calculate append=skip env=install ac_install_merge==on), otherwise the whole subtree is omitted without any message. Inside repository layers the action variable is set by the event directory, so there is no need for more than append=skip.
Naming directories: <category>/<package>
In package configuration directories (N_ac_install_merge, N_ac_install_unmerge, N_ac_install_patch, …) the structure must match the package:
2_ac_install_merge/
└── sys-libs/
└── ncurses-6.1/
├── .calculate_directory
└── ncurses.sh
The name of the package directory defines the package the template is bound to: the merge(), mergepkg(), pkg() functions without arguments take the category and the package name from the path, dropping sorting prefixes and versions (05-, -4.6). A version present in the name is a way to tie the template to a range of versions.
Storage layers and priority
Templates live in several "layers", and the layer names correspond to the connected repositories. On a real system this looks like:
/usr/libexec/calculate/cl-variable --value cl_template_data
calculate:/var/db/repos/calculate/profiles/templates,distros:/var/db/repos/distros/profiles/templates,local:/var/calculate/templates,remote:/var/calculate/remote/templates
- Repository layers (calculate, distros, …) are the profiles/templates directories of the connected repositories. The distribution creates and updates them: they must not be edited, at the next sync the changes will disappear.
- local - /var/calculate/templates, the user layer. This is where you put your own templates.
- remote - /var/calculate/remote/templates: templates received from a Calculate server (used in the domain configuration).
- clt - override templates lying next to the file being configured in /etc, with the .clt extension.
A template that ends up in two layers with the same address (path + + name + + link) wins by layer priority: the user layer overrides the repository, so you can override a system template without touching the file itself.
At configuration time you choose which layers take part with the -T/--templates parameter:
cl-core-setup -n baselayout -T calculate,distros,local
The possible values are fixed: calculate, distros, local, remote, clt and none. These are not the names of just any connected repositories: the gentoo repository is also connected, but as a template layer it does not exist, and the utility rejects -T gentoo. For user profile configuration the clt layer does not take part.
Order inside the tree
First-level directories set the action by their header, not by their name: an ac_* variable (or cl_name==) must be present in the .calculate_directory of that level, otherwise the subtree is omitted without any message. The N_ac_[HTML_REMOVED] convention serves a different purpose: directories are traversed in lexicographic order, so the digit at the start of a name sets the merge sequence and does not take part in choosing the action. Inside an event the same order works for files too: numeric prefixes (05-rebuild_openrc) are a way to set the sequence, not part of the package name. What actions exist and who enables them - in Who merges templates and when.
If one file needs several edits from different places, you can spread them over files sorted by name: they will be applied in alphabetical order within one directory.
The tool that writes templates itself: cl-kernel
Almost all utilities only merge templates. cl-kernel (the sys-apps/calculate-toolkit package, a bash script installed to /usr/sbin/cl-kernel) does both: it builds the kernel and turns your configuration changes into an ordinary template in the user store - /var/calculate/templates/kernel/.
How it works:
- on first run /var/calculate/templates/kernel/.calculate_directory is created with the header
# Calculate env=install ac_install_patch==on append=skip- the action variable of a first-level directory plus append=skip, so that the directory itself does not appear in the system; - the template name is built from the kernel series:
10-config-<architecture>-<MAJOR.MINOR>(for packages of the form*-sources-10-<name>-<architecture>-<MAJOR.MINOR>), so the binding applies to one specific version and does not interfere with the others; - the template header carries the format and the binding:
# Calculate format=kernel name=.config os_install_arch_machine==<architecture>&&merge(<category>/<package>)>=<version>; - the template content is only the difference between the base configuration (
make defconfig, already with the templates merged) and what you got: added options as a listCONFIG_…=…, removed ones with!before the name. The kernel format merges, it does not rewrite: options that the template does not contain stay in the file as they were; - the previous template of the same series is not deleted but moves to /var/calculate/templates/kernel/backup with the header
# Calculate cl_action==skip- it stays at hand and at the same time is not merged.
The benefit is that kernel configuration stops being part of one built system. The template outlives reinstalling the package, a series update and a rebuild: each time it is merged into a fresh base configuration. The final .config is obtained the same way by cl-kernel itself: it calls cl-core --method core_patch with --pkg-name, --pkg-category, --pkg-version and a --pkg-path pointing to a duplicate directory where the base .config lies - without building the kernel. If you run this pass by hand for another package, check that it has any ac_install_patch action templates at all: otherwise the duplicate directory will stay empty, and this is not an error but the absence of suitable templates. The general way to see the result in advance is in template preview.
To move the binding to other machines, the kernel directory is put into an overlay (profiles/templates/kernel/) and distributed as a package: then identical kernels on different machines are built from the same set of templates. Read the reference for the utility itself on the kernel page, and the sources in calculate-toolkit.
See also
- Template syntax - header parameters.
- Life of a file after its template - who the created file belongs to.
- The template was not applied and said nothing - where to see which layer takes part.