The ever CLI acts as a thin router (multiplexer) that dispatches commands to product-specific sub-CLIs. Each product in the Ever ecosystem ships its own standalone CLI binary, and the ever root CLI discovers and invokes them transparently.
ever <product> <command> [subcommand] [args] [flags]
Examples:
ever os run agents
ever os plugin install yo
ever teams notify kostya
ever teams add member vanya
ever cloc start timer
ever gauzy export invoices --format=csv
ever dev setup workspaceThe user types one unified command. Under the hood, ever resolves the product name to the correct binary and forwards the remaining arguments.
- The root CLI is tiny. It handles routing, plugin management, and global flags only. No product logic lives here.
- Sub-CLIs are fully independent. Each can be a separate npm package, Rust crate, Go binary — any language, any release cadence, any maintainer.
- Sub-CLIs work standalone.
ever-os run agentsworks identically whether invoked directly or viaever os run agents. The sub-CLI receives the same argv either way. - Zero coupling between products. Adding a new product CLI never requires changes to the router.
- Graceful degradation. If a sub-CLI is not installed, the router provides a clear install command instead of a cryptic error.
The router uses a two-phase lookup: manifest first, PATH fallback.
ever teams notify kostya
│
├─ Phase 1: Check ~/.ever/plugins.json
│ └─ Found "teams" → /usr/local/bin/ever-teams
│
├─ Phase 2 (if not in manifest): Search PATH for "ever-teams"
│ └─ Found → exec ever-teams notify kostya
│
├─ Phase 3 (if not found anywhere):
│ └─ Error: "Unknown product 'teams'. Run: ever install teams"
│
└─ Exec: ever-teams notify kostya
└─ Sub-CLI receives argv: ["notify", "kostya"]
The router reads ~/.ever/plugins.json (created on first run or first install). This file maps product names to binary paths and metadata.
{
"version": 1,
"plugins": {
"os": {
"binary": "/usr/local/bin/ever-os",
"package": "ever-os-cli",
"source": "npm",
"version": "0.3.1",
"installed_at": "2026-04-01T12:00:00Z"
},
"teams": {
"binary": "/home/user/.cargo/bin/ever-teams",
"package": "ever-teams-cli",
"source": "cargo",
"version": "1.0.0",
"installed_at": "2026-04-01T12:05:00Z"
}
}
}If the product is found in the manifest and the binary exists at the recorded path, the router execs it immediately. If the binary path is stale (file no longer exists), the router falls through to Phase 2 and, if found, updates the manifest.
If the product is not in the manifest, the router searches the system PATH for a binary named ever-<product>. This enables sub-CLIs installed manually, via system package managers, or by other tools to be discovered automatically.
On successful PATH discovery, the router auto-registers the binary into the manifest for faster subsequent lookups.
If neither phase finds a binary, the router prints:
Error: Product 'teams' is not installed.
Install it with:
ever install teams
Available products:
ever list
Once the router resolves a binary path, it performs an exec (process replacement), not a subprocess spawn. This means:
- The sub-CLI fully replaces the router process (no parent process hanging around).
- stdin, stdout, stderr pass through natively.
- Exit codes propagate correctly.
- Signal handling works as expected (Ctrl+C, SIGTERM, etc.).
Argument forwarding:
# Mode A: Via router
User types: ever os run agents --verbose
Router resolves: /usr/local/bin/ever-os
Exec call: exec /usr/local/bin/ever-os run agents --verbose
Sub-CLI receives: argv = ["ever-os", "run", "agents", "--verbose"]
# Mode B: Direct prefixed
User types: ever-os run agents --verbose
Shell resolves: /usr/local/bin/ever-os
Sub-CLI receives: argv = ["ever-os", "run", "agents", "--verbose"]
# Mode C: Short alias
User types: os run agents --verbose
Shell resolves: /usr/local/bin/os (symlink → ever-os)
Sub-CLI receives: argv = ["os", "run", "agents", "--verbose"]
In all three modes, the sub-CLI receives the same meaningful arguments: ["run", "agents", "--verbose"]. Only argv[0] differs (the binary name), which the sub-CLI should ignore.
The root ever CLI reserves the following built-in commands (these are NOT forwarded to sub-CLIs):
| Command | Description |
|---|---|
ever install <product> |
Install a product sub-CLI |
ever uninstall <product> |
Remove a product sub-CLI and its manifest entry |
ever update [product] |
Update one or all installed sub-CLIs |
ever list |
List all known products and their install status |
ever doctor |
Verify all manifest entries point to valid binaries |
ever version |
Show router version |
ever help |
Show global help and list of available products |
ever config |
Manage global configuration (~/.ever/config.toml) |
Collision rule: Built-in commands take priority. If a sub-CLI is ever named ever-install, the built-in ever install wins. This set of reserved names should remain small and stable.
All product CLIs in the Ever ecosystem. Each sub-CLI exposes three command names: the short alias, the prefixed binary name, and the router invocation.
| Product | Short Alias | Prefixed Binary | Router Invocation | Package (npm) | Package (crate) | Status |
|---|---|---|---|---|---|---|
| ever (router) | — | ever |
ever <product> <cmd> |
ever-cli |
ever-cli |
✅ Exists (npm) |
| gauzy | gauzy |
ever-gauzy |
ever gauzy <cmd> |
ever-gauzy-cli |
ever-gauzy-cli |
✅ Reserved (npm) |
| os | os |
ever-os |
ever os <cmd> |
ever-os-cli |
ever-os-cli |
✅ Reserved (npm) |
| teams | teams |
ever-teams |
ever teams <cmd> |
ever-teams-cli |
ever-teams-cli |
✅ Reserved (npm) |
| works | works |
ever-works |
ever works <cmd> |
ever-works-cli |
ever-works-cli |
✅ Exists (npm) |
| rec | rec |
ever-rec |
ever rec <cmd> |
ever-rec-cli |
ever-rec-cli |
✅ Reserved (npm) |
| hust | hust |
ever-hust |
ever hust <cmd> |
ever-hust-cli |
ever-hust-cli |
✅ Reserved (npm) |
| jobs | jobs |
ever-jobs |
ever jobs <cmd> |
ever-jobs-cli |
ever-jobs-cli |
✅ Reserved (npm) |
| dev | dev |
ever-dev |
ever dev <cmd> |
ever-dev-cli |
ever-dev-cli |
✅ Reserved (npm) |
| cloc | cloc |
ever-cloc |
ever cloc <cmd> |
ever-cloc-cli |
ever-cloc-cli |
✅ Reserved (npm) |
| demand | demand |
ever-demand |
ever demand <cmd> |
ever-demand-cli |
ever-demand-cli |
✅ Reserved (npm) |
| traduora | traduora |
ever-traduora |
ever traduora <cmd> |
ever-traduora-cli |
ever-traduora-cli |
✅ Reserved (npm) |
| tech | tech |
ever-tech |
ever tech <cmd> |
ever-tech-cli |
ever-tech-cli |
✅ Reserved (npm) |
| saas | saas |
ever-saas |
ever saas <cmd> |
ever-saas-cli |
ever-saas-cli |
✅ Reserved (npm) |
| docs | docs |
ever-docs |
ever docs <cmd> |
ever-docs-cli |
ever-docs-cli |
✅ Reserved (npm) |
| digital | digital |
ever-digital |
ever digital <cmd> |
ever-digital-cli |
ever-digital-cli |
✅ Reserved (npm) |
| shop | shop |
ever-shop |
ever shop <cmd> |
ever-shop-cli |
ever-shop-cli |
✅ Reserved (npm) |
| iq | iq |
ever-iq |
ever iq <cmd> |
ever-iq-cli |
ever-iq-cli |
✅ Reserved (npm) |
Note: The short alias (e.g.
cloc,teams) and the prefixed binary (e.g.ever-cloc,ever-teams) both point to the same underlying executable. See "Short Alias Commands" below for how this is implemented.
~/.ever/
├── config.toml # Global configuration (API endpoints, auth tokens, defaults)
├── plugins.json # Manifest: product → binary path mapping
└── cache/ # Optional: cached package metadata, update checks
[global]
telemetry = false
auto_update_check = true
default_org = "ever-co"
[auth]
# Shared auth token usable by all sub-CLIs
api_token = "ey..."
api_endpoint = "https://api.ever.co"
[registry]
# Where to look for sub-CLI packages
npm_prefix = "ever"Sub-CLIs can read ~/.ever/config.toml for shared configuration (auth tokens, org defaults) so the user authenticates once via ever config set auth.api_token <token> and all products inherit it.
fn main():
args = parse_cli_args()
if args.command in BUILT_IN_COMMANDS:
handle_builtin(args)
return
product = args.command # e.g. "os"
rest = args.remaining # e.g. ["run", "agents", "--verbose"]
# Phase 1: Manifest lookup
manifest = load_manifest("~/.ever/plugins.json")
if product in manifest.plugins:
binary = manifest.plugins[product].binary
if file_exists(binary):
exec(binary, rest) # Process replacement, never returns
else:
warn("Binary not found at {binary}, searching PATH...")
# Phase 2: PATH fallback
binary_name = "ever-" + product # e.g. "ever-os"
binary = which(binary_name)
if binary:
# Auto-register for future lookups
manifest.plugins[product] = { binary: binary, source: "path" }
save_manifest(manifest)
exec(binary, rest)
# Phase 3: Not found
error("Product '{product}' is not installed.")
hint("Run: ever install {product}")
hint("Run: ever list (to see available products)")
exit(1)
Language choice for the router: The router is built in Rust for instant startup (~5ms vs ~200ms for Node.js). This matters because every ever <x> command pays the router's startup cost before reaching the sub-CLI. Distribution to end users is handled via npm using platform-specific optional dependencies — users run npm install -g ever-cli and get the native Rust binary transparently. See "Distribution: Rust Binary via npm" below for full details.
exec semantics by platform:
- Unix/macOS: Use
execvp()(Rust:std::os::unix::process::CommandExt::exec()) for true process replacement. - Windows: Use
CreateProcess+ wait + propagate exit code (Windows does not support exec-style process replacement).
Binary naming convention: All sub-CLI binaries MUST be named ever-<product> (lowercase, hyphenated). This is the contract between the router and sub-CLIs.
The router is built in Rust for instant startup (~5ms vs ~200ms for Node.js). But developers expect to install CLI tools via npm:
npm install -g ever-cli
# or
npx ever os run agentsThey should never need to install Rust, run cargo install, or download binaries manually.
This is the same pattern used by esbuild, SWC, Biome, Turbo, Oxlint, Prisma, and Lightning CSS. The Rust binary is compiled for every OS/arch combination and published as separate npm packages. The main package pulls in the correct one automatically.
ever-cli ← Main package, unscoped (what users install)
├── package.json ← Has optionalDependencies for all platforms
├── bin/ever ← Thin JS wrapper (5 lines)
└── npm/postinstall.js ← Optional: verify binary works
@ever-co/cli-darwin-arm64 ← macOS Apple Silicon (scoped)
└── ever ← Native Rust binary
@ever-co/cli-darwin-x64 ← macOS Intel (scoped)
└── ever
@ever-co/cli-linux-x64-gnu ← Linux x64 glibc (scoped)
└── ever
@ever-co/cli-linux-x64-musl ← Linux x64 musl/Alpine (scoped)
└── ever
@ever-co/cli-linux-arm64-gnu ← Linux ARM64 glibc (scoped)
└── ever
@ever-co/cli-win32-x64-msvc ← Windows x64 (scoped)
└── ever.exe
@ever-co/cli-win32-arm64-msvc ← Windows ARM64 (scoped)
└── ever.exe
Why scoped for platform packages? Product CLIs (e.g.
ever-gauzy-cli) are unscoped to reserve the public names. Platform binary packages are internal implementation details — users never install them directly. Scoping them under@ever-co/keeps them organized, protected by the org, and avoids polluting the public namespace with long names likeever-cli-linux-arm64-gnu.
{
"name": "ever-cli",
"version": "1.0.0",
"description": "Ever CLI — unified command-line interface for the Ever ecosystem",
"bin": {
"ever": "bin/ever"
},
"optionalDependencies": {
"@ever-co/cli-darwin-arm64": "1.0.0",
"@ever-co/cli-darwin-x64": "1.0.0",
"@ever-co/cli-linux-x64-gnu": "1.0.0",
"@ever-co/cli-linux-x64-musl": "1.0.0",
"@ever-co/cli-linux-arm64-gnu": "1.0.0",
"@ever-co/cli-win32-x64-msvc": "1.0.0",
"@ever-co/cli-win32-arm64-msvc": "1.0.0"
},
"scripts": {
"postinstall": "node npm/postinstall.js"
}
}npm automatically installs only the optionalDependency matching the current platform and skips the rest. This is built-in npm behavior — no custom logic needed.
This is the only JavaScript in the entire router. It exists solely to locate and exec the native binary:
#!/usr/bin/env node
const { execFileSync } = require("child_process");
const path = require("path");
const PLATFORMS = {
"darwin-arm64": "@ever-co/cli-darwin-arm64/ever",
"darwin-x64": "@ever-co/cli-darwin-x64/ever",
"linux-x64": "@ever-co/cli-linux-x64-gnu/ever",
"linux-arm64": "@ever-co/cli-linux-arm64-gnu/ever",
"win32-x64": "@ever-co/cli-win32-x64-msvc/ever.exe",
"win32-arm64": "@ever-co/cli-win32-arm64-msvc/ever.exe",
};
const key = `${process.platform}-${process.arch}`;
const binPkg = PLATFORMS[key];
if (!binPkg) {
console.error(`Error: Unsupported platform ${key}`);
process.exit(1);
}
const binPath = require.resolve(binPkg);
try {
const result = execFileSync(binPath, process.argv.slice(2), {
stdio: "inherit",
env: process.env,
});
} catch (e) {
process.exit(e.status ?? 1);
}Note: This wrapper runs only once per invocation and adds ~30ms of Node overhead. Since the actual routing and all subsequent work happens in the native Rust binary, the total overhead is negligible. For users who want zero Node overhead, they can add the native binary directly to their PATH (see "Direct Binary Installation" below).
{
"name": "@ever-co/cli-darwin-arm64",
"version": "1.0.0",
"os": ["darwin"],
"cpu": ["arm64"],
"files": ["ever"],
"preferUnpacked": true
}The os and cpu fields tell npm to only install this package on matching systems. The files array ensures only the binary is included (tiny package size).
Each release compiles the Rust router for all targets and publishes all npm packages atomically:
GitHub Actions / Release Workflow
│
├─ Build Matrix:
│ ├─ target: aarch64-apple-darwin → @ever-co/cli-darwin-arm64
│ ├─ target: x86_64-apple-darwin → @ever-co/cli-darwin-x64
│ ├─ target: x86_64-unknown-linux-gnu → @ever-co/cli-linux-x64-gnu
│ ├─ target: x86_64-unknown-linux-musl → @ever-co/cli-linux-x64-musl
│ ├─ target: aarch64-unknown-linux-gnu → @ever-co/cli-linux-arm64-gnu
│ ├─ target: x86_64-pc-windows-msvc → @ever-co/cli-win32-x64-msvc
│ └─ target: aarch64-pc-windows-msvc → @ever-co/cli-win32-arm64-msvc
│
├─ For each target:
│ 1. cargo build --release --target <target>
│ 2. Strip binary (strip / llvm-strip)
│ 3. Copy binary into platform npm package dir
│ 4. npm publish @ever-co/cli-<platform> --access public
│
└─ Finally:
5. Update version in ever-cli/package.json
6. npm publish ever-cli
Cross-compilation tools: Use cross (https://github.com/cross-rs/cross) or cargo-zigbuild for reliable cross-compilation from a single CI runner, or use GitHub Actions' matrix strategy with native runners for each OS.
# Install globally — identical to any Node CLI
$ npm install -g ever-cli
# Or use npx — no global install needed
$ npx ever-cli os run agents
# Then just use it
$ ever os run agents
$ ever teams notify kostya
$ teams notify kostyaThe user never knows it's Rust. No cargo, no rustup, no downloading binaries. Just npm.
While npm is the primary distribution channel, the Rust binary should also be available through other channels for non-Node users:
# Cargo (for Rust developers)
cargo install ever-cli
# Homebrew (macOS/Linux)
brew install ever-co/tap/ever
# Shell script (curl | sh pattern, like rustup)
curl -fsSL https://cli.ever.co/install.sh | sh
# GitHub Releases (manual download)
# https://github.com/ever-co/ever-cli/releases/latest
# Windows installer (MSI or winget)
winget install ever-co.ever-cliThese are secondary channels. npm is the primary one and covers 90%+ of the target audience.
Each product sub-CLI (ever-os, ever-teams, etc.) can use the exact same distribution strategy if built in Rust:
# User installs via the ever router
ever install os
└─ internally runs: npm install -g ever-os-cli
└─ pulls in ever-os-cli (native binary or Node package)
# Or user installs directly
npm install -g ever-os-cliSub-CLIs can also be pure Node/TypeScript if Rust is overkill for that product. The router doesn't care what language the sub-CLI is written in — it just execs a binary.
The router binary should be small since it does very little:
| Component | Expected size |
|---|---|
| Router binary (stripped) | ~2–4 MB |
| Platform npm package | ~1–2 MB (compressed) |
| Main npm package (JS wrapper only) | ~5 KB |
For reference, Biome's binary is ~30MB (it does a lot more). The router should be a fraction of that.
$ ever install os
Resolving ever-os...
→ Found ever-os-cli@0.3.1 on npm
Installing...
→ npm install -g ever-os-cli
→ Binary installed at /usr/local/bin/ever-os
→ Short alias installed at /usr/local/bin/os
Registered in ~/.ever/plugins.json
✓ ever os is ready. Try: ever os --help or os --help
The installer should support multiple sources:
# Auto-detect (checks npm first, then cargo, then GitHub releases)
ever install os
# Explicit source
ever install os --from npm
ever install os --from cargo
ever install os --from github
# Specific version
ever install os@1.2.3Resolution order (auto-detect):
- Check if a known mapping exists in a built-in product catalog (hardcoded in the router, updated with router releases).
- Try npm:
npm install -g ever-<product>-cli - Try cargo:
cargo install ever-<product>-cli - Try GitHub releases:
https://github.com/ever-co/ever-<product>-cli/releases/latest
The router ships with a hardcoded catalog that maps product names to package coordinates. This enables ever install os to know where to look without guessing:
{
"os": { "npm": "ever-os-cli", "crate": "ever-os-cli", "repo": "ever-co/ever-os-cli" },
"teams": { "npm": "ever-teams-cli", "crate": "ever-teams-cli", "repo": "ever-co/ever-teams-cli" },
"gauzy": { "npm": "ever-gauzy-cli", "crate": "ever-gauzy-cli", "repo": "ever-co/ever-gauzy-cli" },
"works": { "npm": "ever-works-cli", "crate": "ever-works-cli", "repo": "ever-co/ever-works-cli" },
"rec": { "npm": "ever-rec-cli", "crate": "ever-rec-cli", "repo": "ever-co/ever-rec-cli" },
"hust": { "npm": "ever-hust-cli", "crate": "ever-hust-cli", "repo": "ever-co/ever-hust-cli" },
"jobs": { "npm": "ever-jobs-cli", "crate": "ever-jobs-cli", "repo": "ever-co/ever-jobs-cli" },
"dev": { "npm": "ever-dev-cli", "crate": "ever-dev-cli", "repo": "ever-co/ever-dev-cli" },
"cloc": { "npm": "ever-cloc-cli", "crate": "ever-cloc-cli", "repo": "ever-co/ever-cloc-cli" },
"demand": { "npm": "ever-demand-cli", "crate": "ever-demand-cli", "repo": "ever-co/ever-demand-cli" },
"traduora": { "npm": "ever-traduora-cli", "crate": "ever-traduora-cli", "repo": "ever-co/ever-traduora-cli" },
"tech": { "npm": "ever-tech-cli", "crate": "ever-tech-cli", "repo": "ever-co/ever-tech-cli" },
"saas": { "npm": "ever-saas-cli", "crate": "ever-saas-cli", "repo": "ever-co/ever-saas-cli" },
"docs": { "npm": "ever-docs-cli", "crate": "ever-docs-cli", "repo": "ever-co/ever-docs-cli" },
"digital": { "npm": "ever-digital-cli", "crate": "ever-digital-cli", "repo": "ever-co/ever-digital-cli" },
"shop": { "npm": "ever-shop-cli", "crate": "ever-shop-cli", "repo": "ever-co/ever-shop-cli" },
"iq": { "npm": "ever-iq-cli", "crate": "ever-iq-cli", "repo": "ever-co/ever-iq-cli" }
}This catalog is shipped as static data inside the router binary. It can also be augmented at runtime from a remote endpoint (e.g. https://cli.ever.co/catalog.json) for discovering new products without upgrading the router.
Every product CLI that integrates with the ever router MUST follow these rules:
Each sub-CLI package MUST register two bin entries pointing to the same executable: the short alias and the prefixed name.
npm example (package.json):
{
"name": "ever-os-cli",
"version": "0.3.1",
"bin": {
"os": "./bin/cli.js",
"ever-os": "./bin/cli.js"
}
}Both os and ever-os are symlinked to the same script on npm install -g. The third invocation mode (ever os) is handled by the ever router, not by the package's bin field.
Rust example (Cargo.toml):
[package]
name = "ever-os-cli"
version = "0.3.1"
[[bin]]
name = "ever-os"
path = "src/main.rs"
[[bin]]
name = "os"
path = "src/main.rs"The sub-CLI receives everything after the product name. It must NOT expect "os" as its first argument. All three invocation modes produce identical argv:
Mode A (router): ever os run agents --verbose
Mode B (prefixed): ever-os run agents --verbose
Mode C (short): os run agents --verbose
All three → Sub-CLI receives: ["run", "agents", "--verbose"]
The sub-CLI binary detects how it was invoked by inspecting argv[0] but this should not affect behavior — all three modes are functionally identical.
Standard Unix conventions:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
General error |
2 |
Usage / argument error |
126 |
Command found but not executable |
127 |
Command not found (sub-sub-command) |
130 |
Interrupted (Ctrl+C / SIGINT) |
Sub-CLIs SHOULD read ~/.ever/config.toml for shared settings (auth, org, API endpoint). They MAY maintain their own product-specific config under ~/.ever/<product>/ if needed.
~/.ever/
├── config.toml # Shared (auth, org, API endpoint)
├── plugins.json # Router manifest
├── os/
│ └── config.toml # ever-os specific settings
├── teams/
│ └── config.toml # ever-teams specific settings
└── ...
Sub-CLIs SHOULD include a header line identifying themselves and showing all invocation methods:
$ os --help
ever-os 0.3.1 — Ever OS command-line interface
USAGE:
os <command> [options]
ever-os <command> [options]
ever os <command> [options]
COMMANDS:
run Run OS agents
plugin Manage plugins
config Configure ever-os
...
$ ever os --version
ever-os 0.3.1
$ os --version
ever-os 0.3.1Every sub-CLI is accessible via a short alias that omits the ever- prefix. This means cloc start timer, teams notify kostya, and gauzy export invoices all work as top-level commands.
For npm packages: The bin field in package.json registers both names pointing to the same script. When a user runs npm install -g ever-cloc-cli, both cloc and ever-cloc are symlinked into the user's PATH.
{
"bin": {
"cloc": "./bin/cli.js",
"ever-cloc": "./bin/cli.js"
}
}For Rust crates: Two approaches:
Option A — Multiple bin entries (same source, preferred):
[[bin]]
name = "ever-cloc"
path = "src/main.rs"
[[bin]]
name = "cloc"
path = "src/main.rs"Option B — Post-install symlink:
The install script creates a symlink: ln -sf ever-cloc /usr/local/bin/cloc
Short aliases like teams, rec, demand are unlikely to conflict with existing system commands. However, some names carry higher risk:
| Alias | Conflict Risk | Notes |
|---|---|---|
os |
Low | No standard binary uses this name |
dev |
Medium | Some systems have /dev references; unlikely binary conflict |
cloc |
cloc is a well-known lines-of-code counter tool |
|
jobs |
jobs is a Bash/Zsh shell built-in for background job control |
|
tech |
Low | No known conflicts |
docs |
Low | No known conflicts |
shop |
Low | No known conflicts |
digital |
Low | No known conflicts |
demand |
Low | No known conflicts |
rec |
Low | No known conflicts |
hust |
Low | No known conflicts |
gauzy |
None | Unique name |
teams |
Low | No standard binary (Microsoft Teams is a GUI app, not a CLI) |
traduora |
None | Unique name |
saas |
Low | No known conflicts |
iq |
Low | No known conflicts |
works |
Low | No known conflicts |
Conflict resolution strategy:
- The sub-CLI npm package registers the short alias in
binby default. - If a user already has a conflicting binary (e.g. they have the
clocline-counter installed), npm will warn on install. The user can still invoke viaever-clocorever cloc. - The
ever doctorcommand should detect and report alias conflicts:
$ ever doctor
Checking short aliases...
✓ gauzy → /usr/local/bin/gauzy (ever-gauzy-cli)
✓ teams → /usr/local/bin/teams (ever-teams-cli)
⚠ cloc → /usr/bin/cloc (CONFLICT: existing binary found, not ever-cloc)
The 'cloc' alias is shadowed by an existing binary.
Use 'ever cloc' or 'ever-cloc' instead.
✓ demand → /usr/local/bin/demand (ever-demand-cli)
When a user types a bare command like cloc start timer, the shell resolves it via standard PATH lookup. The command that appears first in PATH wins. There is no special Ever-level logic for short aliases — they are just regular binaries/symlinks on PATH.
The three invocation modes have different resolution paths:
| Mode | Resolution | Requires |
|---|---|---|
ever cloc <cmd> |
Router looks up manifest/PATH for ever-cloc |
ever router installed |
ever-cloc <cmd> |
Direct PATH lookup for ever-cloc binary |
Sub-CLI installed |
cloc <cmd> |
Direct PATH lookup for cloc binary (short alias) |
Sub-CLI installed, no conflicts |
The root ever CLI intercepts these flags BEFORE routing:
| Flag | Description |
|---|---|
--version, -V |
Print router version |
--help, -h |
Print router help (when no product specified) |
--verbose |
Enable verbose output (also forwarded to sub-CLI) |
--no-color |
Disable colored output (also forwarded to sub-CLI) |
--config <path> |
Override config file path |
Important: When a product IS specified, --help and --version are forwarded to the sub-CLI, not intercepted by the router.
ever --help # Router help
ever os --help # Forwarded to ever-os
ever --version # Router version
ever os --version # Forwarded to ever-os
# Short aliases work the same way:
os --help # ever-os help (direct, no router involved)
os --version # ever-os version (direct)$ ever list
Ever CLI v1.0.0 — https://ever.co
PRODUCT STATUS VERSION SOURCE
gauzy ✓ installed 1.2.0 npm
os ✓ installed 0.3.1 cargo
teams ✓ installed 2.1.0 npm
works ✓ installed 0.5.0 npm
rec ✗ not installed
hust ✗ not installed
jobs ✗ not installed
dev ✓ installed 0.1.0 path
cloc ✗ not installed
demand ✗ not installed
traduora ✗ not installed
tech ✗ not installed
saas ✗ not installed
docs ✗ not installed
digital ✗ not installed
shop ✗ not installed
iq ✗ not installed
Install a product: ever install <product>
Update all: ever update
$ ever doctor
Checking Ever CLI installation...
✓ Router binary: /usr/local/bin/ever (v1.0.0)
✓ Config directory: ~/.ever/
✓ Config file: ~/.ever/config.toml
✓ Manifest file: ~/.ever/plugins.json
✓ Auth token: configured
Checking installed products...
✓ ever-gauzy /usr/local/bin/ever-gauzy v1.2.0 OK
✓ ever-os /home/user/.cargo/bin/ever-os v0.3.1 OK
✗ ever-teams /usr/local/bin/ever-teams MISSING (binary not found at recorded path)
✓ ever-works /usr/local/bin/ever-works v0.5.0 OK
✓ ever-dev /usr/local/bin/ever-dev v0.1.0 OK
Issues found: 1
→ ever-teams: binary missing. Run: ever install teams
The router should support community-contributed sub-CLIs that are not in the built-in catalog. Users can register any binary manually:
# Register a custom/community sub-CLI
ever plugin add mycustomtool --binary /path/to/ever-mycustomtool
# Now it works
ever mycustomtool do-somethingThis allows the ecosystem to grow beyond Ever's own products. Any binary following the ever-<name> convention can plug in.
Since ever-cli and ever-works-cli already exist on npm:
-
Phase 1: Refactor the existing
ever-clinpm package to be the thin router described here. Any existing commands currently baked intoever-clishould be extracted into a product sub-CLI (likelyever-gauzyorever-dev, depending on what they do today). -
Phase 2: Wrap
ever-works-cliso its binary is renamed/aliased from whatever it is today toever-works. Register it in the built-in catalog. -
Phase 3: Build out new product sub-CLIs one at a time. Each is independent — no need to coordinate releases.
┌─────────────────────────────────────────────────────────────────────┐
│ Three ways to invoke — all equivalent: │
│ │
│ A) ever os run agents --verbose (via router) │
│ B) ever-os run agents --verbose (direct, prefixed) │
│ C) os run agents --verbose (direct, short alias) │
└───────┬──────────────────┬───────────────────┬──────────────────────┘
│ A │ B │ C
▼ │ │
┌──────────────────────┐ │ │
│ ever (router) │ │ │
│ │ │ │
│ 1. Parse: "os" │ │ │
│ 2. Lookup ever-os │ │ │
│ 3. exec(ever-os) │ │ │
└──────────┬───────────┘ │ │
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────────────────┐
│ ever-os (same binary, same behavior) │
│ │
│ argv: ["run", "agents", "--verbose"] │
│ │
│ → Runs agents │
└──────────────────────────────────────────────────────────────┘
The ever CLI is the front door to the entire Ever ecosystem. It stays thin, stable, and backwards-compatible. Product complexity lives in the sub-CLIs where it belongs. Short aliases let power users skip the router entirely for faster, more direct access.