Back to skills
SkillHub ClubShip Full StackFull StackBackend

refly

Base skill for Refly ecosystem: creates, discovers, and runs domain-specific skills bound to workflows. Routes user intent to matching domain skills via symlinks, delegates execution to Refly backend. Use when user asks to: create skills, run workflows, automate multi-step tasks, or manage pipelines. Triggers: refly, skill, workflow, run skill, create skill, automation, pipeline. Requires: @refly/cli installed and authenticated.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
7,025
Hot score
99
Updated
March 19, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
B73.6

Install command

npx @skill-hub/cli install refly-ai-refly-skill

Repository

refly-ai/refly

Skill path: packages/cli/skill

Base skill for Refly ecosystem: creates, discovers, and runs domain-specific skills bound to workflows. Routes user intent to matching domain skills via symlinks, delegates execution to Refly backend. Use when user asks to: create skills, run workflows, automate multi-step tasks, or manage pipelines. Triggers: refly, skill, workflow, run skill, create skill, automation, pipeline. Requires: @refly/cli installed and authenticated.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack, Backend.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: refly-ai.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install refly into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/refly-ai/refly before adding refly to shared team environments
  • Use refly for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: refly
description: "Base skill for Refly ecosystem: creates, discovers, and runs domain-specific skills bound to workflows. Routes user intent to matching domain skills via symlinks, delegates execution to Refly backend. Use when user asks to: create skills, run workflows, automate multi-step tasks, or manage pipelines. Triggers: refly, skill, workflow, run skill, create skill, automation, pipeline. Requires: @refly/cli installed and authenticated."
---

# Refly

## Rules

1. **CLI only** - Use `refly <command>`, never call API directly.
2. **Trust JSON** - Only trust CLI JSON (`ok`, `payload`, `error`, `hint`).
3. **No fabricated IDs** - Never invent workflow/run/node IDs.
4. **No tokens** - Never print or request auth tokens.
5. **Stop on error** - If `ok=false`, stop and show `hint`.

## Available Commands

| Command | ID Format | Description |
|---------|-----------|-------------|
| `refly status` | - | Check authentication and connection status |
| `refly login` | - | Authenticate with Refly |
| `refly skill list` | - | List all available skills in the marketplace |
| `refly skill installations` | - | List your installed skills (get installationId here) |
| `refly skill run --id <installationId> --input '<json>'` | skpi-xxx | Run an installed skill, returns runId (we-xxx) |
| `refly workflow status <runId> --watch` | we-xxx | Watch workflow execution status |
| `refly workflow detail <runId>` | we-xxx | Get workflow run details |
| `refly workflow toolcalls <runId> --files --latest` | we-xxx | Get files from latest toolcall |
| `refly file download <fileId> -o <path>` | df-xxx | Download a file |

**Tip**: Get `installationId` (skpi-xxx) from `refly skill installations`.

### Command Options

| Command | Option | Description |
|---------|--------|-------------|
| `workflow status` | `--watch` | Poll until workflow completes |
| `workflow status` | `--interval <ms>` | Polling interval in milliseconds (default: 5000) |
| `workflow toolcalls` | `--files` | Return simplified output with only files and content |
| `workflow toolcalls` | `--latest` | With `--files`, return only files from the most recent toolcall |
| `workflow toolcalls` | `--raw` | Disable output sanitization (show full tool outputs) |

**Recommended**: Use `--files --latest` to get files from the final output without processing all toolcalls.

## Skill Categories & Execution Patterns

Choose the execution pattern based on the skill's output type:

| Category | Skills | Output | Pattern |
|----------|--------|--------|---------|
| **File Generation** | image, video, audio skills | Files (png/mp4/mp3) | Run → Wait → Download → Open |
| **Text/Data** | search, research, report skills | Text content | Run → Wait → Extract content |
| **Action** | email, messaging, integration skills | Status confirmation | Run → Wait → Confirm |

---

### Pattern A: File Generation Skills
**Use for**: nano-banana-pro, fal-image, fal-video, fal-audio, seedream-image, kling-video, wan-video

