found

found is a command for Claude Code from john-broadway/maude-for-claude. It costs 67 tokens per session (3,670 once invoked), scanned B, original, Apache-2.0.

A workspace inventory command that records paths and basic file shapes in a house map.

In plain words
What is it for?
Use it first in a project to scan the workspace, include relevant memory locations, and create or refresh .maude/plugin/house-map.md.
Why use it?
It gives a new project a repeatable starting inventory without interpreting or changing what the files mean.

Command for Claude Code

Written for Claude Code: argument-hint in frontmatter. Also seen: reads .claude/ paths; mentions CLAUDE.md; positional $N argument.

Runs only inside its plugin — its command needs a path that Claude Code sets for a plugin’s own hooks and for nothing else. Install the plugin, not this.

Part of the maude plugin — 1 skill, 15 commands, 1 agent, 8 hooks shipped together

Good fit Use it first in a project to scan the workspace, include relevant memory locations, and create or refresh .maude/plugin/house-map.md.

Compare 6 commands from other repositories ↓
Install

Getting it into your agent

This one installs as part of its plugin. Adding the marketplace and installing the plugin brings it with everything else the plugin ships.

Claude Code
/plugin marketplace add john-broadway/maude-for-claude
Claude Code
/plugin install maude

Made for: Claude Code.

Or install maude, the plugin that ships this one along with the rest of its 1 skill, 15 commands, 1 agent, 8 hooks.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for found

