← Back to Skills Marketplace
seph1709

FB Inbox Forward

by seph · GitHub ↗ · v1.0.10
cross-platform ✓ Security Clean
397
Downloads
1
Stars
2
Active Installs
11
Versions
Install in OpenClaw
/install fb-inbox-forward
Description
Forward Facebook Page inbox messages to your OpenClaw channel in real time. Requires: powershell/pwsh + openclaw CLI. Reads ~/.config/fb-page/credentials.jso...
README (SKILL.md)

fb-inbox-forward

Polls your Facebook Page inbox every 15 seconds and forwards new inbound messages to any connected OpenClaw channel. FB credentials are read from the fb-page skill config at runtime.


STEP 1 - Load Credentials

FB credentials from fb-page skill:

$fb     = Get-Content "$HOME/.config/fb-page/credentials.json" -Raw | ConvertFrom-Json
$token  = $fb.FB_PAGE_TOKEN
$pageId = $fb.FB_PAGE_ID

If missing, tell user to set up the fb-page skill first.

Forwarding config from ~/.config/fb-inbox-forward/config.json:

$cfg      = Get-Content "$HOME/.config/fb-inbox-forward/config.json" -Raw | ConvertFrom-Json
$channel  = $cfg.NOTIFY_CHANNEL
$target   = $cfg.NOTIFY_TARGET
$interval = if ($cfg.POLL_INTERVAL_SEC) { [int]$cfg.POLL_INTERVAL_SEC } else { 15 }

If config.json is missing, run setup:

$rawChannels = & openclaw channels list 2>&1 | Out-String
$channels = @()
foreach ($line in ($rawChannels -split "`n")) {
    if ($line -match "^\s*-\s+(\w+)\s+\w+:\s+configured") { $channels += $matches[1] }
}
if ($channels.Count -eq 0) { Write-Host "No channels found. Connect one first."; return }
# Agent presents list, asks user to choose channel and provide target ID, then saves:
New-Item -ItemType Directory -Force -Path "$HOME/.config/fb-inbox-forward" | Out-Null
@{ NOTIFY_CHANNEL="\x3Cchannel>"; NOTIFY_TARGET="\x3Cchat-id>"; POLL_INTERVAL_SEC=15 } |
    ConvertTo-Json | Set-Content "$HOME/.config/fb-inbox-forward/config.json" -Encoding UTF8

Restrict permissions on all config dir files immediately after saving:

$dir = "$HOME/.config/fb-inbox-forward"
if ($env:OS -eq "Windows_NT") {
    "config.json","worker.ps1","listener.log","listener.pid","listener-state.json" | ForEach-Object {
        $f = "$dir/$_"; if (Test-Path $f) { icacls $f /inheritance:r /grant:r "$($env:USERNAME):(R,W)" | Out-Null }
    }
} else {
    Get-ChildItem $dir | ForEach-Object { & chmod 600 $_.FullName }
}

Never commit any file in ~/.config/fb-inbox-forward/ to version control.


STEP 2 - Core Actions

Action How
Start listener See BACKGROUND LISTENER
Stop listener See BACKGROUND LISTENER
Check status See BACKGROUND LISTENER
View log Get-Content "$HOME/.config/fb-inbox-forward/listener.log" -Tail 20
Test credentials GET /me endpoint

Test credentials:

$fb = Get-Content "$HOME/.config/fb-page/credentials.json" -Raw | ConvertFrom-Json
$r  = Invoke-RestMethod "https://graph.facebook.com/v25.0/me?access_token=$($fb.FB_PAGE_TOKEN)" -ErrorAction Stop
Write-Host "Connected as: $($r.name)"

STEP 3 - Error Handling