```bash
# Step 1: Run and capture RUN_ID
RESULT=$(refly skill run --id <installationId> --input '<json>')
RUN_ID=$(echo "$RESULT" | jq -r '.payload.workflowExecutions[0].id')

# Step 2: Wait for completion
refly workflow status "$RUN_ID" --watch --interval 30000

# Step 3: Get files and download to Desktop
FILES=$(refly workflow toolcalls "$RUN_ID" --files --latest | jq -r '.payload.files[]')
echo "$FILES" | jq -c '.' | while read -r file; do
  FILE_ID=$(echo "$file" | jq -r '.fileId')
  FILE_NAME=$(echo "$file" | jq -r '.name')
  if [ -n "$FILE_ID" ] && [ "$FILE_ID" != "null" ]; then
    refly file download "$FILE_ID" -o "$HOME/Desktop/${FILE_NAME}"
    open "$HOME/Desktop/${FILE_NAME}"
  fi
done
```

---

### Pattern B: Text/Data Skills
**Use for**: jina, perplexity, weather-report, exa, research skills

```bash
# Step 1: Run and capture RUN_ID
RESULT=$(refly skill run --id <installationId> --input '<json>')
RUN_ID=$(echo "$RESULT" | jq -r '.payload.workflowExecutions[0].id')

# Step 2: Wait for completion
refly workflow status "$RUN_ID" --watch --interval 30000

# Step 3: Extract text content from toolcalls
CONTENT=$(refly workflow toolcalls "$RUN_ID" --files --latest | jq -r '.payload.nodes[].content')
echo "$CONTENT"
```

---

### Pattern C: Action Skills
**Use for**: send-email, slack, microsoft-teams, zoom, calendar, CRM integrations

```bash
# Step 1: Run and capture RUN_ID
RESULT=$(refly skill run --id <installationId> --input '<json>')
RUN_ID=$(echo "$RESULT" | jq -r '.payload.workflowExecutions[0].id')

# Step 2: Wait for completion
refly workflow status "$RUN_ID" --watch --interval 30000

# Step 3: Confirm action status
STATUS=$(refly workflow detail "$RUN_ID" | jq -r '.payload.status')
echo "Action completed with status: $STATUS"
```

---

**ID Types:**
| ID Format | Example | Used For |
|-----------|---------|----------|
| `skpi-xxx` | skpi-h9kpmts9ho1kl9l1sohaloeu | `skill run --id` only |
| `we-xxx` | we-abc123def456 | `workflow status`, `workflow detail`, `workflow toolcalls` |
| `c-xxx` | c-g6emwcpi1wpalsz6j4gyi3d9 | Browser URL only |
| `df-xxx` | df-b3yxyelshtwsbxbrkmcqxmx9 | `file download` |
| `skpe-xxx` | skpe-qga5lpyv59yjzz2ghz2iv9bu | ⚠️ Do NOT use for workflow commands |

**Required behavior:**
- `skill run` returns `RUN_ID` (we-xxx) in `.payload.workflowExecutions[0].id`
- Use `we-xxx` for all workflow commands (`status`, `detail`, `toolcalls`)
- Choose execution pattern (A/B/C) based on skill category
- File skills: Download to `~/Desktop/` and `open` to show user
- Text skills: Extract `.payload.nodes[].content` for text output
- Action skills: Confirm `.payload.status` for completion

## Directory Structure

```
~/.refly/skills/
├── base/                       # Base skill files (this symlink target)
│   ├── SKILL.md
│   └── rules/
│       ├── execution.md
│       ├── workflow.md
│       ├── node.md
│       ├── file.md
│       └── skill.md
└── <skill-name>/               # Domain skill directories
    └── SKILL.md

~/.claude/skills/
├── refly → ~/.refly/skills/base/           # Base skill symlink
└── <skill-name> → ~/.refly/skills/<name>/  # Domain skill symlinks
```

## Routing

User intent -> match domain skill (name/trigger) in `~/.claude/skills/`
-> read domain skill `SKILL.md` -> execute via `refly skill run` -> return CLI-verified result.

## References

- `rules/execution.md` - **Skill execution patterns and error handling**
- `rules/workflow.md` - Workflow command reference
- `rules/node.md` - Node command reference
- `rules/file.md` - File command reference
- `rules/skill.md` - Customized Skill command reference


---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### references/execution.md