README.md
[![agentmods](https://agentmods.dev/badge/commands/john-broadway/maude-for-claude/found.svg)](https://agentmods.dev/commands/john-broadway/maude-for-claude/found)
Your own site
<a href="https://agentmods.dev/commands/john-broadway/maude-for-claude/found"><img src="https://agentmods.dev/badge/commands/john-broadway/maude-for-claude/found.svg" alt="Measured on agentmods" height="20"></a>
Per session 67 Only the description is in the session, so the agent can decide to use it. The body loads when it is invoked.
When invoked 3,670 The whole file, excluding the scripts and references it only reads on demand.
Security scan B 1 finding. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00067 $0.03670
Opus 5 $0.00034 $0.01835
Sonnet 5 $0.00013 $0.00734
Haiku 4.5 $0.00007 $0.00367

Measured 7d ago against content hash 6b82c2b212c1, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-07, from the pricing page.

Security

Grade B, and why

found scanned grade B with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 7d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Asks for rootmediumPrivilege escalation

A mod that escalates privileges can change anything on the machine, not only the project.

elif sudo -n docker ps --format '{{.Names}}' >/dev/null 2>&1; then
commands/found.md · 246 lines

How it starts

The opening of the file, as written. The whole thing — 246 lines — stays where its author put it; the contents beside it link to each section on GitHub.

/maude:found

You are Maude. You just moved in — this is home now. Walk our house and take inventory. List what's there. Don't interpret. The user (or your runtime reasoning) decides what each thing means.

What to do

  1. Compute paths:

    PROJ="${CLAUDE_PROJECT_DIR:-$(pwd)}"
    SLUG="$(printf %s "$PROJ" | sed 's/[^a-zA-Z0-9]/-/g')"
    MEM="$HOME/.claude/projects/$SLUG/memory"
    SELF="$PROJ/.maude/plugin"
    USER_DIR="$HOME/.claude/maude"
    REMEMBER="$PROJ/.remember"
    mkdir -p "$SELF/trace"
    mkdir -p "$USER_DIR"
    [ -f "$SELF/.gitignore" ] || echo '*' > "$SELF/.gitignore"
    MAP="$SELF/house-map.md"
    
  2. Walk: list what's there with universal-shape labels only. No app/framework recognition.

    cd "$PROJ"
    
    # Anthropic auto-memory (Claude Code's own convention — universal in this ecosystem)
    [ -d "$MEM" ] && ls -la "$MEM" 2>/dev/null
    
    # remember plugin (sibling Claude Code plugin in the official marketplace)
    if [ -d "$REMEMBER" ]; then
      echo "FOUND: $REMEMBER (remember plugin — has its own pipeline)"
      ls "$REMEMBER"/*.md 2>/dev/null | head
    fi
    
    # Top-level entries (excluding noise). Just list — don't classify.
    for entry in *; do
      case "$entry" in
        .git|node_modules|__pycache__|.cache|.venv|venv|dist|build|target|vendor) continue ;;
      esac
      [ -e "$entry" ] && echo "TOP-LEVEL: $entry"
    done
    for entry in .[!.]*; do
      [ -e "$entry" ] || continue
      case "$entry" in .git|.cache|.venv) continue ;; esac
      echo "DOTFILE: $entry"
    done
    
    # SQLite databases — find candidates, schema-walk only. Don't pattern-match the schema.
    if command -v sqlite3 >/dev/null 2>&1; then
      find . -maxdepth 5 \
             \( -path './.git' -o -path './node_modules' -o -path './__pycache__' \
                -o -path './.cache' -o -path './.venv' -o -path './venv' \
                -o -path './dist' -o -path './build' \) -prune -o \
             -type f \( -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' \) \
             -not -name '*-shm' -not -name '*-wal' -print 2>/dev/null \
        | while read -r dbpath; do
            if file "$dbpath" 2>/dev/null | grep -qi 'sqlite'; then
              echo "FOUND DB: $dbpath"
              TABLES="$(sqlite3 -readonly "$dbpath" '.tables' 2>/dev/null | tr '\n' ' ' | head -c 400)"
              SCHEMA_HEAD="$(sqlite3 -readonly "$dbpath" '.schema' 2>/dev/null | head -10)"
              if [ -n "$TABLES" ] || [ -n "$SCHEMA_HEAD" ]; then
                echo "  tables: $TABLES"
                echo "  schema (first 10 lines):"
                printf '%s\n' "$SCHEMA_HEAD" | sed 's/^/    /'
              else
                echo "  schema unreadable (encrypted, locked, or empty)"
              fi
            fi
          done
    else
      echo "DB SCAN SKIPPED: sqlite3 CLI not installed (apt install sqlite3 to enable)"
    fi
    
    # Python interpreter version — just to know what's available. Don't probe specific packages.
    command -v python3 >/dev/null && python3 -c "import sys; print('python:', sys.version.split()[0])" 2>/dev/null
    
    # Local clock — detect a CANDIDATE timezone, but it must be CONFIRMED before trusting it.
    # A server/container box is usually UTC, which is NOT the user's timezone. Greeting by an
    # unconfirmed box clock is how the wrong time-of-day gets said.
    SYS_TZ=""
    command -v timedatectl >/dev/null 2>&1 && SYS_TZ="$(timedatectl show -p Timezone --value 2>/dev/null)"
    [ -z "$SYS_TZ" ] && [ -f /etc/timezone ] && SYS_TZ="$(cat /etc/timezone 2>/dev/null)"
    [ -z "$SYS_TZ" ] && [ -L /etc/localtime ] && SYS_TZ="$(readlink /etc/localtime 2>/dev/null | sed 's#.*/zoneinfo/##')"
    echo "CLOCK: box timezone candidate = ${SYS_TZ:-unknown}; box time now = $(date '+%Y-%m-%d %H:%M %Z')"
    
    # Running services — universal-shape only. Containers and their workspace bind mounts.
    # Filesystem walks miss anything that exists as a process; this catches running stacks
    # whose state is held open via bind mounts into the workspace.
    if command -v docker >/dev/null 2>&1; then
      # Pick the first invocation that actually answers (no creds → no creds, don't loop).
      if docker ps --format '{{.Names}}' >/dev/null 2>&1; then
        DOCKER="docker"
      elif sudo -n docker ps --format '{{.Names}}' >/dev/null 2>&1; then
        DOCKER="sudo -n docker"
      else
        DOCKER=""
        echo "DOCKER PRESENT: yes — but not accessible from this shell. Surface to user; suggest 'sudo docker ps' on next walk."
      fi
    
      if [ -n "$DOCKER" ]; then
        RUNNING="$($DOCKER ps --format '{{.Names}}' 2>/dev/null)"
        if [ -n "$RUNNING" ]; then
          echo "RUNNING CONTAINERS:"
          $DOCKER ps --format '  {{.Names}} ({{.Image}}, {{.Status}})' 2>/dev/null
          echo "BIND MOUNTS touching this workspace ($PROJ):"
          echo "$RUNNING" | while read -r cn; do
            [ -z "$cn" ] && continue
            $DOCKER inspect "$cn" --format '{{range .Mounts}}{{if eq .Type "bind"}}{{.Source}}|{{.Destination}}{{"\n"}}{{end}}{{end}}' 2>/dev/null \
              | while IFS='|' read -r src dst; do
                  [ -z "$src" ] && continue
                  case "$src" in
                    "$PROJ"|"$PROJ"/*) ;;
                    *) continue ;;
                  esac
                  if [ ! -e "$src" ]; then
                    echo "  [ORPHAN]  $cn  $src → $dst  (source path missing)"
                  elif [ -d "$src" ] && [ "$(stat -c %U "$src" 2>/dev/null)" = "root" ] && [ -z "$(ls -A "$src" 2>/dev/null)" ]; then
                    echo "  [GHOST]   $cn  $src → $dst  (root-owned + empty — likely auto-created bind stub)"
                  else
                    echo "  [OK]      $cn  $src → $dst"
                  fi
                done
          done
          # Stopped containers that *did* hold workspace bind paths — they're often the
          # tell-tale of a directory rename that broke a stack.
          STOPPED="$($DOCKER ps -a --filter status=exited --format '{{.Names}}' 2>/dev/null)"
          if [ -n "$STOPPED" ]; then
            echo "STOPPED CONTAINERS with workspace bind mounts (may be rename orphans):"
            echo "$STOPPED" | while read -r cn; do
              [ -z "$cn" ] && continue
              $DOCKER inspect "$cn" --format '{{range .Mounts}}{{if eq .Type "bind"}}{{.Source}}{{"\n"}}{{end}}{{end}}' 2>/dev/null \
                | while read -r src; do
                    [ -z "$src" ] && continue
                    case "$src" in "$PROJ"|"$PROJ"/*) echo "  $cn  $src" ;; esac
                  done
            done
          fi
        else
          echo "DOCKER: available, no containers running"
        fi
      fi
    else
      echo "DOCKER NOT AVAILABLE: container scan skipped"
    fi
    
    # systemd — only flag units whose WorkingDirectory or ExecStart references the workspace.
    # Don't dump the full unit list; that's noise.
    if command -v systemctl >/dev/null 2>&1; then
      for scope in --user ""; do
        systemctl $scope list-units --type=service --state=active --no-legend --no-pager 2>/dev/null \
          | awk '{print $1}' \
          | while read -r u; do
              [ -z "$u" ] && continue
              props="$(systemctl $scope show "$u" --property=WorkingDirectory,ExecStart,FragmentPath --no-pager 2>/dev/null)"
              echo "$props" | grep -qF "$PROJ" && echo "SYSTEMD UNIT references workspace: $u (${scope:---system})"
            done
      done
    fi
    

Read the full file on GitHub · 246 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 7d ago First seen · 246 lines · 67 tokens per session scan B 6b82c2b212c1

Subscribe to this mod's changes

found is a command published in the GitHub repository john-broadway/maude-for-claude (2 stars, last pushed 5d ago), licensed Apache-2.0. It adds 67 tokens to every session and 3,670 once invoked, about $0.0003 per session on Opus 5. A static security scan graded it B with 1 finding (asks for root). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.