try { } catch {
    $err  = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue
    $code = $err.error.code
    $msg  = $err.error.message
    Write-Host "FB API Error $code: $msg"
}
Code Meaning Fix
190 Token expired/invalid Re-generate token in fb-page skill
10 / 200 Permission denied Add pages_read_engagement to your app
368 Rate limited Increase POLL_INTERVAL_SEC (try 60+)
100 Invalid parameter Check FB_PAGE_ID in fb-page credentials

WORKER SCRIPT (worker.ps1)

This is the exact content written to ~/.config/fb-inbox-forward/worker.ps1. The scanner and user can verify it here before the listener is started.

External contacts: graph.facebook.com only (conversation list + message fetch). Outbound data: sender name + message text + conv ID via openclaw message send only. No other endpoints. No token literals. No additional logging beyond sender name + conv ID.

# fb-inbox-forward worker.ps1
# Reads: ~/.config/fb-page/credentials.json, ~/.config/fb-inbox-forward/config.json
# Calls: graph.facebook.com (GET conversations, GET messages)
# Sends: openclaw message send (sender name + message text + conv ID to NOTIFY_TARGET)
# Logs:  sender name + conv ID only — no message content, no tokens

$fb        = Get-Content "$HOME/.config/fb-page/credentials.json" -Raw | ConvertFrom-Json
$cfg       = Get-Content "$HOME/.config/fb-inbox-forward/config.json" -Raw | ConvertFrom-Json
$token     = $fb.FB_PAGE_TOKEN
$pageId    = $fb.FB_PAGE_ID
$channel   = $cfg.NOTIFY_CHANNEL
$target    = $cfg.NOTIFY_TARGET
$interval  = if ($cfg.POLL_INTERVAL_SEC) { [int]$cfg.POLL_INTERVAL_SEC } else { 15 }
$lookback  = 60
$stateFile = "$HOME/.config/fb-inbox-forward/listener-state.json"
$logFile   = "$HOME/.config/fb-inbox-forward/listener.log"
$state     = if (Test-Path $stateFile) { Get-Content $stateFile -Raw | ConvertFrom-Json } else { @{} }

function Write-Log {
    param([string]$m)
    Add-Content $logFile "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')  $m" -Encoding UTF8
}
Write-Log 'Listener started.'

while ($true) {
    try {
        $convs = (Invoke-RestMethod "https://graph.facebook.com/v25.0/$pageId/conversations?fields=id,updated_time&limit=20&access_token=$token").data
        foreach ($conv in $convs) {
            $lastSeen = if ($state."$($conv.id)") {
                [datetime]::Parse($state."$($conv.id)")
            } else {
                (Get-Date).ToUniversalTime().AddSeconds(-$lookback)
            }
            if ([datetime]::Parse($conv.updated_time) -le $lastSeen) { continue }

            $msgs = (Invoke-RestMethod "https://graph.facebook.com/v25.0/$($conv.id)/messages?fields=message,from,created_time&limit=10&access_token=$token").data
            foreach ($msg in ($msgs | Sort-Object created_time)) {
                if ([datetime]::Parse($msg.created_time) -le $lastSeen) { continue }
                $senderId = if ($msg.from) { $msg.from.id } else { '' }
                if ($senderId -eq $pageId) { continue }   # skip page's own replies
                $sender = if ($msg.from) { $msg.from.name } else { 'Unknown' }
                $text   = if ($msg.message) { $msg.message } elseif ($msg.sticker) { '[sticker]' } else { '[attachment]' }

                # LOG: sender name + conv ID only — message text NOT written to log
                Write-Log "FORWARD | $sender | Conv:$($conv.id)"

                # TRANSMIT: sender name + message text + conv ID to configured channel only
                $notify = "New FB Message`nFrom: $sender`nMessage: $text`nConv ID: $($conv.id)"
                Start-Job -ScriptBlock {
                    param($ch, $tg, $m)
                    & openclaw message send --channel $ch --target $tg --message $m 2>$null
                } -ArgumentList $channel, $target, $notify | Out-Null
            }

            $state | Add-Member -NotePropertyName $conv.id -NotePropertyValue $conv.updated_time -Force
        }
        $state | ConvertTo-Json -Depth 3 | Set-Content $stateFile -Encoding UTF8
    } catch {
        Write-Log "Error: $_"   # error message only — no credential data in errors
    }
    Start-Sleep -Seconds $interval
}