```markdown
# Skill Execution Reference

## Quick Reference

| Command | Purpose |
|---------|---------|
| `refly skill run --id <skpi-xxx> --input '<json>'` | Run skill, returns RUN_ID |
| `refly workflow status <we-xxx> --watch --interval 30000` | Wait for completion |
| `refly workflow detail <we-xxx>` | Get execution details and status |
| `refly workflow toolcalls <we-xxx> --files --latest` | Get files and text content |
| `refly file download <df-xxx> -o <path>` | Download file to local path |

## ID Formats

| Format | Example | Used For |
|--------|---------|----------|
| `skpi-xxx` | skpi-h9kpmts9ho1kl9l1sohaloeu | `skill run --id` only |
| `we-xxx` | we-abc123def456 | `workflow status`, `workflow detail`, `workflow toolcalls` |
| `c-xxx` | c-g6emwcpi1wpalsz6j4gyi3d9 | Browser URL only (https://refly.ai/workflow/c-xxx) |
| `df-xxx` | df-b3yxyelshtwsbxbrkmcqxmx9 | `file download` |
| `skpe-xxx` | skpe-qga5lpyv59yjzz2ghz2iv9bu | **Do NOT use** for workflow commands |

---

## Standard Execution Flow

### Step 1: Run Skill and Get Run ID

```bash
RESULT=$(refly skill run --id <installationId> --input '{
  "key": "value"
}')

# Check if command succeeded
if [ "$(echo "$RESULT" | jq -r '.ok')" != "true" ]; then
  echo "Error: $(echo "$RESULT" | jq -r '.error.message')"
  echo "Hint: $(echo "$RESULT" | jq -r '.hint // empty')"
  exit 1
fi

RUN_ID=$(echo "$RESULT" | jq -r '.payload.workflowExecutions[0].id')
echo "Run ID: $RUN_ID"
```

**Important**: Run ID is in `.payload.workflowExecutions[0].id` (we-xxx format)

### Step 2: Open Workflow in Browser and Wait for Completion

```bash
# Open workflow in browser (optional, for monitoring)
open "https://refly.ai/workflow/<workflowId>"

# Poll every 30 seconds until workflow finishes
refly workflow status "$RUN_ID" --watch --interval 30000
```

### Step 3: Get Results (Choose Based on Skill Category)

Choose the pattern based on the skill's `category` field in SKILL.md:
- `category: file-generation` → Pattern A
- `category: text-data` → Pattern B
- `category: action` → Pattern C

---

## Pattern A: File Generation Skills

**Use for**: Skills with `category: file-generation` (image, video, audio skills)

```bash
# Get files from the latest toolcall
TOOLCALL_RESULT=$(refly workflow toolcalls "$RUN_ID" --files --latest)

# Check if files exist
FILES=$(echo "$TOOLCALL_RESULT" | jq -r '.payload.files // empty')
if [ -z "$FILES" ] || [ "$FILES" = "null" ]; then
  echo "No files generated. Check workflow status:"
  refly workflow detail "$RUN_ID"
  exit 1
fi

# Download and open each file
echo "$FILES" | jq -c '.[]' | while read -r file; do
  FILE_ID=$(echo "$file" | jq -r '.fileId')
  FILE_NAME=$(echo "$file" | jq -r '.name')
  if [ -n "$FILE_ID" ] && [ "$FILE_ID" != "null" ]; then
    refly file download "$FILE_ID" -o "$HOME/Desktop/${FILE_NAME}"
    echo "Downloaded: $HOME/Desktop/${FILE_NAME}"
    open "$HOME/Desktop/${FILE_NAME}"
  fi
done
```

**Expected Output**: Files downloaded to `~/Desktop/` and opened automatically

---

## Pattern B: Text/Data Skills

**Use for**: Skills with `category: text-data` (search, research, report, analytics skills)

```bash
# Get text content from toolcalls
TOOLCALL_RESULT=$(refly workflow toolcalls "$RUN_ID" --files --latest)

# Extract content from nodes
CONTENT=$(echo "$TOOLCALL_RESULT" | jq -r '.payload.nodes[].content // empty')
if [ -z "$CONTENT" ]; then
  echo "No content returned. Check workflow status:"
  refly workflow detail "$RUN_ID"
  exit 1
fi

echo "$CONTENT"
```

**Expected Output**: Text content displayed to user

---

## Pattern C: Action Skills

**Use for**: Skills with `category: action` (email, messaging, CRM integration skills)

```bash
# Confirm action completed
DETAIL=$(refly workflow detail "$RUN_ID")
STATUS=$(echo "$DETAIL" | jq -r '.payload.status')

if [ "$STATUS" = "finish" ]; then
  echo "Action completed successfully"
else
  echo "Action status: $STATUS"
  echo "$DETAIL" | jq '.payload'
fi
```

**Expected Output**: Status confirmation (finish = success)

---

## Workflow Status Values

| Status | Description | Action |
|--------|-------------|--------|
| `init` | Workflow is initializing | Wait |
| `executing` | Workflow is running | Wait |
| `finish` | Workflow completed successfully | Get results |
| `failed` | Workflow encountered an error | Check error details |

---

## Error Handling

### Check CLI Response
```bash
RESULT=$(refly skill run --id <installationId> --input '<json>')
if [ "$(echo "$RESULT" | jq -r '.ok')" != "true" ]; then
  echo "Error: $(echo "$RESULT" | jq -r '.error.message')"
  echo "Hint: $(echo "$RESULT" | jq -r '.hint // empty')"
fi
```

### Check Workflow Failed
```bash
DETAIL=$(refly workflow detail "$RUN_ID")
STATUS=$(echo "$DETAIL" | jq -r '.payload.status')
if [ "$STATUS" = "failed" ]; then
  echo "Workflow failed. Details:"
  echo "$DETAIL" | jq '.payload.nodes[] | select(.status == "failed")'
fi
```

### No Files or Content Returned
```bash
# Get verbose output to debug
refly workflow toolcalls "$RUN_ID" --raw
```

---

## Troubleshooting

### Get Full Workflow Details
```bash
refly workflow detail "$RUN_ID"
```

### Get All Toolcalls (Verbose)
```bash
refly workflow toolcalls "$RUN_ID" --raw
```

### Filter Toolcalls by Status
```bash
refly workflow toolcalls "$RUN_ID" --status completed
refly workflow toolcalls "$RUN_ID" --status failed
```

### Check Authentication
```bash
refly status
```

### List Installed Skills
```bash
refly skill installations
```

---

## Required Behavior

1. **CLI only** - Use `refly <command>`, never call API directly
2. **Trust JSON** - Only trust CLI JSON (`ok`, `payload`, `error`, `hint`)
3. **No fabricated IDs** - Never invent workflow/run/node IDs
4. **Stop on error** - If `ok=false`, stop and show `hint`
5. **Use correct IDs** - `skpi-xxx` for run, `we-xxx` for workflow commands

```

### references/file.md

```markdown
# File Reference

## File Commands

```bash
# List files
refly file list [options]
  --page <n>           # Page number (default: 1)
  --page-size <n>      # Files per page (default: 20)
  --canvas-id <id>     # Filter by canvas ID
  --result-id <id>     # Filter by action result ID
  --include-content    # Include file content in response

# Get file details
refly file get <fileId> [options]
  --no-content         # Exclude file content

# Download file
refly file download <fileId> [options]
  -o, --output <path>  # Output path (defaults to original filename)

# Upload file(s)
refly file upload <path> [options]
  --canvas-id <id>     # Canvas ID (required)
  --filter <ext>       # Filter by extensions (e.g., pdf,docx,png)
```

## Interaction

- File IDs typically come from action results (`node.md`) or workflow outputs (`workflow.md`).
- Use file commands to retrieve content produced by workflow runs.
- Use `--result-id` or `--canvas-id` to narrow file listings to a specific run context.

```

### references/node.md

```markdown
# Node Reference

## Node Types

Examples below use two common node types:
- `start` - Workflow entry point that captures user input
- `skillResponse` - AI-powered response node that can use tools

## Node Execution Commands

Node execution commands are now under `refly workflow run`:

```bash
# Run From Here (from this node + downstream nodes)
refly workflow run node-start [options]
  --from <nodeId>            # Node to run from (includes downstream)
  --run-id <runId>           # Existing run context
  --workflow-id <id>         # Start new run from workflow

# Abort running node
refly workflow run node-abort <resultId> [options]
  --version <number>         # Specific version to abort

# Get node execution result
refly workflow run node-result <resultId> [options]
  --include-steps            # Include step details
  --include-messages         # Include chat messages
  --include-tool-calls       # Include tool call details

# Get node detail within a workflow run
refly workflow run node-detail <runId> <nodeId> [options]
  --include-messages         # Include AI messages
  --raw                      # Disable output sanitization

