https://github.com/coyotito-mx/package-skeleton-cli
Companion CLI for COYOTITO's packages skeletons
https://github.com/coyotito-mx/package-skeleton-cli
cli package-skeleton package-skeleton-cli
Last synced: 3 months ago
JSON representation
Companion CLI for COYOTITO's packages skeletons
- Host: GitHub
- URL: https://github.com/coyotito-mx/package-skeleton-cli
- Owner: coyotito-mx
- Created: 2025-02-15T00:55:12.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-10-27T23:19:04.000Z (8 months ago)
- Last Synced: 2025-10-28T01:10:22.258Z (8 months ago)
- Topics: cli, package-skeleton, package-skeleton-cli
- Language: PHP
- Homepage: https://coyotito.com.mx
- Size: 183 KB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# Package Skeleton CLI



The **Package Skeleton CLI** is a command-line interface that allows you to initialize a PHP package skeleton by replacing placeholders in files with the values you provide.
## Installation
> ⚠️
> The CLI currently works **only** on **macOS** with ARM architecture.
### Downloading the CLI
Using **cURL**:
```bash
curl -L "https://github.com/coyotito-mx/package-skeleton-cli/releases/latest/download/skeleton.tar.gz" -o skeleton.tar.gz
tar -xzf skeleton.tar.gz && chmod +x skeleton
```
Using **wget**:
```bash
wget "https://github.com/coyotito-mx/package-skeleton-cli/releases/latest/download/skeleton.tar.gz" -O skeleton.tar.gz
tar -xzf skeleton.tar.gz && chmod +x skeleton
```
Then you can move the binary to your `PATH`:
```bash
mv skeleton /usr/local/bin/
```
## Usage
> ✅
> The CLI initializes packages in the **current working directory** or a specified `--path`. You can initialize from existing files or bootstrap from a template using `--bootstrap`.
The [placeholders](#placeholders-and-modifiers) must follow the format: `{{placeholder}}`. You can apply modifiers to format values before replacement:
```bash
{{placeholder|modifier[,modifier]}}
```
### Running the CLI
Initialize a package with vendor, package name, and author details:
```bash
skeleton init \
acme \
blog \
"Acme\\Blog" \
"John Doe" \
"john@doe.com" \
"A blogging package for Laravel" \
--path="$HOME/projects/my-package"
```
Or use prompts:
```bash
skeleton init
# Prompts: vendor, package, namespace (optional), author, email (fetched from git config, if available), description
```
> Note: The testing framework prompt appears only when dependencies are installed (i.e., without `--no-install`).
To skip confirmation:
```bash
skeleton init acme blog "Acme\\Blog" "John Doe" "john@doe.com" "Description" \
--proceed
```
To skip Composer dependency installation:
```bash
skeleton init acme blog "Acme\\Blog" "John Doe" "john@doe.com" "Description" \
--no-install
```
To skip creating a LICENSE file when it does not exist:
```bash
skeleton init acme blog "Acme\\Blog" "John Doe" "john@doe.com" "Description" \
--skip-license
```
To exclude specific files/directories from processing:
```bash
skeleton init acme blog "Acme\\Blog" "John Doe" "john@doe.com" "Description" \
--exclude="composer.json" \
--exclude="package.json"
```
To bootstrap from a skeleton template (`vanilla` or `laravel`):
```bash
skeleton init acme blog "Acme\\Blog" "John Doe" "john@doe.com" "Description" \
--bootstrap=vanilla
```
To force bootstrapping into a non-empty directory:
```bash
skeleton init acme blog "Acme\\Blog" "John Doe" "john@doe.com" "Description" \
--bootstrap=laravel \
--force
```
### Placeholders and Modifiers
#### Available Placeholders
- `vendor` - Package vendor (e.g., `acme`)
- `package` - Package name (e.g., `blog`)
- `namespace` - Package namespace (auto-generated from vendor\package, or custom)
- `description` - Package description
- `author` - Package author name
- `email` - Author's email address
- `license` - License name (defaults to `MIT`)
- `version` - Package version (defaults to `0.0.1`)
- `year` - Current year
- `class` - Class name (defaults to package name in PascalCase). Used primarily in filenames
> **Namespace Format Requirements**
>
> The `namespace` argument must follow this pattern: `Vendor\Package`
>
> - Must have exactly two parts separated by a backslash
> - Each part must start with an **uppercase letter**
> - Each part can contain alphanumeric characters (A-Z, a-z, 0-9)
> - Invalid example: `acme\blog`, `Acme_Blog`, `Acme/Blog` ❌
> - Valid example: `Acme\Blog`, `MyVendor\MyPackage` ✅
>
> If not provided, the namespace will be auto-generated as `Vendor\Package` based on the vendor and package arguments.
#### Global Modifiers
- `upper` - Converts to UPPERCASE
- `lower` - Converts to lowercase
- `title` - Converts to Title Case
- `snake` - Converts to snake_case
- `kebab` - Converts to kebab-case
- `camel` - Converts to camelCase
- `pascal` - Converts to PascalCase (StudlyCase)
- `slug` - Converts to slug-format
- `ucfirst` - Converts first character to uppercase
- `acronym` - Generates acronym (e.g., "John Doe" → "JD")
> ⚠️
> **Modifier Order Matters!** The order of chained modifiers affects the output.
>
> ```text
> John Doe → JOHN-DOE
>
> {{author|upper,slug}} → john-doe (incorrect)
> {{author|slug,upper}} → JOHN-DOE (correct)
> ```
#### Replacer-Specific Modifiers
##### `namespace` Replacer
- `escape` - Escapes `\` to `\\` (e.g., `Acme\Blog` → `Acme\\Blog`)
- `reverse` - Reverses `\` to `/` (e.g., `Acme\Blog` → `Acme/Blog`)
> **Note**: Modifiers are applied to each part of the namespace separately (vendor and package).
##### `version` Replacer
- `major` - Extracts major version (e.g., `2` from `2.5.3`)
- `minor` - Extracts minor version (e.g., `5` from `2.5.3`)
- `patch` - Extracts patch version (e.g., `3` from `2.5.3`)
- `pre` - Extracts pre-release (e.g., `alpha` from `1.0.0-alpha`)
- `meta` - Extracts build metadata (e.g., `abc123` from `1.0.0+abc123`)
- `prefix` - Adds `v` prefix if not present (e.g., `1.0.0` → `v1.0.0`)
##### `email` Replacer
- `upper` - Converts email to uppercase while preserving `@` and `.`
##### `class` Replacer
- Used only in **filename** contexts
- Converts to kebab-case in filenames (e.g., `{{class}}` → `my-class.php`)
- Default value is transformed from package name (e.g., `blog` → `Blog` → `blog` in filename)
- Supports all global modifiers when used in content
### CLI Arguments and Options
```bash
SYNOPSIS
skeleton init [options] [--]
Arguments
vendor The name of the package vendor (prompted if not provided)
package The name of the package (prompted if not provided)
namespace The package namespace (auto-generated as Vendor\Package if not provided)
author The package author (fetched from `git config user.name` or prompted)
email The package author email (fetched from `git config user.email` or prompted)
description The package description (prompted if not provided)
Options
--bootstrap[=BOOTSTRAP] Initialize a new package from skeleton template (options: laravel, vanilla)
--class[=CLASS] The class name to use in replacements (defaults to package name)
--force Force bootstrapping even if target directory is not empty (use with --bootstrap)
--proceed Accept the configuration and proceed without confirmation
--no-install Skip installing composer dependencies
--skip-license Skip creating a LICENSE file if one does not exist
--path[=PATH] The path to initialize the package in (defaults to current working directory)
--exclude[=EXCLUDE] Paths to exclude when processing files (multiple values allowed)
-h, --help Display help for the command
--silent Do not output any messages
-q, --quiet Only errors are displayed. All other output is suppressed
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
--env[=ENV] The environment the command should run under
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output, and 3 for debug output
```
### Excluded Paths (Default)
By default, the following paths are **excluded** from placeholder replacement:
- `.git`
- `.DS_Store`
- `vendor`
- `node_modules`
Add custom exclusions with `--exclude`:
```bash
skeleton init acme blog "Acme\\Blog" "John Doe" "john@doe.com" "Description" \
--exclude="dist" \
--exclude="build" \
--exclude=".env"
```
### Author Information
The CLI automatically fetches author information from git configuration:
```bash
git config user.name "John Doe"
git config user.email "john@doe.com"
```
If git config is not available, you'll be prompted interactively.
### Testing Framework Selection
When dependencies are enabled (without `--no-install`), you'll be prompted to choose your testing framework:
- **Pest** (default) - Modern, elegant testing for PHP
- **PHPUnit** - Industry-standard PHP testing framework
The selected framework's dev dependencies will be automatically installed.
If `--no-install` is used, this prompt is skipped and no testing framework dependencies are installed.
### CLI Removal Prompt
At the end of a successful `init` run, the CLI always asks:
```text
Do you want to remove this CLI now?
```
If you answer `yes`, the CLI removes the invoked executable file. If it cannot resolve or delete that executable, it shows a warning and continues.
### Remove content
To remove `content` you can use a tag named ``, and all the content between this tag would be removed, also the spaces after the close tag will be removed.
```MD
# Lorem ipsum
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sem libero, rutrum ut congue quis, cursus quis lectus.
Etiam tempor ac lacus in congue.
Ut lobortis eros a ipsum varius, eget tristique risus laoreet. Vestibulum ultricies augue ligula, vitae imperdiet urna tempus non.
```
and the result should be something like:
```MD
# Lorem ipsum
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sem libero, rutrum ut congue quis, cursus quis lectus.
Ut lobortis eros a ipsum varius, eget tristique risus laoreet. Vestibulum ultricies augue ligula, vitae imperdiet urna tempus non.
```
## Examples
### Example 1: Initialize with all prompted values
```bash
$ skeleton init --path="$HOME/projects"
Enter the package vendor name: acme
Enter the package name: blog
Enter the package namespace (Optional, press Enter to auto-generate): Acme\Blog
Enter the package description: A blogging package
(Author and email fetched from git config, if available)
...
Do you want to proceed with this configuration?: Yes
...
Which testing framework do you want to use? [pest/phpunit]: pest
...
Package [Acme\Blog] initialized successfully!
Do you want to remove this CLI now?: No
```
### Example 2: Initialize with all arguments provided
```bash
skeleton init acme blog "Acme\\Blog" "Jane Doe" "jane@example.com" "A blogging package" \
--proceed \
--path="$HOME/projects"
```
### Example 3: Initialize without dependencies
```bash
skeleton init acme blog "Acme\\Blog" "John Doe" "john@doe.com" "A blogging package" \
--no-install \
--proceed
```
### Example 4: Initialize with a custom class name
```bash
skeleton init acme blog "Acme\\Blog" "John Doe" "john@doe.com" "A blogging package" \
--class="BlogManager" \
--proceed
```
## Contributing
If you would like to contribute to the Skeleton CLI, please follow these steps:
1. Fork the repository.
2. Create a new branch for your feature or bugfix.
3. Make your changes and add tests.
4. Ensure all tests pass: `composer test`
5. Run code standards: `composer lint:with-style`
6. Submit a pull request.
## Testing
Run tests with:
```bash
composer test # Run all tests
composer test:ci # Run tests in CI mode
```
Check code standards with:
```bash
composer lint # Run PHPStan (level 5)
composer style # Check code formatting with Pint
```
Fix code formatting:
```bash
composer fix # Auto-fix code formatting
```
## License
The Skeleton CLI is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).