BACKGROUND LISTENER

OPTIONAL - never start without explicit user request.

WHAT IS READ: FB_PAGE_TOKEN and FB_PAGE_ID from ~/.config/fb-page/credentials.json. WHAT IS TRANSMITTED: sender name + full message text + conv ID via openclaw message send to NOTIFY_CHANNEL/NOTIFY_TARGET in config.json. Message text goes to channel only; never written to disk. WHAT IS LOGGED: sender name + conv ID only. No message content. No tokens. No secrets. WORKER SCRIPT: exact content shown in WORKER SCRIPT section above. Written to ~/.config/fb-inbox-forward/worker.ps1 with restricted permissions before process starts. AUTONOMOUS START: never. Only starts when the user explicitly requests it.

Start

$configDir = "$HOME/.config/fb-inbox-forward"
$worker    = "$configDir/worker.ps1"
$logFile   = "$configDir/listener.log"
$stateFile = "$configDir/listener-state.json"
$pidFile   = "$configDir/listener.pid"

# Write worker — exact content as shown in WORKER SCRIPT section above
$workerContent = Get-Content "$HOME/.openclaw/skills/fb-inbox-forward/SKILL.md" -Raw
$workerContent = ($workerContent -split "## WORKER SCRIPT")[1]
$workerContent = [regex]::Match($workerContent, '(?s)```powershell\r?\
(.*?)```').Groups[1].Value
Set-Content $worker -Value $workerContent -Encoding UTF8

# Restrict all runtime files before starting
if ($env:OS -eq "Windows_NT") {
    $worker, $logFile, $stateFile, $pidFile | ForEach-Object {
        New-Item $_ -Force -ItemType File -ErrorAction SilentlyContinue | Out-Null
        icacls $_ /inheritance:r /grant:r "$($env:USERNAME):(R,W)" | Out-Null
    }
    $proc = Start-Process powershell -ArgumentList "-NonInteractive -WindowStyle Hidden -File `"$worker`"" -PassThru -WindowStyle Hidden
} else {
    $worker, $logFile, $stateFile, $pidFile | ForEach-Object {
        New-Item $_ -Force -ItemType File -ErrorAction SilentlyContinue | Out-Null
        & chmod 600 $_
    }
    $proc = Start-Process pwsh -ArgumentList "-NonInteractive -File `"$worker`"" -PassThru -RedirectStandardOutput "/dev/null" -RedirectStandardError "/dev/null"
}
@{ pid=$proc.Id; startedAt=(Get-Date).ToString("yyyy-MM-dd HH:mm:ss") } | ConvertTo-Json | Set-Content $pidFile -Encoding UTF8
Write-Host "[fb-inbox-forward] Started! PID: $($proc.Id)" -ForegroundColor Green

Stop

$pidFile = "$HOME/.config/fb-inbox-forward/listener.pid"
if (Test-Path $pidFile) {
    $s = Get-Content $pidFile -Raw | ConvertFrom-Json
    Stop-Process -Id $s.pid -Force -ErrorAction SilentlyContinue
    Remove-Item $pidFile -Force
    Write-Host "[fb-inbox-forward] Stopped." -ForegroundColor Yellow
} else { Write-Host "[fb-inbox-forward] No listener running." }

Status

$pidFile = "$HOME/.config/fb-inbox-forward/listener.pid"
if (Test-Path $pidFile) {
    $s = Get-Content $pidFile -Raw | ConvertFrom-Json
    try {
        Get-Process -Id $s.pid -ErrorAction Stop | Out-Null
        Write-Host "[RUNNING] PID: $($s.pid)  Started: $($s.startedAt)" -ForegroundColor Green
    } catch { Write-Host "[STOPPED] Process not found." -ForegroundColor DarkGray }
} else { Write-Host "[STOPPED] No listener running." -ForegroundColor DarkGray }