# List tool calls from node execution
refly workflow run node-toolcalls <resultId> [options]
  --status <status>          # Filter: executing, completed, failed
  --tool-name <name>         # Filter by tool name
  --toolset-id <id>          # Filter by toolset ID

# Single tool call detail
refly workflow run node-toolcall <callId> [options]
  --raw                      # Full output without sanitization
```

Note: Use `--run-id` when you already have a specific run context; use `--workflow-id` to start a new run from a node.

## List Nodes in Workflow

```bash
refly workflow node list <workflowId> [options]
  --include-edges            # Include edge/connection info
  --include-position         # Include node coordinates
  --include-metadata         # Include full node metadata
```

## Get Single Node Information

```bash
refly workflow node get <id> <nodeId> [options]
  --include-connections      # Include incoming/outgoing connections
```

Note: `<id>` can be workflow ID (`c-xxx`) or run ID (`we-xxx`).

## Interaction

- `workflow run node-detail <runId> <nodeId>` yields `resultId` used by node/tool commands.
- Use `workflow run node-result` to fetch node output and optional file IDs.
- Use `workflow run node-toolcalls` to inspect tool execution details.
- File IDs from node results should be handled via `file.md`.

## Migration Note

The following commands have been migrated:

| Old Command | New Command |
|-------------|-------------|
| `refly node run --type <t>` | **REMOVED** - Use `refly workflow run node-start --type <t>` |
| `refly node result <id>` | `refly workflow run node-result <id>` |
| `refly node abort <id>` | `refly workflow run node-abort <resultId>` |
| `refly workflow run node <runId> <nodeId>` | `refly workflow run node-detail <runId> <nodeId>` |

**Breaking Change:** The standalone `refly node` command group has been removed.
Node execution is now under `refly workflow run node-*`. For single-node debugging, use:
1. `refly workflow run node-start --type <t>`
2. Use `node-start --from <nodeId> --run-id <runId>` to run from node + downstream

```

### references/skill.md

```markdown
# Skill Reference

## CLI Commands

### Discovery

```bash
# List skill packages
refly skill list [options]
  --status <status>     # Filter: draft, published, deprecated
  --mine                # Show only my packages
  --tags <tags>         # Filter by tags (comma-separated)
  --page <number>       # Page number (default: 1)
  --page-size <number>  # Page size (default: 20)

# Search public packages
refly skill search <query> [options]
  --tags <tags>         # Filter by tags (comma-separated)
  --page <number>       # Page number (default: 1)
  --page-size <number>  # Page size (default: 20)

# Get skill details
refly skill get <skillId> [options]
  --include-workflows   # Include workflow details
  --share-id <shareId>  # Share ID for private skills
```

### Lifecycle

```bash
# Create skill package (see "Skill Creation Modes" below)
refly skill create [options]
  --name <name>                 # Skill name (required)
  --version <version>           # Semantic version (default: 1.0.0)
  --description <desc>          # Skill description
  --triggers <triggers>         # Trigger phrases (comma-separated)
  --tags <tags>                 # Category tags (comma-separated)
  --workflow <workflowId>       # Bind single workflow
  --workflow-ids <ids>          # Bind multiple workflows (comma-separated)
  --workflow-spec <json>        # Workflow spec JSON
  --workflow-query <query>      # Natural language description
  --verbose                     # Include workflow details in output

# Publishing
refly skill publish <skillId>   # Make public
refly skill unpublish <skillId> # Make private
refly skill delete <skillId> [options]
  --force                       # Skip confirmation

# Local management
refly skill sync [options]      # Sync registry with filesystem
  --dry-run                     # Preview changes only
  --prune                       # Remove orphan entries

refly skill validate [path] [options]
  --fix                         # Attempt to fix issues
```

### Installation

```bash
# Install skill
refly skill install <skillId> [options]
  --version <version>   # Specific version
  --share-id <shareId>  # Share ID for private skills
  --config <json>       # Installation config JSON

# List installations
refly skill installations [options]
  --status <status>     # Filter: downloading, initializing, ready, error, disabled
  --page <number>       # Page number (default: 1)
  --page-size <number>  # Page size (default: 20)

# Uninstall
refly skill uninstall <installationId> [options]
  --force               # Skip confirmation
```

### Execution

```bash
# Run installed skill
refly skill run <installationId> [options]
  --input <json>                # Input JSON for the skill
  --workflow <skillWorkflowId>  # Run specific workflow only
  --async                       # Run asynchronously
