Skip to main content
skill CX Codex

add-command — Claude Code skill: what it does, how to install

Guides the step-by-step addition of new CLI commands into Dippy. It separates read-only tools from subcommands that require custom flag parsing.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add ldayton/Dippy --skill add-command -a claude-code
Open on GitHub

What add-command does

This skill guides developers through integrating external CLI tools into Dippy. It starts by investigating command behavior via tldr docs, man, or --help flags. This research separates read-only executions from system-modifying operations.

Next comes the design branch. Commands that remain completely safe regardless of arguments go into SIMPLE_SAFE inside src/dippy/core/allowlists.py. Complex commands with destructive flags get a dedicated handler in src/dippy/cli/<command>.py accompanied by pytest cases under tests/cli/.

The workflow strictly relies on the Dippy repository structure and the just command runner. You cannot finish the integration without passing just check.

What it helps with

  • register read-only CLI tools in SIMPLE_SAFE
  • generate pytest suites for dangerous command subcommands
  • write classification handlers inside src/dippy/cli/
  • validate CLI rules against just test and just check

Example prompts for the agent

  • /add-command git
  • /add-command docker
  • Add support for ripgrep using /add-command

How to install add-command

1Skills CLI (Vercel)

npx skills add ldayton/Dippy --skill add-command -a claude-code

2Manually: put the files in place

~/.claude/skills/add-command/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/add-command/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about add-command

How to install add-command in Claude Code?

Run npx skills add ldayton/Dippy --skill add-command -a claude-code. The skill file lands in ~/.claude/skills/add-command/SKILL.md.

What is the difference between SIMPLE_SAFE and a Handler?

SIMPLE_SAFE handles tools that are strictly read-only regardless of flags. A handler inspects subcommands and flags in Python to allow safe actions or ask for user confirmation.

How do you verify the newly added command?

Run just test to resolve test failures, followed by just check, which must pass before completing the task.

Source text

SKILL.md · MIT
---
name: add-command
description: Add support for a new CLI command. Use when implementing a handler or adding to SIMPLE_SAFE.
argument-hint: <command>
disable-model-invocation: true
---

Add support for `$ARGUMENTS` in Dippy.

## 1. Research

**tldr pages:**
```
ls ~/source/tldr/pages/*/$ARGUMENTS*.md
cat ~/source/tldr/pages/*/$ARGUMENTS.md
```

**CLI docs:**
```
$ARGUMENTS --help
man $ARGUMENTS
```

Note which operations are read-only vs mutations.

## 2. Decide: Handler or SIMPLE_SAFE?

- **SIMPLE_SAFE**: Always safe regardless of arguments (read-only, no destructive flags). Go to step 3A.
- **Handler**: Needs subcommand/flag analysis. Go to step 3B.

## 3A. SIMPLE_SAFE Path

Add to `SIMPLE_SAFE` in `src/dippy/core/allowlists.py` and add tests to `tests/test_simple.py` in the appropriate category. Skip to step 5.

## 3B. Handler Path

Create `tests/cli/test_$ARGUMENTS.py`:

```python
"""Test cases for $ARGUMENTS."""

import pytest
from conftest import is_approved, needs_confirmation

TESTS = [
    # Safe operations
    ("$ARGUMENTS <safe-subcommand>", True),
    ("$ARGUMENTS --help", True),
    # Unsafe operations
    ("$ARGUMENTS <unsafe-subcommand>", False),
]

@pytest.mark.parametrize("command,expected", TESTS)
def test_command(check, command: str, expected: bool):
    result = check(command)
    if expected:
        assert is_approved(result), f"Expected approve: {command}"
    else:
        assert needs_confirmation(result), f"Expected confirm: {command}"
```

## 4. Implement Handler

Create `src/dippy/cli/$ARGUMENTS.py`:

```python
"""$ARGUMENTS handler for Dippy."""

from dippy.cli import Classification, HandlerContext

COMMANDS = ["$ARGUMENTS"]

SAFE_ACTIONS = frozenset({"list", "show", "status"})

def classify(ctx: HandlerContext) -> Classification:
    tokens = ctx.tokens
    action = tokens[1] if len(tokens) > 1 else None
    if action in SAFE_ACTIONS:
        return Classification("allow", description=f"$ARGUMENTS {action}")
    return Classification("ask", description="$ARGUMENTS")
```

For handler patterns (nested subcommands, flag-checking, delegation), see [patterns.md](patterns.md).

## 5. Iterate

```
just test
```

Fix failures until tests pass.

## 6. Verify

`just check` MUST pass before you're done.

© ldayton · MIT · ldayton/Dippy

Similar skills

All skills for Security →

From the same set5

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor