Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Unformal Notifications

v1.1.0

Get notified when someone completes an Unformal Pulse — via a scheduled Claude Code routine (hourly), a local desktop listener (real-time macOS notifications...

0· 28·0 current·0 all-time
byJonas Boury@jonasboury
Security Scan
Capability signals
Requires sensitive credentials
These labels describe what authority the skill may exercise. They are separate from suspicious or malicious moderation verdicts.
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The skill's name/description match the included script and SKILL.md: it polls Unformal and surfaces notifications. Requiring an Unformal API key and writing marker/inbox files in ~/.unformal is consistent with the stated purpose. However, the registry metadata declares no required env vars/primary credential while the SKILL.md and script clearly require UNFORMAL_API_KEY—an omission that reduces transparency and is unexpected.
!
Instruction Scope
Runtime instructions explicitly read/write files under the user's home (~/.unformal, ~/.unformal/last-seen, ~/.claude/scheduled-tasks/...), suggest sourcing arbitrary local secret files, and recommend embedding an API key inline into generated SKILL.md. Embedding secrets into files that live under ~/.claude or in a scheduled routine increases the risk of secret leakage. The script also instructs downloading an executable via curl and placing it in ~/bin—normal for CLI tools, but it increases attack surface if the source is untrusted.
Install Mechanism
There is no formal install spec in the registry, but SKILL.md advises using curl to fetch a single script from https://unformal.ai/unformal-listen.sh and saving it to ~/bin. Downloading a single script from the project's domain is common but still higher-risk than package-managed installs because it executes code fetched at install time. The package itself includes the script, which helps reviewability, but the user guidance to curl the upstream URL could fetch a different file later.
!
Credentials
The skill only needs an Unformal API key to function, which is proportionate. But the manifest does not declare this required env var (transparency problem). More importantly, the instructions explicitly suggest embedding the API key inline in SKILL.md or sourcing arbitrary local secrets files—both practices can expose credentials to other local apps or to any system/process that can read those files. The script itself accepts the key via env var or --key flag (good), but the guidance to embed keys into scheduled task files is risky.
Persistence & Privilege
The skill does not request always:true or any global privileges. It runs only when invoked (or when you create a local routine). It writes files only under the user's home (~/bin, ~/.unformal, ~/.claude scheduled-tasks) and does not modify other skills or system-wide settings—this is within expected bounds for a desktop notification helper.
What to consider before installing
This skill is coherent with its purpose (notify you about Unformal Pulse completions) but take these precautions before installing: - Expect to provide your UNFORMAL_API_KEY; the registry failed to declare it—verify you are comfortable supplying that key. - Do NOT embed your API key inline into generated SKILL.md or other files unless you understand the file's storage/permissions; prefer setting UNFORMAL_API_KEY in your shell profile (~/.zshrc) or use a secure secret manager. - Inspect the unformal-listen.sh file you download; the repository package includes it so compare the downloaded copy with the one you reviewed. Prefer installing from a stable, signed release or a repository you control. - Limit file permissions on ~/.unformal and the scheduled task files (chmod 700/600) so other local users/processes can't read them. - If you need stronger isolation, run the listener in a dedicated container or separate account. If you want higher assurance, ask the publisher for: authoritative homepage/repo link, signed releases or checksums for the download URL, and an updated registry manifest that declares UNFORMAL_API_KEY as a required credential. If the publisher is unknown or you can't verify the download origin, treat the download/install step as higher risk.

Like a lobster shell, security has layers — review code before you run it.

agentsvk97bf0d7xw1234zat3dz5gwm6h85484qaivk97bf0d7xw1234zat3dz5gwm6h85484qlatestvk97bf0d7xw1234zat3dz5gwm6h85484qnotificationsvk97bf0d7xw1234zat3dz5gwm6h85484qrealtimevk97bf0d7xw1234zat3dz5gwm6h85484qssevk97bf0d7xw1234zat3dz5gwm6h85484qunformalvk97bf0d7xw1234zat3dz5gwm6h85484qwebhooksvk97bf0d7xw1234zat3dz5gwm6h85484q
28downloads
0stars
1versions
Updated 13h ago
v1.1.0
MIT-0

Unformal Notifications

Three ways to get notified about new responses on your Unformal Pulse. Pick one — or combine.

When to use this skill

Trigger on any of these:

  • "any new Unformal responses?"
  • "check my Unformal"
  • "who completed the [pulse name]?"
  • "summarize today's responses"
  • "set up a routine to check my Pulse"
  • "notify me when responses come in"
  • "did anyone finish the survey?"

Prerequisites

  • An Unformal API key — get one at unformal.ai/studio/settings or via POST /api/v1/signup
  • A Pulse ID — from GET /api/v1/pulses or the Studio URL

Option A — Claude Code desktop routine (recommended)

Best for: always-on monitoring that shows up in your Claude Code desktop sidebar alongside your other routines. Runs locally, can use your local secrets files, and you pick the schedule visually in the desktop UI.

Ask Claude:

"Create a Claude Code desktop routine called unformal-new-responses that checks for new completed responses on my Unformal Pulse <PULSE_ID> using API key <API_KEY>. It should track the last-seen timestamp in ~/.unformal/last-seen, only fetch new responses since that marker, and give me a concise digest (sentiment + summary + key quotes) or say 'No new responses' if there are none."

What Claude does

Creates a directory at ~/.claude/scheduled-tasks/<routine-name>/ containing a single SKILL.md file with:

---
name: unformal-new-responses
description: Check for new completed responses on active Unformal Pulses
---

1. Load secrets: `source /path/to/load-secrets.sh` (optional — if keys are
   in a local env file, use it; otherwise embed API key inline)
2. Read marker: `SINCE=$(cat ~/.unformal/last-seen 2>/dev/null || echo 0)`
3. Fetch new responses:
   ```bash
   TMP=$(mktemp)
   curl -fsS "https://unformal.ai/api/v1/pulses/<PULSE_ID>/conversations?completedSince=$SINCE" \
     -H "Authorization: Bearer <API_KEY>" > "$TMP"
  1. Parse & summarize with Python (read from the temp file to keep heredoc stdin clean):
    python3 << PYEOF
    import json
    with open("$TMP") as f:
        d = json.load(f)
    items = d.get("data", [])
    completed = [c for c in items if c.get("status") == "completed"]
    if not completed:
        print("NONE")
    else:
        print("FOUND " + str(len(completed)))
        for c in completed:
            echo = c.get("echo") or {}
            print("---")
            print("id: " + str(c.get("id", "")))
            print("sentiment: " + str(echo.get("sentimentScore", "?")) + "/10")
            print("summary: " + (echo.get("summary") or "(no summary)")[:300])
            for q in (echo.get("keyQuotes") or [])[:3]:
                print("quote: " + str(q)[:200])
    PYEOF
    
  2. Update marker: python3 -c "import time; print(int(time.time()*1000))" > ~/.unformal/last-seen
  3. Report briefly if NONE, or present a clean digest if FOUND.

### Setting the schedule

After creating the SKILL.md file, the routine appears in the Claude Code desktop sidebar under "Routines". **Set the cron schedule from the desktop UI** — click the routine and pick Daily / Weekdays / Custom / etc. The schedule is stored by the desktop app; the SKILL.md only defines the task.

### Key points

- Runs locally on your machine (unlike remote triggers) — has access to `~/` and local secrets
- Does NOT appear in [claude.ai/code/scheduled](https://claude.ai/code/scheduled) (that's the remote triggers UI — a separate system)
- Minimum cadence is whatever the desktop UI allows (typically 1 minute+)
- You can edit the SKILL.md anytime; changes take effect on next run

---

## Option B — Local desktop listener (real-time macOS notifications)

**Best for**: live in-session awareness while you're actively working. Runs on your machine, shows native OS notifications the second a response comes in.

### One-time install

```bash
mkdir -p ~/bin
curl -fsS https://unformal.ai/unformal-listen.sh > ~/bin/unformal-listen
chmod +x ~/bin/unformal-listen
export UNFORMAL_API_KEY=unf_xxx   # add to ~/.zshrc for persistence

Run

unformal-listen                    # lists your Pulses
unformal-listen <pulse_id>         # starts listening

Leave it running in a spare terminal tab. Every completion:

  • Pops a native macOS notification (Linux: notify-send fallback)
  • Writes the event JSON to ~/.unformal/inbox/<timestamp>.json
  • Auto-reconnects on server-side timeouts

Option C — On-demand check (no setup)

Best for: one-off lookups. The user asks "any new responses?" and you query the API right there.

# Responses completed in the last hour
SINCE=$(python3 -c "import time; print(int(time.time()*1000) - 3600000)")
curl -fsS "https://unformal.ai/api/v1/pulses/<PULSE_ID>/conversations?completedSince=$SINCE" \
  -H "Authorization: Bearer $UNFORMAL_API_KEY" | \
  jq '[.data[] | select(.status=="completed")] | sort_by(.completedAt) | reverse'

For "since last check" semantics with a local marker file:

mkdir -p ~/.unformal
LAST=$(cat ~/.unformal/last-seen 2>/dev/null || echo 0)
curl -fsS "https://unformal.ai/api/v1/pulses/<PULSE_ID>/conversations?completedSince=$LAST" \
  -H "Authorization: Bearer $UNFORMAL_API_KEY"
python3 -c "import time; print(int(time.time()*1000))" > ~/.unformal/last-seen

Usage patterns (when the user asks you to check)

If Option B (listener) is running

Summarize the newest events from the inbox:

ls -t ~/.unformal/inbox/*.json 2>/dev/null | head -5 | while read f; do
  cat "$f" | jq -r '{
    completedAt: .completedAt,
    summary: (.echo.summary // .summary // "no summary"),
    sentiment: .echo.sentimentScore,
    quotes: (.echo.keyQuotes // [] | .[0:2])
  }'
done

If no listener is running

Fall back to the on-demand API call (Option C above).

After acting on events, archive

mkdir -p ~/.unformal/processed
mv ~/.unformal/inbox/*.json ~/.unformal/processed/ 2>/dev/null || true

What Claude can do with new responses

  • Flag hot leads (high sentiment + specific keywords) and draft follow-ups
  • Detect patterns across multiple completions and propose a Resonance-style summary
  • Save interesting quotes to a notes file
  • Trigger other skills (draft a Slack message, update a CRM, etc.)

Inbox event shape

Each file in ~/.unformal/inbox/ (and each element of the API .data[] array) looks like:

{
  "conversationId": "k17abc...",
  "pulseId": "k97xyz...",
  "echo": {
    "fields": {"budget_range": "$10k-20k", "timeline": "Q3"},
    "summary": "Strong fit. Mid-size agency ready to pilot.",
    "keyQuotes": ["We spend 3 hours weekly on status reports"],
    "sentimentScore": 7
  },
  "completedAt": "2026-04-17T10:32:01Z",
  "metadata": {"duration": 240, "messageCount": 12}
}

Related

Comments

Loading comments...