```

---

## Skill Creation Modes

### Mode 1: Generate Workflow from Query

```bash
refly skill create --name <name> --workflow-query "<query>"
```

Behavior:
1. Calls backend AI to generate workflow
2. Creates skill and binds workflow
3. Returns skillId + workflowId

Optional metadata (does not generate workflow by itself):
- `--description`, `--triggers`, `--tags`

Example:
```bash
refly skill create \
  --name comfyui-refly-skill \
  --workflow-query "ComfyUI image generation workflow collection" \
  --description "ComfyUI image workflow collection" \
  --triggers "comfyui,text to image,image generation,image to image" \
  --tags "image,comfyui"
```

### Mode 2: Bind Existing Workflow(s)

```bash
refly skill create --name <name> --workflow <workflowId>
```

Bind multiple workflows:
```bash
refly skill create --name <name> --workflow-ids "<workflowId1,workflowId2>"
```

Example:
```bash
refly skill create \
  --name my-skill \
  --description "My custom skill" \
  --workflow c-zybbx65ydi5npo7xevjx1wlr \
  --triggers "custom,workflow" \
  --tags "internal"
```

### Mode 3b: Bind Multiple Workflows (Explicit)

```bash
refly skill create --name <name> --workflow-ids "<workflowId1,workflowId2>"
```

Example:
```bash
refly skill create \
  --name multi-workflow-skill \
  --description "Multiple workflow entry points" \
  --workflow-ids "c-aaa111,c-bbb222" \
  --triggers "multi,entry" \
  --tags "batch,workflow"
```

### Mode 3: Use Workflow Spec (Structured)

```bash
refly skill create --name <name> --workflow-spec '<json>'
```

Example:
```bash
refly skill create \
  --name pdf-processor \
  --workflow-spec '{
    "nodes": [
      {"id": "n1", "type": "start", "data": {"title": "Start"}},
      {"id": "n2", "type": "skillResponse", "data": {"title": "Process PDF", "metadata": {"query": "Extract and summarize PDF content"}}}
    ],
    "edges": [
      {"id": "e1", "source": "n1", "target": "n2"}
    ]
  }'
```

> **Note**: Examples use `start` and `skillResponse`. Additional node types may be supported by backend.

### Mode 4: Local Skill Only (No Cloud Package)

Use when you only want a local skill directory and registry entry.

```bash
# Create local skill files manually, then sync
refly skill sync
```

You can later create a cloud skill package with:
```bash
refly skill create --name <name> --workflow <workflowId>
```

---

## Workflow Generation Logic

When no `--workflow`, `--workflow-ids`, `--workflow-spec`, or `--workflow-query` is specified,
CLI will return `skill.create.needs_workflow` with suggested options and examples.

---

## Directory Structure

```
~/.refly/skills/
├── base/                       # Base skill files (symlink target for 'refly')
│   ├── SKILL.md
│   └── rules/
│       ├── workflow.md
│       ├── node.md
│       ├── file.md
│       └── skill.md
└── <skill-name>/               # Domain skill directories
    └── SKILL.md