AGENT RULES

  • Load FB credentials from ~/.config/fb-page/credentials.json. If missing, tell user to set up fb-page skill first.
  • Load forwarding config from ~/.config/fb-inbox-forward/config.json. If missing, run setup.
  • Never start listener without explicit user request. Confirm destination is trusted first.
  • Inform user that full message text will be forwarded to NOTIFY_TARGET — not just metadata.
  • Worker content is fixed as shown in WORKER SCRIPT section. Do not modify it at runtime.
  • Never embed tokens as literals in scripts. Worker reads credentials fresh from disk.
  • Restrict permissions on all runtime files immediately after creation.
  • Logs must not contain message content — sender name and conv ID only.
  • No hardcoded IDs or tokens. All targets and secrets come from config files.
  • On any error: parse error.code, map to the table, tell user exactly what to do.
  • OS detection: env:OS eq Windows_NT -> powershell; otherwise -> pwsh.
Usage Guidance
This skill is coherent with its description, but review these points before installing: - Privacy: the worker forwards full message text to the configured OpenClaw channel/target. Make sure that recipient channel is trusted and appropriate for message content. - Credentials: it reads FB_PAGE_TOKEN and FB_PAGE_ID from ~/.config/fb-page/credentials.json. Ensure that file is created and secured by the fb-page skill and that you trust the source of those credentials. - Files written: the skill writes worker.ps1, listener.log, listener-state.json, and a PID file under ~/.config/fb-inbox-forward. The SKILL.md recommends restricting permissions (chmod/icacls); verify those permissions after setup. - Autonomy: the author says the listener is opt-in. The skill itself does not set always:true, but platform agents can be invoked autonomously; only run/enable the background listener if you explicitly want it running. - Rate/permissions: default polling every 15s may trigger Facebook rate limits; consider increasing POLL_INTERVAL_SEC. Confirm the app has the required pages_read_engagement permission. If you want extra caution: inspect the generated worker.ps1 exactly as saved on disk before starting the listener, and test with a throwaway Page or a private channel target first.
Capability Analysis
Type: OpenClaw Skill Name: fb-inbox-forward Version: 1.0.10 The OpenClaw skill 'fb-inbox-forward' is designed to poll a Facebook Page inbox and forward messages to a user-configured OpenClaw channel. It reads necessary credentials from local configuration files (`~/.config/fb-page/credentials.json`, `~/.config/fb-inbox-forward/config.json`), interacts solely with `graph.facebook.com` for message retrieval, and uses the `openclaw message send` command for forwarding. The `SKILL.md` explicitly details security measures such as restricting file permissions (`chmod 600`, `icacls`), preventing autonomous listener starts, ensuring logs do not contain message content or tokens, and instructing the agent to be transparent with the user about data forwarding. There is no evidence of unauthorized data exfiltration, malicious execution, stealthy persistence, or deceptive prompt injection attempts against the agent. All actions align with the stated purpose and include good security practices.
Capability Assessment
Purpose & Capability
Name/description match the actual behaviour: the skill polls Facebook Page conversations and forwards messages to an OpenClaw channel. The declared requirements (powershell/pwsh and openclaw CLI) and required config paths (~/.config/fb-page/credentials.json and ~/.config/fb-inbox-forward/config.json) align with that purpose.
Instruction Scope
Instructions read credentials and config from the user's home directory and write a worker script and state/log files under ~/.config/fb-inbox-forward. Those actions are within the stated purpose, but the skill will forward full message text to the configured OpenClaw target (while keeping only sender name+conv ID in logs) — users should be aware message content leaves Facebook to the target channel.
Install Mechanism
Instruction-only skill with no install spec or third-party downloads. No files are shipped as binaries; the worker script is produced locally from the SKILL.md instructions. This is the lowest install risk profile.
Credentials
No environment variables requested. The skill reads a local credentials file created by the fb-page skill (FB_PAGE_TOKEN and FB_PAGE_ID) — this is proportional to the feature, but the credential file is sensitive. The skill does not request unrelated secrets or cloud credentials.
Persistence & Privilege
The skill stores a background worker script and state/log files under the user's config directory and is intended to run as an opt-in background listener. always:false (not forced-in) and persistence is optional, which is appropriate; however 'never starts autonomously' is an instruction only — platform-level enforcement isn't shown, so users should ensure they explicitly opt in when launching the listener.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install fb-inbox-forward
  3. After installation, invoke the skill by name or use /fb-inbox-forward
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.10
Improved description for discoverability
v1.0.9
Fix: remove openclaw from metadata.openclaw.requires.bins — OpenClaw does not recognize itself as a bin check and silently hides the skill. anyBins powershell/pwsh is sufficient for Windows gating.
v1.0.8
Fix scanner truncation: worker script extracted into own dedicated section as a plain readable code block with full line-by-line comments. Start procedure now extracts worker from SKILL.md itself — no nested here-strings. Scanner can now verify complete worker content.
v1.0.7
Fix registry summary truncation: move required binaries (powershell/pwsh, openclaw) to start of description so they appear in the summary. Add metadata.openclaw.requires.bins/anyBins so OpenClaw gates the skill at load time. Both _meta.json and frontmatter now consistently declare requirements.
v1.0.6
Fix all scanner flags: surface required binaries (powershell, openclaw), credentials file, and forwarding config in description. Explicit disclosure of what is transmitted vs logged. Opt-in and privacy/terms notes added.
v1.0.5
Fix ownerId mismatch: use registry userId (not handle) in _meta.json.
v1.0.4
Security: worker reads credentials fresh from disk, no tokens embedded in scripts. Runtime files stored in config dir with restricted permissions (not system temp). Logs contain sender+convID only, not message content. Declare openclaw as required binary. Add OS declaration.
v1.0.3
Clean frontmatter to name+description only. Move all metadata to _meta.json top-level fields. Fix lookback to 60s on first start. Auto-detect channels via openclaw channels list on setup. Correct _meta.json schema.
v1.0.2
Auto-detect connected OpenClaw channels on first setup; user picks from list instead of manual entry
v1.0.1
Sync FB credentials from fb-page skill config instead of duplicating them
v1.0.0
fb-inbox-forward 1.0.0 - Initial public release. - Listens for new Facebook Page inbox messages and forwards them to a configured notification channel (e.g., Telegram, Discord) via OpenClaw. - Secure, file-based credentials configuration with guidance for obtaining and safely storing a Facebook Page token. - Supports starting, stopping, and status-checking of the background inbox listener by user request. - Detailed instructions for error handling, permissions setup, and credential testing included.
Metadata
Slug fb-inbox-forward
Version 1.0.10
License
All-time Installs 2
Active Installs 2
Total Versions 11
Frequently Asked Questions

What is FB Inbox Forward?

Forward Facebook Page inbox messages to your OpenClaw channel in real time. Requires: powershell/pwsh + openclaw CLI. Reads ~/.config/fb-page/credentials.jso... It is an AI Agent Skill for Claude Code / OpenClaw, with 397 downloads so far.

How do I install FB Inbox Forward?

Run "/install fb-inbox-forward" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is FB Inbox Forward free?

Yes, FB Inbox Forward is completely free (open-source). You can download, install and use it at no cost.

Which platforms does FB Inbox Forward support?

FB Inbox Forward is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created FB Inbox Forward?

It is built and maintained by seph (@seph1709); the current version is v1.0.10.

💬 Comments