DEV Community

Cover image for How I built a CLI tool to simplify my daily terminal workflow
Emanuele Strazzullo
Emanuele Strazzullo

Posted on

How I built a CLI tool to simplify my daily terminal workflow

As a developer, I live in the terminal. Every day I end up typing the same long commands: boot servers, build artifacts, sync repos, SSH into boxes, run one-off scripts. It’s fine… until it isn’t. I’d tweak flags, forget exact arguments, or copy–paste broken snippets.

I wanted something tiny, fast, and mine: a way to name the commands I use most and run them from anywhere with muscle‑memory simplicity.

That’s how mcl — My Command Line — was born.

🧠 The idea behind mcl

The “aha” moment came after repeating the same flows across projects. I didn’t want another framework. I wanted a thin layer over the shell where I could:

  • Describe commands once
  • Reuse them with arguments and variables
  • Keep them organized across projects
  • See what I have at a glance

With mcl you write small JSON recipes. For example:

{
  "scripts": {
    "say-hello": "echo 'Hello!'",
    "start-dev": "npm run dev"
  }
}
Enter fullscreen mode Exit fullscreen mode

Then you just run:

mcl say-hello
Enter fullscreen mode Exit fullscreen mode

No DSL. No ceremony. Just your shell, with a nicer memory.

⚙️ How it works (local vs global, args, vars)

mcl reads from two places and merges:

  • Local project config: ./mcl.json
  • Global config: ~/.mcl/global-mcl.json

Local overrides global, so you can keep common shortcuts globally (e.g., open-docs, deploy) and specialize per project.

It also supports:

  • Positional placeholders: $1, $2, … and optional ones like ?$1
  • Named vars: $project, $version via a vars object
  • Nested flows: scripts can be nested objects, e.g. example.date.utc
  • Dry-run mode: see exactly what would run before executing
  • Env sharing: --share-vars exports config vars and args to subprocesses

A richer example:

{
  "vars": {
    "project": "mcl",
    "version": "0.2.0"
  },
  "scripts": {
    "example": {
      "hello": "echo Hello, $1!",
      "date": {
        "utc": "date -u"
      }
    },
    "build": {
      "win": "GOOS=windows GOARCH=amd64 wails build"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Run them like this:

mcl --dry-run example date utc
mcl build win
Enter fullscreen mode Exit fullscreen mode

And if you run plain mcl, it prints a handy list of available scripts (local first, then global).

Under the hood: it’s Python + Click, with strict type hints, pytest, mypy, and black. The CLI resolves your script path, applies substitutions, and executes steps in order.

🚀 What’s next

Here’s what I’m exploring next to make mcl smarter, safer, and more shareable:

  • AI‑assisted recipe generator: analyze your repo (Dockerfile, package.json, pyproject, Makefile, CI) and propose a ready‑to‑use mcl.json with common tasks.
  • Natural language → command recipes: “build and publish the docker image” becomes a reproducible script (with a dry‑run preview first).
  • Smart discovery and autocomplete: fuzzy search across local/global scripts, inline arg hints, and quick previews of what will run.
  • Safety checks: secret/unsafe flag linting and an optional “explain this command” powered by an LLM before you execute.
  • Team sharing & sync: share curated script packs across repos (and optionally sync via a gist or a small registry).
  • Plugin hooks & marketplace: pre/post hooks, custom resolvers, and reusable packs (e.g., Docker, Git, Node, Python).
  • Config schema validation (Pydantic) and optional YAML support.
  • Multi‑platform test matrix (tox) to keep behavior consistent across OSes and shells.

📦 Try it out

Quick start:

# install (recommended)
pipx install mcl-tool

# or in a virtual environment
pip install mcl-tool

# initialize a local config
mcl init

# run your scripts
mcl <script> [args...]
Enter fullscreen mode Exit fullscreen mode

If this sounds useful, a ⭐️ on GitHub helps a ton — and I’d love to hear your feedback or feature ideas. Let’s make the terminal a bit more ergonomic together.

Top comments (0)