PHPackages                             citomni/installer - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. citomni/installer

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

citomni/installer
=================

Deterministic scaffold materializer and lifecycle tool for CitOmni applications.

v1.0.0.0(1mo ago)011MITPHPPHP ^8.2

Since Jun 11Pushed 1mo agoCompare

[ Source](https://github.com/citomni/installer)[ Packagist](https://packagist.org/packages/citomni/installer)[ Docs](https://github.com/citomni/installer)[ GitHub Sponsors](https://github.com/LarsGMortensen)[ Fund](https://ko-fi.com/)[ RSS](/packages/citomni-installer/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (1)Versions (2)Used By (1)

CitOmni Installer
=================

[](#citomni-installer)

Official scaffold lifecycle tool for CitOmni applications.

`citomni/installer` is the package-owned scaffold materializer for the CitOmni ecosystem. It discovers scaffold manifests from installed Composer packages, renders package-owned scaffold files, writes the few files that must physically exist in the application layer, and tracks their state so future repairs and scaffold updates can be handled safely.

The package is deliberately narrow. It is not a framework runtime, not a web updater, not a Composer replacement, not a historical restore tool, and not a merge engine with a heroic cape and a questionable threat model.

In practical terms, `citomni/installer` lets CitOmni keep `citomni/app-skeleton` neutral and almost empty while allowing packages such as `citomni/http` and `citomni/cli` to own the runtime-near entrypoints and scaffold files that belong to them.

---

Highlights
----------

[](#highlights)

- **Official scaffold lifecycle tool for CitOmni** with explicit ownership of scaffold discovery, rendering, planning, status, repair, sync, and state.
- **Composer-native model** where scaffold files come from the currently installed package versions, not from live GitHub fetches or mutable remote templates.
- **Neutral app skeleton support** so `citomni/app-skeleton` can remain a thin application container instead of a pile of mode-specific runtime files.
- **Conservative write behavior** with no blind overwrites, `.new` files for blocked upstream updates, confirmation before plain forced replacement, and backups before overwriting existing files.
- **Stateful managed-file sync** using both raw stub checksums and rendered-file checksums to separate upstream scaffold drift from local changes.
- **Bootstrap-independent CLI** through `vendor/bin/citomni-installer`, without requiring `citomni/cli`, `citomni/http`, or a running CitOmni application.
- **Stable JSON output** for project tooling, CI, deploy hooks, and other automation that needs machine-readable scaffold status.

---

What this package is
--------------------

[](#what-this-package-is)

`citomni/installer` is the scaffold materialization and lifecycle package for CitOmni.

It handles the few package-owned files that cannot stay in `/vendor/` because they must exist in the application tree to function. Typical examples are an HTTP front controller such as `public/index.php` or a CLI entrypoint such as `bin/citomni`.

The package works from installed Composer packages. A package that owns scaffold declares a manifest, and `citomni/installer` uses that manifest to plan and apply safe changes in the application layer.

This keeps the ownership model mechanical and easy to reason about:

- Runtime packages own their scaffold stubs.
- The application owns its local code, root files, and configuration after project creation.
- Composer owns dependency resolution and installed package versions.
- `citomni/installer` owns the mechanics that materialize package-owned scaffold into the app.

No smoke, no mirrors, and preferably no wizard hat in production.

---

What this package provides
--------------------------

[](#what-this-package-provides)

### Scaffold discovery

[](#scaffold-discovery)

- Discovery of installed Composer packages.
- Support for scaffold manifests declared through `extra.citomni.scaffold`.
- Convention fallback to `install/manifest.php` when no explicit Composer extra value exists.
- Manifest validation, package-name validation, and manifest version validation.
- Deterministic path normalization and guard checks before any write operation.

### Scaffold materialization

[](#scaffold-materialization)

- Creation of missing scaffold files from package-owned stubs.
- Placeholder rendering using deterministic placeholder sources.
- Registration of rendered files in app-local installer state.
- Conservative handling of existing unknown files.
- Targeted package filtering through `--package=vendor/package`.

### Scaffold lifecycle commands

[](#scaffold-lifecycle-commands)

- `doctor` for read-only environment validation.
- `status` for read-only scaffold status.
- `install` for first-time package scaffold materialization.
- `repair` for recreating missing scaffold files from the currently installed package version.
- `sync` for controlled updates of managed scaffold files.

Post-MVP may add `diff` for comparing local files against the current rendered upstream version.

### Integration output

[](#integration-output)

- Human-readable CLI output by default.
- JSON output for project tooling, CI, deployment tooling, and automation.
- Stable machine-readable status and reason values for scaffold drift, missing files, local changes, and blocked sync.

---

What this package owns
----------------------

[](#what-this-package-owns)

`citomni/installer` owns the lifecycle mechanics around package-owned scaffold.

That includes:

- The `vendor/bin/citomni-installer` CLI entrypoint.
- Discovery of scaffold manifests from installed Composer packages.
- Validation of scaffold manifests, source paths, target paths, and supported manifest versions.
- Placeholder resolution and simple placeholder rendering.
- Plan-first scaffold decisions.
- Safe write behavior for scaffold targets, `.new` files, backups, and state.
- App-local scaffold state format.
- Checksum semantics for raw stubs and rendered files.
- Read-only status and doctor diagnostics.
- JSON output intended for project tooling and other automation.

This package owns the mechanism, not the application. That distinction is the whole point.

---

What this package does not own
------------------------------

[](#what-this-package-does-not-own)

`citomni/installer` is intentionally not a general application generator or updater.

It does **not** own:

- HTTP runtime behavior.
- CLI runtime behavior.
- The contents of HTTP scaffold stubs.
- The contents of CLI scaffold stubs.
- Application business code.
- Application root-level files after `composer create-project`.
- `composer.json` or `composer.lock` mutation.
- Composer dependency resolution.
- Composer `require` or `update` execution.
- GitHub repository creation.
- Deployment profiles.
- Secrets management.
- Historical restoration of previous scaffold bytes.
- Automatic merging of local modifications.
- HTTP write access to the codebase.

Those responsibilities belong elsewhere. The installer stays small because that is where most of its safety comes from.

---

Relationship to other CitOmni packages
--------------------------------------

[](#relationship-to-other-citomni-packages)

CitOmni separates project creation, dependency management, runtime packages, scaffold materialization, and project tooling into distinct layers.

Within that model:

1. `citomni/app-skeleton` provides the neutral application container.
2. Composer installs and updates packages.
3. Runtime packages such as `citomni/http` and `citomni/cli` own their own scaffold stubs.
4. `citomni/installer` materializes package-owned scaffold into the application layer.
5. External project tooling may orchestrate richer workflows around project creation, repository setup, secrets, deployment, and registration.

A minimal HTTP application can therefore start from a neutral skeleton, require `citomni/http`, and then materialize only the HTTP-owned files needed by that mode.

A minimal CLI application can do the same with `citomni/cli` without dragging a `public/` directory around like ceremonial luggage.

---

Scaffold ownership model
------------------------

[](#scaffold-ownership-model)

Package-owned scaffold should live in the package that owns the runtime function.

Examples:

```
vendor/citomni/http/install/manifest.php
vendor/citomni/http/install/scaffold/public/index.php.stub
vendor/citomni/http/install/scaffold/config/citomni_http_cfg.php.stub
vendor/citomni/http/install/scaffold/config/citomni_http_routes.php.stub

vendor/citomni/cli/install/manifest.php
vendor/citomni/cli/install/scaffold/bin/citomni.stub
vendor/citomni/cli/install/scaffold/config/citomni_cli_cfg.php.stub

```

Those stubs are the package-owned reference versions. The materialized files in the app are app-local runtime artifacts derived from those stubs.

Examples:

```
public/index.php
bin/citomni
config/citomni_http_cfg.php
config/citomni_cli_cfg.php

```

This duplication is intentional. The files have different lifecycles:

- The stub in `/vendor/` follows the installed package version.
- The materialized file in the app may be present, missing, clean, locally modified, or ready for sync.

Composer remains the source of truth for which upstream scaffold version is available.

---

Application skeleton model
--------------------------

[](#application-skeleton-model)

`citomni/app-skeleton` should stay neutral and mode-free.

It may provide the application container and base structure, such as:

```
composer.json
.gitattributes
.gitignore
.htaccess
LICENSE
NOTICE
README.md
TRADEMARKS.md
bin/
config/
language/
src/
tests/
var/

```

It should not need to include complete HTTP or CLI runtime entrypoints as permanent root-owned files.

Examples:

- `public/index.php` comes from `citomni/http`.
- `bin/citomni` comes from `citomni/cli`.
- `config/citomni_installer.php` may be added by the app to provide versioned placeholder configuration when scaffold placeholders are needed.

After `composer create-project`, root-level files are app-owned. `citomni/installer` must not rewrite the app README, `.gitignore`, `composer.json`, or `composer.lock` during normal operation.

---

Requirements
------------

[](#requirements)

- PHP **8.2+**
- Composer autoloading
- `ext-json` for JSON output

`citomni/installer` is intentionally independent of `citomni/cli` and `citomni/http`. It must be able to run before either runtime package has been installed in the application.

`citomni/kernel` is not required for the installer CLI bootstrap unless a future implementation explicitly chooses that dependency.

---

Installation
------------

[](#installation)

In a new CitOmni application, `citomni/installer` is normally installed through `citomni/app-skeleton`.

```
composer create-project citomni/app-skeleton my-app
cd my-app
```

For an existing application, install the package explicitly:

```
composer require citomni/installer
composer dump-autoload -o
```

The package provides its own CLI entrypoint:

```
vendor/bin/citomni-installer
```

No CitOmni provider registration is required for MVP usage. The installer is a CLI lifecycle tool, not a request-time runtime dependency.

---

Typical workflows
-----------------

[](#typical-workflows)

### Add HTTP support

[](#add-http-support)

```
composer require citomni/http
vendor/bin/citomni-installer install --package=citomni/http
```

If the installed scaffold uses placeholders such as `{{ CITOMNI_ENVIRONMENT }}`, provide them either through `config/citomni_installer.php` or through repeated `--placeholder=KEY=VALUE` options before running `install`.

```
vendor/bin/citomni-installer install --package=citomni/http --placeholder=CITOMNI_ENVIRONMENT=dev
```

### Add CLI support

[](#add-cli-support)

```
composer require citomni/cli
vendor/bin/citomni-installer install --package=citomni/cli
```

### Check scaffold status

[](#check-scaffold-status)

```
vendor/bin/citomni-installer status
vendor/bin/citomni-installer status --package=citomni/http
vendor/bin/citomni-installer status --format=json
```

### Update framework packages and sync scaffold

[](#update-framework-packages-and-sync-scaffold)

```
composer update citomni/http citomni/installer
vendor/bin/citomni-installer status --package=citomni/http
vendor/bin/citomni-installer sync --package=citomni/http
```

### Repair missing files

[](#repair-missing-files)

```
vendor/bin/citomni-installer repair --package=citomni/http
```

`repair` is not historical restore. It recreates missing scaffold files from the currently installed package version.

---

Composer scripts
----------------

[](#composer-scripts)

Applications may expose shorter commands through root-level Composer scripts.

Example:

```
{
	"scripts": {
		"citomni:status": "vendor/bin/citomni-installer status",
		"citomni:install": "vendor/bin/citomni-installer install",
		"citomni:sync": "vendor/bin/citomni-installer sync",
		"citomni:repair": "vendor/bin/citomni-installer repair",
		"citomni:doctor": "vendor/bin/citomni-installer doctor"
	}
}
```

Usage:

```
composer citomni:status
composer citomni:sync
```

These scripts belong to the application. `citomni/installer` must not rewrite `composer.json` to add or modify them.

Avoid wiring write-capable commands such as `sync` into automatic Composer hooks. Read-only hints are friendly. Surprise file mutation after dependency update is how a tool earns side-eye.

---

Commands
--------

[](#commands)

### `doctor`

[](#doctor)

Runs read-only validation of the application environment.

Typical checks include:

- Application root detection.
- Presence of `vendor/`.
- Readability of Composer metadata.
- Discovery of scaffold manifests.
- Write access diagnostics for relevant app paths.
- State readability and format validation where relevant.

Examples:

```
vendor/bin/citomni-installer doctor
vendor/bin/citomni-installer doctor --format=json
```

### `status`

[](#status)

Shows scaffold status without changing files.

It reports whether known scaffold targets are missing, clean, locally modified, affected by upstream stub changes, affected by placeholder changes, or blocked from automatic sync.

Examples:

```
vendor/bin/citomni-installer status
vendor/bin/citomni-installer status --package=citomni/http
vendor/bin/citomni-installer status --format=json
```

### `install`

[](#install)

Materializes scaffold for a newly installed package or runtime mode.

Default behavior:

- Creates missing files.
- Does not overwrite existing files.
- Registers created files in installer state.
- Stores checksum and placeholder metadata where relevant.
- Fails clearly on conflicts.

Example:

```
vendor/bin/citomni-installer install --package=citomni/http
```

Forced replacement:

```
vendor/bin/citomni-installer install --package=citomni/http --force
vendor/bin/citomni-installer install --package=citomni/http --force=yes
```

`--force` allows existing scaffold targets to be overwritten, but asks for interactive confirmation before writing. `--force=yes` confirms the overwrite without prompting and is intended for scripts or explicitly confirmed manual runs. Forced replacements create backups before writing.

### `repair`

[](#repair)

Recreates missing scaffold files from the currently installed package stubs.

Default behavior:

- Writes only files that are missing.
- Does not overwrite existing files.
- Uses previously registered placeholder values when state exists.
- Updates the baseline for files it recreates.
- Reports `recreated_stub_drift` when the recorded stub checksum differs from the currently installed package stub.

Example:

```
vendor/bin/citomni-installer repair --package=citomni/cli
```

### `sync`

[](#sync)

Updates managed scaffold files safely.

Default behavior:

- Creates missing scaffold files, including missing `managed` and `create-only` targets.
- Updates files that still match the previous rendered baseline.
- Does not overwrite locally modified files.
- Writes the new upstream version to `.new` when a local modification blocks automatic sync.
- Does not update existing `create-only` files by default; forced replacement requires `--force` or `--force=yes`.

Example:

```
vendor/bin/citomni-installer sync --package=citomni/http
```

Forced sync:

```
vendor/bin/citomni-installer sync public/index.php --package=citomni/http --force
vendor/bin/citomni-installer sync public/index.php --package=citomni/http --force=yes
```

`--force` replaces the existing target after interactive confirmation and writes a backup first. `--force=yes` performs the same forced replacement without prompting. A positional target limits the run to that app-relative file; without a target, the command applies to the selected package scope.

Conflict example:

```
public/index.php changed locally and was not overwritten.
New upstream version written to public/index.php.new
Review public/index.php and public/index.php.new before merging manually.

```

Post-MVP may add a `diff` command for comparing local app files against the current rendered upstream scaffold.

---

Package manifest convention
---------------------------

[](#package-manifest-convention)

Packages that provide scaffold should declare a scaffold manifest.

Composer `extra` is the primary discovery mechanism:

```
{
	"extra": {
		"citomni": {
			"scaffold": "install/manifest.php"
		}
	}
}
```

If no explicit value exists, the installer may fall back to:

```
install/manifest.php

```

If both exist and point to different paths, the Composer `extra` value wins.

The manifest's scaffold source base is normally `install/scaffold/`.

Example manifest:

```