~/.claude/skills/
├── refly → ~/.refly/skills/base/           # Base skill symlink
└── <skill-name> → ~/.refly/skills/<name>/  # Domain skill symlinks
```

### How Symlinks Work

- **Base skill**: `~/.claude/skills/refly` → `~/.refly/skills/base/`
- **Domain skills**: `~/.claude/skills/<name>` → `~/.refly/skills/<name>/`

Claude Code discovers skills via symlinks in `~/.claude/skills/`. Each skill is a symlink pointing to the actual skill directory in `~/.refly/skills/`.

---

## Domain Skill Template

Location: `~/.refly/skills/<skill-name>/SKILL.md` (accessed via `~/.claude/skills/<skill-name>/SKILL.md`)

````markdown
---
name: <skill-name>
description: <one-line summary, under 100 chars>
workflowId: <workflow-id>
triggers:
  - <phrase-1>
  - <phrase-2>
tags:
  - <tag-1>
author: <author>
version: 1.0.0
---

# <Skill Name>

## Quick Start

<Minimal code example>

## Run

```bash
refly skill run <installationId> --input '<json>'
```

## Advanced

**Feature A**: See [FEATURE_A.md](FEATURE_A.md)
**API Reference**: See [REFERENCE.md](REFERENCE.md)
````

---

## Best Practices

**Naming**: lowercase, hyphens, max 64 chars (`pdf-processing`, `doc-translator`)

**Description**: verb + what + when, third person, under 100 chars
- Good: "Extracts text from PDF files. Use when processing PDF documents."
- Bad: "I can help you with PDFs"

**Triggers**: 3-6 high-signal phrases, mix EN/ZH if needed

**Structure**: Each skill is a directory with `skill.md` as entry; push details to sibling files

**Workflow Creation**:
1. Be specific in workflow query - helps AI generate accurate workflow
2. Include diverse triggers - cover EN/ZH variations
3. Test before publish - install then run (`refly skill install` -> `refly skill run`)
4. Use `--workflow-spec` for complex scenarios requiring precise control

---

## Local Skills vs Cloud Skills

| Type | Location | Management | Use Case |
|------|----------|------------|----------|
| Local | `~/.refly/skills/<name>/` | Symlinks | Fast iteration |
| Cloud | Backend `SkillPackage` | API | Distribution & versioning |

Integration flow:
1. Create cloud skill -> `refly skill create` (generates workflow + local symlink)
2. Publish skill -> `refly skill publish` -> makes skill discoverable
3. Install to run -> `refly skill install` -> creates local SKILL.md + symlink
4. Run skill -> `refly skill run <installationId>`

---

## Output Examples

### List Output

```json
{
  "ok": true,
  "type": "skill.list",
  "version": "1.0",
  "payload": {
    "skills": [
      {
        "skillId": "skp-xxx",
        "name": "my-skill",
        "version": "1.0.0",
        "description": "Skill description",
        "status": "published",
        "isPublic": true,
        "downloadCount": 10,
        "createdAt": "2026-01-19T00:00:00Z"
      }
    ],
    "total": 10,
    "page": 1,
    "pageSize": 20,
    "hasMore": false
  }
}
```

### Installations Output

```json
{
  "ok": true,
  "type": "skill.installations",
  "version": "1.0",
  "payload": {
    "installations": [
      {
        "installationId": "skpi-xxx",
        "skillId": "skp-xxx",
        "skillName": "my-skill",
        "skillVersion": "1.0.0",
        "status": "ready",
        "installedAt": "2026-01-19T00:00:00Z"
      }
    ],
    "total": 3,
    "page": 1,
    "pageSize": 20,
    "hasMore": false
  }
}
```

### Execution Output

```json
{
  "ok": true,
  "type": "skill.run",
  "version": "1.0",
  "payload": {
    "executionId": "skpe-xxx",
    "installationId": "skpi-xxx",
    "status": "completed",
    "workflowExecutions": [
      {
        "skillWorkflowId": "skw-xxx",
        "workflowId": "c-xxx",
        "status": "completed"
      }
    ],
    "result": {},
    "error": null
  }
}
```

---

## Skill Sync Details

`refly skill sync` will:
- Validate existing symlinks in `~/.claude/skills/`
- Check for broken symlinks (pointing to non-existent directories)
- Check for orphan directories (directories without symlinks)
- With `--fix`: recreate broken symlinks
- With `--prune`: remove broken symlinks

---

## Skill Validate Details

`refly skill validate [path]` will:
- Validate frontmatter schema and required fields
- Return per-file errors and warnings
- Provide a summary of valid/invalid files

Example output:
```json
{
  "ok": true,
  "type": "skill.validate",
  "version": "1.0",
  "payload": {
    "path": "/path/to/skills",
    "summary": {
      "total": 3,
      "valid": 2,
      "invalid": 1,
      "warnings": 1
    }
  }
}
```

---

## Error Handling

| Error Code | Cause | Solution |
|------------|-------|----------|
| `VALIDATION_ERROR` | Missing required params or invalid format | Check `--name` and other required params |
| `ACCESS_DENIED` | No permission for resource | Verify login and resource ownership |
| `INTERNAL_ERROR` | Server error | Retry later or contact support |

> **Note**: Invalid JSON in `--workflow-spec` will fail the command; ensure it is valid JSON.

```

### references/workflow.md

