CLI tool setup project quickly.
Project description
Cliex
Cliex is a Python CLI tool that helps you bootstrap projects quickly using setup profiles defined in YAML. Instead of retyping dozens of install commands every time you start a new project, you run one command — Cliex executes the entire setup workflow for you.
The source code is free and open for the community. You may use, modify, and share it freely under the MIT license.
Features
- Bootstrap a new project with a single command
- Support for multiple setup profiles (Next.js, FastAPI, Razor, etc.)
- Create or customize your own profiles via YAML files
- Rich step types — run commands, copy/move files, and edit generated files
with idempotent
insert/replace - Platform-specific steps via
when(Windows / macOS / Linux) - Save a default git identity so the commit step never fails
- List and manage available profiles
- Colorful terminal output for easy progress tracking
- Automatic checks for required tools before running
Requirements
- Python 3.11+
- Node.js, npm, npx (for frontend profiles such as Next.js)
- Git
Installation
Option 1 — PyPI (recommended for end users)
Requires Python 3.11+.
# Recommended: isolated install
pipx install cliex
# Or with pip
pip install cliex
Verify:
cliex list
Update to the latest version:
pipx upgrade cliex
# or
pip install -U cliex
Option 2 — GitHub Releases
Download a wheel from Releases or install directly:
pip install https://github.com/DucHuynhTrung/cliex-quick/releases/download/v0.1.0/cliex-0.1.0-py3-none-any.whl
Replace v0.1.0 with the latest tag.
Option 3 — Install from source (development)
git clone https://github.com/DucHuynhTrung/cliex-quick.git
cd cliex-quick
pip install -e .
Using uv (optional)
uv venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
uv pip install -e .
After installation, the cliex command is available in your terminal.
Maintainers: see docs/RELEASE.md for the full GitLab → GitHub mirror → PyPI + Releases workflow.
Usage
Create a new project
# Create a project in the "my-app" folder (uses the default profile)
cliex new my-app
# Create a project in the current directory
cliex new .
# No name provided → defaults to the current directory
cliex new
Choose a specific setup profile
# Use the Next.js profile
cliex new my-app --setup nextjs-setup
# Short form
cliex new my-app -s fastapi
# Force the built-in version (ignore your custom override)
cliex new my-app -s b:nextjs-setup
# Force your custom version
cliex new my-app -s u:nextjs-setup
# Use a custom YAML file directly
cliex new my-app --setup path/to/my-setup.yaml
When you have a custom profile and a built-in profile with the same key, the
custom one wins by default. Use the b: prefix to force the built-in, or u:
to force the user version.
Pass variables
If a profile declares variables, you can provide them on the command line or let Cliex prompt you:
# Provide values (skips the prompt for those)
cliex new my-app -s my-profile --var git_user=Duc --var app_title="My App"
# Use declared defaults without prompting
cliex new my-app -s my-profile --yes
Set the git identity for the commit step
Profiles that initialize git need a user.name / user.email, otherwise the
commit step fails with "unable to auto-detect email address". Cliex resolves
the identity in this order:
--username/--useremailflag → saved default (cliex config) → your global git config
Per-project (overrides the saved default for this run only):
cliex new my-app -s tauri-setup --username "Your Name" --useremail "you@example.com"
# Short form
cliex new my-app -s tauri-setup -un "Your Name" -ue "you@example.com"
Save a default once, then every cliex new reuses it:
# Set the default git identity
cliex config --git-username "Your Name" --git-email "you@example.com"
# Show current defaults (default profile + git identity)
cliex config
The identity is stored per-user in config.yaml (never inside a shared
profile). Inside a profile, the resolved values are available as the
{{ git_username }} and {{ git_email }} variables — typically used by a
git step that runs git config --local right after git init:
- type: run
name: git-init
cmd: git init
- type: git
name: git-config
username: "{{ git_username }}"
email: "{{ git_email }}"
If both flag and saved default are empty, the git step is skipped and git
falls back to your global config.
List available profiles
cliex list
This displays all registered profiles, their source (package or user), and which one is the default.
Create, fork, or edit a profile
# Create a new profile, fork a built-in to customize it, or open an existing one
cliex registry my-custom-setup
# Fork the built-in nextjs-setup into an editable local copy
cliex registry nextjs-setup
cliex registry <key> always writes to your user setup directory and:
- If you already have a user profile with that key → opens it.
- Else if a built-in with that key exists → copies it into your user directory as a local override, then opens it. Future app updates won't touch your copy.
- Else → creates a new
<key>.yamltemplate (withname,description, and a sample step) and opens it.
The file is opened in your system's default text editor. Profile metadata
(name, description) lives inside the file itself, so profiles are
self-describing and easy to share.
Set the default profile
cliex set-default fastapi
cliex new with no --setup uses this default. The setting is stored per-user
in config.yaml (it is never embedded in a shared profile).
Revert a customized built-in
cliex reset nextjs-setup
Removes your local override and goes back to the built-in profile.
Validate profiles
# Validate one profile
cliex validate nextjs-setup
# Validate all profiles
cliex validate
Run without installing
python -m cliex new my-app
python -m cliex list
Commands
| Command | Description |
|---|---|
cliex new [PROJECT_NAME] |
Create a new project using a setup profile |
cliex new --setup <profile> |
Select a profile (b:/u: prefix or YAML file) |
cliex new --var k=v --yes |
Provide profile variables / skip prompts |
cliex new -un <name> -ue <email> |
Set git identity for this project's commit step |
cliex config |
Show persistent defaults (default profile + git identity) |
cliex config --git-username <n> --git-email <e> |
Save the default git identity |
cliex list |
List all setup profiles |
cliex registry <name> |
Create, fork, or edit a profile YAML file |
cliex set-default <name> |
Set the default profile |
cliex reset <name> |
Remove a custom override, revert to built-in |
cliex validate [name] |
Validate one or all profiles |
Built-in setup profiles
| Profile | Description |
|---|---|
nextjs-setup (default) |
Next.js + TypeScript + Tailwind + ESLint + shadcn/ui + Firebase + agent skills |
fastapi |
FastAPI with a virtual environment |
razor |
Razor project setup |
Step-by-step details for each profile live in cliex/templates/setups/.
What does the Next.js profile do?
When you run cliex new my-app -s nextjs-setup, Cliex will:
- Check for
node,npm,npx, andgit - Create a Next.js project (TypeScript, Tailwind, ESLint, App Router)
- Install packages: Firebase, Zod, TanStack Query, Zustand, etc.
- Initialize shadcn/ui and add common components
- Install agent skills for Claude
- Initialize git and commit the changes
- Add your customizations.
And you're ready to write code.
Customizing setup profiles
Each profile is a YAML file with top-level name, description, an optional
variables list, and a list of steps. Supported step types:
| Type | Description | Example fields |
|---|---|---|
run |
Run a shell command | cmd: npm install |
copy |
Copy a file or directory | src, dest |
move |
Move/rename a file or directory | src, dest |
mkdir |
Create a directory | path |
remove |
Delete a file or directory | path, ignore_missing |
append |
Append content to the end of a file | file, content |
insert |
Insert content at a line number or anchor | file, content, one of line/after/before, skip_if_present |
replace |
Replace a literal string inside a file | file, find, replace, count, skip_if_missing |
git |
Git operations | add, commit_message, username, email |
insert and replace (editing generated files)
Use these to tweak files a scaffolder created, without shipping template copies. Both are idempotent — re-running a setup won't duplicate changes.
# Insert a line right after the line that matches an anchor
- type: insert
file: src/main.tsx
after: 'import App from "./App";' # or: before: '<text>' / line: 3
content: |
import "./index.css";
# Replace a literal string (e.g. add a plugin to an array)
- type: replace
file: vite.config.ts
find: "plugins: [react()]"
replace: "plugins: [react(), tailwindcss()]"
insert: pick one ofline(1-based, inserts before that line),after(inserts on the next line after the match), orbefore. With none, it appends at the end.skip_if_present: true(default) skips when the content already exists; a missingafter/beforeanchor raises an error.replace: replaces all occurrences by default (count: Nlimits it). Iffindis absent butreplaceis already present, the step is skipped (safe re-runs); setskip_if_missing: trueto ignore a genuinely missingfindinstead of erroring.
Platform-specific steps (when)
Any step may include a when field so it only runs on matching platforms —
this is how you express "if/else by OS" (write one step per platform; the
non-matching ones are skipped):
when |
Runs on |
|---|---|
windows |
Windows only |
unix |
Any non-Windows OS (Linux, macOS, BSD) |
linux |
Linux only |
macos / darwin |
macOS only |
A step with no when runs everywhere (the "else" branch).
- type: run
name: redirect-stdin
when: windows
cmd: some-cli < NUL
- type: run
name: redirect-stdin
when: unix
cmd: some-cli < /dev/null
Minimal profile example:
name: My Profile
description: A tiny example profile.
steps:
- type: run
name: say-hello
cmd: echo "Hello from Cliex!"
Variables
Declare variables and reference them with {{ name }} in any step string.
project_name and project_path are always available.
name: My Profile
description: Example with variables.
variables:
- name: app_title
prompt: "App title"
default: "My App"
steps:
- type: append
file: README.md
content: "# {{ app_title }} ({{ project_name }})\n"
Provide values with --var app_title="...", accept defaults with --yes, or
answer the interactive prompt.
Where profiles are stored
- Package (bundled with Cliex):
cliex/templates/setups/ - User (your custom profiles):
- Windows:
%APPDATA%\cliex\setups\(i.e....\AppData\Roaming\cliex\setups\) - macOS / Linux:
~/.config/cliex/setups/
- Windows:
User-created profiles override package profiles with the same key (filename).
Updating Cliex never touches your user profiles. Per-user settings — the
default profile and the default git identity — are stored in config.yaml next
to your setups directory (never inside a shared profile).
Project structure
cliex/
├── cliex/
│ ├── main.py # CLI entry point (Typer)
│ ├── cli/
│ │ └── new.py # New project creation logic
│ ├── setup/
│ │ ├── registry.py # Profile registry, default, validation
│ │ ├── loader.py # YAML file loader
│ │ ├── variables.py # Variable prompts + {{ }} substitution
│ │ └── executor.py # Step executor
│ ├── runner/
│ │ └── runner.py # Subprocess runner
│ ├── checker/
│ │ └── checker.py # System requirement checker
│ └── templates/
│ └── setups/ # Default profiles + metadata
├── pyproject.toml
├── LICENSE
└── README.md
Troubleshooting
Missing required tools
Missing required commands: node, npm
Install the missing tools:
- Node.js / npm: https://nodejs.org/
- Git: https://git-scm.com/
Target directory already exists
Target folder already exists
Choose a different folder name or remove the existing directory before running again.
Git commit failed
*** Please tell me who you are.
fatal: unable to auto-detect email address
The commit step has no git identity. Fix it with any of these (highest precedence first):
# Per project, for this run only
cliex new my-app -un "Your Name" -ue "you@example.com"
# Saved default, reused by every future run
cliex config --git-username "Your Name" --git-email "you@example.com"
# Or your machine-wide global git identity
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
Profile not found
Run cliex list to see available profiles, or create a new one with cliex registry <name>.
Development
# Install in editable mode
pip install -e .
# Run directly
python -m cliex list
Contributing
Contributions are welcome! You can:
- Report bugs or request features via Issues
- Submit Pull Requests with new setup profiles or code improvements
- Share your YAML profiles with the community
License
This project is released under the MIT license — completely free and open source for the community.
You are free to use, copy, modify, distribute, and use it commercially without permission. See LICENSE for details.
Author
DucHuynhTrung — huynhtrungduc.growth@gmail.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cliex-0.3.0.tar.gz.
File metadata
- Download URL: cliex-0.3.0.tar.gz
- Upload date:
- Size: 1.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c56c96a13bf7ddb6789c662bf141ceeb935d5413d89f47cae6a030cccb8cdd8
|
|
| MD5 |
d513097f68e19197abbf077ec17b6d9b
|
|
| BLAKE2b-256 |
4619f19ce263dd857636d80af63c85e22dbcf395f415430b1b41657346da677d
|
File details
Details for the file cliex-0.3.0-py3-none-any.whl.
File metadata
- Download URL: cliex-0.3.0-py3-none-any.whl
- Upload date:
- Size: 28.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
780cd0f05f081edab3a6b5cc7ecaf632237212e575b4b8fbcae8469adeffdf32
|
|
| MD5 |
0fd21a9c3e465f945cd1b467d916dc6e
|
|
| BLAKE2b-256 |
d4ea10875aa97d0f2038bab75431b2328464bd8a115dbe10a26c7d35114f4f54
|