# Shell Handoff

> shell-handoff

- Skill: `jasonkneen/shell-handoff` (Agent Skill)
- Install (CLI): `npx skillmds@latest add jasonkneen/shell-handoff`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jasonkneen/shell-handoff/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: jasonkneen (https://skillmd.com/u/jasonkneen)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/jasonkneen/shell-handoff

---

# shell-handoff

Make a skill or wrapper invokable from the user's shell as a command, *without* writing to PATH directories. The sandbox blocks writes to `~/bin/`, `/usr/local/bin/`, etc. by design — that boundary exists so the agent never silently defines what happens when the user types a command. Hand off through an explicit aliases file the user sources from their shell config.

## When to use

- Wrapping `lazar` (renderer, formatter, custom invocation flags).
- Authoring any skill that "should be a shell command" (e.g. `glazar`, `lt`, `note`).
- Anytime you'd otherwise reach for `cp foo ~/bin/` or `cp foo /usr/local/bin/` and hit `Operation not permitted`.

## How to use

The aliases file lives at:

    $LAZAR_HOME/workspace/aliases.sh

Workspace is in the writable allowlist. `--reset-all` wipes workspace, so aliases vanish predictably — the agent's user-facing surface always matches its current state.

### Recipe

1. Ensure the aliases file exists with a header:

       mkdir -p $LAZAR_HOME/workspace
       if [ ! -f $LAZAR_HOME/workspace/aliases.sh ]; then
         cat > $LAZAR_HOME/workspace/aliases.sh <<'EOF'
       # lazar shell aliases — generated by skills.
       # Source from .zshrc:
       #   [ -f $LAZAR_HOME/workspace/aliases.sh ] && source $LAZAR_HOME/workspace/aliases.sh
       EOF
       fi

2. Append your alias or function (always include a marker comment so duplicates can be detected and removed later):

       # simple alias
       cat >> $LAZAR_HOME/workspace/aliases.sh <<'EOF'

       # alias: <name> (skill: <skill-name>)
       alias <name>='<command>'
       EOF

       # function form (when args matter)
       cat >> $LAZAR_HOME/workspace/aliases.sh <<'EOF'

       # function: <name> (skill: <skill-name>)
       <name>() {
         lazar -p "$*" 2>/dev/null | glow -
       }
       EOF

3. Tell the user what just happened. If aliases.sh didn't exist before, this is their first-time setup:

       Add this one line to ~/.zshrc (or ~/.bashrc):
           [ -f $LAZAR_HOME/workspace/aliases.sh ] && source $LAZAR_HOME/workspace/aliases.sh
       Then: source ~/.zshrc

   If aliases.sh already existed, just tell them: `source ~/.zshrc` (or open a new shell) to pick up the new alias.

### Idempotency

Before appending, check whether the alias is already there:

    rg -q "^alias <name>=" $LAZAR_HOME/workspace/aliases.sh || \
      cat >> $LAZAR_HOME/workspace/aliases.sh <<'EOF'
    ...
    EOF

### Removal

To remove an alias, edit aliases.sh in place. Each alias has a marker comment (`# alias: <name>` or `# function: <name>`) — use sed to drop the block:

    sed -i '' "/# alias: <name>/,/^$/d" $LAZAR_HOME/workspace/aliases.sh

## Principle

The agent never writes to the user's PATH. The user sources one file. Every shell command the agent has provided is auditable with `cat $LAZAR_HOME/workspace/aliases.sh` — no surprises.

This pattern composes cleanly with `--reset-all`: workspace is wiped, aliases vanish next shell, the user's environment is back to default. No drift between agent state and shell state.

