Files
development-scripts-3darch/references/module-patterns.md
T
oleg-lukasonokandClaude Opus 5 31a5408a6c Add development-scripts agent skill
Ports generic-scripts-module-v1 into a routed skill: module anatomy, shared
loggers/base modules, Taskfile integration, workflows, and pattern decisions.

Fixes a latent defect in the loggers example that silenced all logging in the
module scaffold: loggers/lib/--index-api.sh now sources --env-vars-reader.sh,
and the reader preserves already-exported values so caller overrides still win.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 22:18:55 +03:00

2.8 KiB

Module Patterns

A decision guide for what kind of module you are building and how it should connect to the others.


1. Module type

Module type Has api/ Has Taskfile.yml Example
Support-only library No No loggers
Shared foundation with public commands Yes Optional / no base
Feature module Yes Usually yes kube, github, data-migration
Wrapper around an external CLI Yes Usually yes helm, openshift, github

Pick the type before creating any file — it decides whether api/ and Taskfile.yml exist at all, and adding them later means reworking every consumer that has already started sourcing the module.

A module with no user-facing command is a support library. Do not give it an api/ directory speculatively; every file in api/ is a public interface someone may come to depend on.


2. Dependency sourcing

You need Source
Logging ./.scripts/loggers/lib/--index-api.sh
Shared base functions ./.scripts/base/lib/--index-api.sh
Another module's exported functions that module's lib/--index-api.sh
Your own module's full runtime, from its api/ wrapper your lib/--index.sh

The rule underneath: --index-api.sh is the public edge between modules; --index.sh is a module's own private entrypoint. Sourcing another module's --index.sh runs its reader and validator inside your command — importing its defaults, its required-input checks, and in base's case its .env loading. Symptoms show up as variables nobody set, or a validation failure naming a module the user never invoked.


3. Command exposure

Three independent decisions, in increasing order of commitment:

  1. lib/ only — internal. Reachable from other modules that source your --index-api.sh.
  2. api/<command>.sh — user-facing. Someone can run it directly from the repository root.
  3. Module Taskfile.yml — discoverable through task --list-all.
  4. Root Taskfile.yml include — a stable public namespace, effectively permanent.

Escalate only as far as the command genuinely needs. Each step is easy to add later and disruptive to withdraw, because each one is a promise someone may already be relying on.


4. Common mistakes

  • Putting full implementation logic into api/*.sh.
  • Adding a lib/-*.sh file and forgetting to source it from lib/--index-api.sh.
  • Parsing CLI flags in implementation files instead of --env-vars-reader.sh.
  • Printing secrets in logs.
  • Sourcing base/lib/--index.sh from a library function and unexpectedly loading .env.
  • Adding root Taskfile includes for experimental modules.
  • Giving a support-only library an api/ directory it does not need.
  • Mixing function prefixes inside one module after a rename.