```markdown
# Workflow Reference

## Workflow Commands

### Management

```bash
# Generate workflow from natural language
refly workflow generate [options]
  --query <query>            # Natural language description
  --canvas-id <id>           # Update existing workflow
  --model-id <id>            # Model for generation
  --locale <locale>          # Output language (en, zh)
  --timeout <ms>             # Timeout (default: 300000)
  --variables <json>         # Predefined variables
  --skip-default-nodes       # Skip default start+skillResponse
  --no-cleanup               # Disable orphan cleanup on failure

# Edit workflow
refly workflow edit <workflowId> [options]
  --name <name>              # New name
  --ops <json>               # Node/edge operations
  --variables <json>         # Variables array
  --toolsets <keys>          # Toolset keys (comma-separated)
  --auto-layout              # Auto-layout nodes

# Other management
refly workflow get <workflowId>
refly workflow delete <workflowId>
refly workflow list [--limit <n>] [--offset <n>]
refly workflow layout <workflowId> [--direction LR|TB]
refly workflow toolset-keys [--type <type>]
```

### Execution

```bash
# Start workflow run
refly workflow run start <workflowId> [options]
  --input <json>             # Input variables
  --from-node <nodeId>       # Run From Here

# Query run status
refly workflow run get <runId>
refly workflow run detail <runId> [--no-tool-calls] [--preview-length <n>]
refly workflow runs <workflowId> [--limit <n>] [--offset <n>] [--status <s>]
refly workflow status <id> [--watch] [--interval <ms>] [--full]
refly workflow detail <id> [--no-tool-calls] [--preview-length <n>]
refly workflow abort <workflowId>
```

### Node Operations

```bash
# List/get nodes
refly workflow node list <workflowId> [--include-edges] [--include-position] [--include-metadata]
refly workflow node get <id> <nodeId> [--include-connections]
refly workflow node output <id> <nodeId> [--include-tool-calls] [--raw]

# Run from node
refly workflow run node-start [options]
  --from <nodeId>            # Node to run from
  --run-id <runId>           # Existing run context
  --workflow-id <id>         # Start new run

# Node results
refly workflow run node-detail <runId> <nodeId> [--include-messages] [--raw]
refly workflow run node-result <resultId> [--include-steps] [--include-messages] [--include-tool-calls]
refly workflow run node-abort <resultId> [--version <n>]
```

### Tool Calls

```bash
# Workflow-level tool calls (full options)
refly workflow toolcalls <id> [options]
refly workflow run toolcalls <runId> [options]
  --node-id <nodeId>         # Filter by node
  --toolset-id <id>          # Filter by toolset
  --tool-name <name>         # Filter by tool name
  --status <status>          # Filter: executing, completed, failed
  --limit <n>                # Max results (default: 100)
  --offset <n>               # Pagination offset
  --raw                      # Full output without sanitization

# Node-level tool calls (limited options)
refly workflow run node-toolcalls <resultId> [options]
  --status <status>          # Filter: executing, completed, failed
  --tool-name <name>         # Filter by tool name
  --toolset-id <id>          # Filter by toolset

# Single tool call
refly workflow run node-toolcall <callId> [--raw]
```

## Interaction

- `workflow run start` returns `runId` used by `workflow run get` and `workflow run node-detail`.
- `workflow run node-detail` returns `resultId` for action/tool lookups (see `node.md`).
- `workflow node output` retrieves the actual execution output content of a node.
- Action results may include file IDs; use `file.md` to fetch/download.

## Node Output Command

Get the execution output content of a specific node:

```bash
# Using workflowId (gets output from latest run)
refly workflow node output c-xxx <nodeId>

# Using runId (gets output from specific run)
refly workflow node output we-xxx <nodeId>

# Include tool call details
refly workflow node output <id> <nodeId> --include-tool-calls

# Get full content without truncation (default: 10KB limit)
refly workflow node output <id> <nodeId> --raw
```

**ID Type Detection:**
- `c-xxx` prefix: Treated as workflowId, uses latest/active run
- `we-xxx` prefix: Treated as runId, uses specific run

**Security:** Node output access requires ownership verification at both workflow execution level and action result level (defense-in-depth).

## Workflow Generate Examples

```bash
refly workflow generate --query "Parse PDF, summarize content, translate to Chinese"
```

```bash
refly workflow generate \
  --query "Process documents from input folder" \
  --variables '[{"variableId":"v1","name":"inputFolder","variableType":"string"}]'
```

```

refly | SkillHub