{
  "slug": "io-github-danilokhury-synabun",
  "name": "SynaBun",
  "auditedAt": "2026-11-02T12:22:45Z",
  "version": "2.1.0",
  "ecosystem": "npm",
  "package": "synabun",
  "disclaimer": "Automated smoke test, not a security guarantee.",
  "complete": true,
  "checks": {
    "versionPin": {
      "status": "pass",
      "detail": "Pinned npm synabun@2.1.0",
      "version": "2.1.0"
    },
    "vulnerabilities": {
      "status": "fail",
      "detail": "Critical or high advisories were returned.",
      "critical": 1,
      "high": 13,
      "medium": 13,
      "low": 2,
      "packagesScanned": 350
    },
    "license": {
      "status": "pass",
      "detail": "Apache-2.0",
      "spdx": "Apache-2.0"
    },
    "installScripts": {
      "status": "warn",
      "detail": "Install-time scripts: postinstall",
      "scripts": [
        "postinstall"
      ]
    },
    "secrets": {
      "status": "pass",
      "detail": "No credential patterns in the published artifact.",
      "findings": []
    },
    "packageSize": {
      "status": "pass",
      "detail": "37201775 bytes",
      "bytes": 37201775
    },
    "activity": {
      "status": "pass",
      "detail": "Active 4 days ago.",
      "ageDays": 4
    },
    "sandbox": {
      "status": "pass",
      "detail": "MCP handshake completed. 80 tools listed.",
      "starts": true,
      "handshake": true,
      "timeToReadyMs": 338,
      "tools": [
        {
          "name": "remember",
          "description": "Store a piece of information in persistent memory. Use this when you learn something important, make a decision, discover a pattern, fix a hard bug, or want to preserve context for future sessions."
        },
        {
          "name": "recall",
          "description": "Search your persistent memory for relevant information. Use this at the start of any task to check what you already know, or when you need context about past decisions, known issues, or architectural patterns. Prefer format=\"compact\" for di"
        },
        {
          "name": "forget",
          "description": "Move a specific memory to trash by ID. The memory can be restored from the Neural Interface trash panel or via the restore tool. Use this to clean up outdated, incorrect, or superseded information."
        },
        {
          "name": "restore",
          "description": "Restore a trashed memory by ID. Use this to undo a forget operation."
        },
        {
          "name": "reflect",
          "description": "Update or annotate an existing memory. Use this when you discover additional context, when a decision changes, or when you want to adjust importance based on new information."
        },
        {
          "name": "memories",
          "description": "Browse recent memories, get statistics, or fetch one memory in FULL by id. Use action \"get\" with an id to pull a large/consolidated memory untruncated (list actions truncate content to 150 chars). Use to see what you remember about a projec"
        },
        {
          "name": "category",
          "description": "Manage memory categories. Actions: create, update, delete, list. Categories persist across sessions."
        },
        {
          "name": "sync",
          "description": "Check for stale memories whose related files have changed. Compares stored file checksums against current hashes. Returns compact output (ID + changed files only, no content). IMPORTANT: Always pass \"categories\" to scope the scan \u2014 calling "
        },
        {
          "name": "loop",
          "description": "Autonomous loop control. Start a repeating task loop, check status, update progress journal, or stop it. The Stop hook drives iteration. Call \"update\" after each iteration with a brief summary to maintain context across compactions."
        },
        {
          "name": "tool_groups",
          "description": "Always-available router for SynaBun's tool groups. When a task needs a SynaBun tool this runtime does not list, call action=\"get\", then action=\"add\" with the group that has it, and continue once the host refreshes its tools. On Codex and Cl"
        },
        {
          "name": "choice",
          "description": "Ask the user blocking multiple-choice questions through MCP form elicitation. Use this for SynaBun choices in Codex Default mode. If the result reports supported=false, ask the same numbered choices once in plain text and wait; do not call "
        },
        {
          "name": "browser_batch",
          "description": "Run up to 10 known browser steps sequentially on one owned tab. Uses existing guarded tools, stops on the first failure, and returns one final snapshot by default. Never retry the whole batch after a partial failure. Steps run exactly as wr"
        },
        {
          "name": "browser_navigate",
          "description": "Navigate the browser to a URL (auto-creates a session if needed). By default the response includes an AI snapshot of the new page with [ref=eN] element refs \u2014 act on them directly with browser_click/fill/type, no separate snapshot call need"
        },
        {
          "name": "browser_go_back",
          "description": "Go back to the previous page in browser history."
        },
        {
          "name": "browser_go_forward",
          "description": "Go forward to the next page in browser history."
        },
        {
          "name": "browser_reload",
          "description": "Reload the current page. Useful after making changes or when content is stale."
        },
        {
          "name": "browser_click",
          "description": "Click an element. Pass ref (e.g. \"e12\") from browser_snapshot \u2014 exact, no guessing. Selector is the fallback (CSS, text=\"...\", :has-text(...), role=...; never :contains()). By default the response includes an AI snapshot diff of what change"
        },
        {
          "name": "browser_fill",
          "description": "Clear an input/textarea and fill it with new text. Pass ref from browser_snapshot (preferred) or a selector. For contenteditable editors prefer browser_type."
        },
        {
          "name": "browser_type",
          "description": "Type text (simulates keystrokes; appends). Target by ref from browser_snapshot (preferred), selector, or omit both to type into the focused element. Prefer over browser_fill for contenteditable/rich-text editors."
        },
        {
          "name": "browser_hover",
          "description": "Hover over an element (reveals dropdowns, tooltips, hover-triggered content). Pass ref from browser_snapshot (preferred) or a selector."
        },
        {
          "name": "browser_select",
          "description": "Select an option from a <select> dropdown by ref or selector, and option value."
        },
        {
          "name": "browser_press",
          "description": "Press a keyboard key or key combination. Supports modifiers like Control+A, Shift+Enter, etc."
        },
        {
          "name": "browser_scroll",
          "description": "Scroll the page or a scrollable container (by ref or selector). Essential for infinite-scroll feeds \u2014 but for harvesting feed data, prefer the browser_extract_* tools with their scrolls param, which scroll+extract+dedupe in one call."
        },
        {
          "name": "browser_upload",
          "description": "Upload files via a file input element (by ref or selector). For hidden/gated inputs, click the visible upload button first to reveal the input. See browser_cheatsheet for per-platform upload flows."
        },
        {
          "name": "browser_snapshot",
          "description": "Observe page structure and element refs for click/fill/type. Scope with selector on complex pages. AI mode deduplicates delivered observations and supports snapshot IDs and diffs. Refs target elements in the latest captured scope; refresh a"
        },
        {
          "name": "browser_content",
          "description": "Get the content of the current page. Set format=\"markdown\" for clean markdown with structure preserved \u2014 preferred for LLM consumption. Returns up to maxChars (default 20000); pass offset to page through long pages."
        },
        {
          "name": "browser_screenshot",
          "description": "Take a screenshot of the current page (localhost pages included): the viewport as JPEG, downscaled to 1024 px wide, by default. For visual QA pass width/height (breakpoints 375 / 768 / 1440 \u2014 emulated for this capture only), fullPage for th"
        },
        {
          "name": "browser_console",
          "description": "Read the current tab's console messages and uncaught page errors (the last 200, kept from when SynaBun opened the tab), localhost pages included. Use level \"error\" to check a page for errors, and clear or since to see only what a reload or "
        },
        {
          "name": "browser_evaluate",
          "description": "Execute JavaScript in the browser page context and return the result. Useful for reading DOM state, extracting data, or performing actions not covered by other tools."
        },
        {
          "name": "browser_wait",
          "description": "Wait for an element to reach a certain state, a page load state, or a fixed timeout. Useful after navigation or clicks that trigger async content loading. Use loadState=\"networkidle\" after posting on Twitter/X or after navigation to ensure "
        },
        {
          "name": "browser_session",
          "description": "Manage browser sessions \u2014 list open sessions, create a new browser, or close an existing one."
        },
        {
          "name": "browser_cheatsheet",
          "description": "Look up stable selectors and flow notes for a social platform (twitter, facebook, tiktok, whatsapp, instagram, linkedin). Call this before automating a platform the first time in a session \u2014 then reuse the returned selectors for browser_cli"
        },
        {
          "name": "browser_extract_tweets",
          "description": "Extract visible tweets as structured JSON (author, handle, text, time, url, replies, reposts, likes, views). Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call (e.g. scrolls:3 minItems:30). Much faster than browser_snapsh"
        },
        {
          "name": "browser_x_compose_state",
          "description": "Inspect the X/Twitter compose surface in ONE call (read-only). Returns: composerOpen, composerText (read back from [data-testid=\"tweetTextarea_0\"]), charCount, overLimit; quoteCard {present, type:\"quote\"|\"link\"|\"none\", author, handle, text,"
        },
        {
          "name": "browser_extract_fb_posts",
          "description": "Extract visible Facebook posts as structured JSON (author, authorUrl, text, time, postUrl, reactions). Works on group feeds and Pages. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Much faster than browser_snapshot "
        },
        {
          "name": "browser_fb_composer_state",
          "description": "Inspect the Facebook posting surface in ONE call (read-only). Returns: modal {open,title,closeSelector,containsComposer} (modal.open is true ONLY for a visible posting dialog \u2014 FBs permanent hidden 0x0 Notifications dialog is ignored); trig"
        },
        {
          "name": "browser_extract_fb_groups",
          "description": "Extract ALL JOINED Facebook groups from the current page (navigate to facebook.com/groups/joins/?ordering=viewer_added first) as a region-sorted index. Auto-scrolls the full virtualized joins list and dedupes by url in ONE call (defaults: s"
        },
        {
          "name": "fb_groups",
          "description": "Structured Facebook group directory + per-group posting checklist (SQLite-backed; the single source of truth that replaces the free-text seed-queue). Actions: worklist {currency|region, offerSlug, limit?, freshDays?=14, includePending?=fals"
        },
        {
          "name": "browser_extract_tiktok_videos",
          "description": "Extract visible TikTok videos from the For You or Following feed as structured JSON (handle, videoUrl, caption, likes, comments, saves, shares, music). Navigate to tiktok.com/ or tiktok.com/following first. Pass scrolls/minItems to auto-scr"
        },
        {
          "name": "browser_extract_tiktok_search",
          "description": "Extract visible TikTok search result videos as structured JSON (videoUrl, handle, profileUrl, caption, views). Navigate to tiktok.com/search?q=<query> first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Much faster"
        },
        {
          "name": "browser_extract_tiktok_studio",
          "description": "Extract visible posts from TikTok Studio content list as structured JSON (title, url, date, privacy, stats[]). Navigate to tiktok.com/tiktokstudio/content first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Use thi"
        },
        {
          "name": "browser_extract_tiktok_profile",
          "description": "Extract profile info and video grid from a TikTok profile page as structured JSON (name, handle, bio, followers, following, likes, videos[{videoUrl, views}]). Navigate to tiktok.com/@username first. Scroll down to load more videos in the gr"
        },
        {
          "name": "browser_extract_wa_chats",
          "description": "Extract visible WhatsApp chats from the sidebar as structured JSON (name, lastMsg, time, unreadCount, muted, pinned). Must be on web.whatsapp.com with the chat list visible. Pass scrolls/minItems to auto-scroll the sidebar and dedupe in ONE"
        },
        {
          "name": "browser_extract_wa_messages",
          "description": "Extract visible messages from the open WhatsApp chat as structured JSON (sender, time, date, direction, text, dataId). Open a chat first by clicking span[title=\"Chat Name\"]. Pass scrolls/minItems to auto-scroll UP through history and dedupe"
        },
        {
          "name": "browser_extract_ig_feed",
          "description": "Extract visible Instagram feed posts as structured JSON (username, profileUrl, postUrl, caption, likes, comments, time, datetime, isSponsored, hasFollow). Navigate to instagram.com/ first. Pass scrolls/minItems to auto-scroll, extract, and "
        },
        {
          "name": "browser_extract_ig_profile",
          "description": "Extract Instagram profile data as structured JSON (username, displayName, bio, posts, followers, followerExact, following, isVerified, website, gridPosts, highlights). Navigate to instagram.com/username/ first. Returns bio, stats, post grid"
        },
        {
          "name": "browser_extract_ig_post",
          "description": "Extract a single Instagram post with comments as structured JSON (author, caption, likes, commentCount, time, datetime, comments[{username, text, time, datetime}]). Navigate to instagram.com/p/POST_ID/ or instagram.com/reel/REEL_ID/ first. "
        },
        {
          "name": "browser_extract_ig_reels",
          "description": "Extract visible Instagram Reels with engagement data as structured JSON (username, profileUrl, caption, likes, comments, audioName, audioUrl, hasFollow). Navigate to instagram.com/reels/ first. Pass scrolls/minItems to auto-scroll, extract,"
        },
        {
          "name": "browser_extract_ig_search",
          "description": "Extract posts from the Instagram Explore page as structured JSON (url, alt, isReel). Navigate to instagram.com/explore/ first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. For hashtag search, navigate to instagram."
        },
        {
          "name": "browser_extract_li_feed",
          "description": "Extract visible LinkedIn feed posts as structured JSON (author, authorUrl, headline, time, text, reactions, commentsCount, mediaType, articleTitle, articleLink, isPromoted, isRepost, postUrl). Navigate to linkedin.com/feed/ first. Pass scro"
        },
        {
          "name": "browser_extract_li_profile",
          "description": "Extract LinkedIn profile data as structured JSON (name, headline, location, profilePic, connections, about, sections[{heading, items[{title, subtitle, meta}]}], recentActivity). Navigate to linkedin.com/in/USERNAME/ first. Sections include "
        },
        {
          "name": "browser_extract_li_post",
          "description": "Extract a single LinkedIn post with comments as structured JSON (author, authorUrl, headline, time, text, reactions, commentsCount, postUrn, comments[{author, authorUrl, text, time, likes}]). Navigate to linkedin.com/feed/update/urn:li:acti"
        },
        {
          "name": "browser_extract_li_notifications",
          "description": "Extract LinkedIn notifications as structured JSON (text, time, isUnread, url, image). Navigate to linkedin.com/notifications/ first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Useful for monitoring engagement, co"
        },
        {
          "name": "browser_extract_li_messages",
          "description": "Extract LinkedIn messaging data as structured JSON with two arrays: conversations[{name, lastMessage, time, isUnread, url}] (sidebar list) and activeThread[{sender, text, time, direction}] (open conversation messages). Navigate to linkedin."
        },
        {
          "name": "browser_extract_li_search_people",
          "description": "Extract LinkedIn people search results as structured JSON (name, profileUrl, headline, location, mutual, actionButton, image). Navigate to linkedin.com/search/results/people/?keywords=QUERY first. Pass scrolls/minItems to auto-scroll, extra"
        },
        {
          "name": "browser_extract_li_network",
          "description": "Extract LinkedIn My Network data as structured JSON with two arrays: invitations[{name, subtitle, profileUrl, acceptLabel, ignoreLabel}] (pending connection requests) and suggestions[{name, subtitle, followers, profileUrl, action, image}] ("
        },
        {
          "name": "browser_extract_li_jobs",
          "description": "Extract LinkedIn job listings as structured JSON (jobId, title, company, companyUrl, location, salary, jobUrl, logo, promoted, easyApply, postedDate). Works on linkedin.com/jobs/ (recommendations) and linkedin.com/jobs/search/?keywords=QUER"
        },
        {
          "name": "bluesky_session",
          "description": "BlueSky: who am I? Returns the logged-in account (did, handle, pdsUrl). Use first to confirm you are signed in. A blank assigned tab is safely initialized at bsky.app; nonblank tabs are never navigated implicitly. An expired session token i"
        },
        {
          "name": "bluesky_timeline",
          "description": "BlueSky: read your home timeline (following feed) as compact JSON posts (uri, cid, author, text, counts, viewer). Pass maxItems to auto-paginate. Returns the next cursor."
        },
        {
          "name": "bluesky_author_feed",
          "description": "BlueSky: read a user's posts (author feed) as compact JSON. Pass actor (handle or DID), optional filter, and maxItems to auto-paginate."
        },
        {
          "name": "bluesky_thread",
          "description": "BlueSky: read a post and its thread (parents + replies) as compact JSON. Accepts an AT-URI or a bsky.app post URL. Each post includes uri+cid (needed to reply/like/repost)."
        },
        {
          "name": "bluesky_profile",
          "description": "BlueSky: get an actor profile (did, handle, name, bio, follower/following/post counts, and your viewer relationship: following/followedBy/muted/blocking)."
        },
        {
          "name": "bluesky_search_posts",
          "description": "BlueSky: full-text search posts. Supports sort (top/latest), since/until, author, lang. Pass maxItems to auto-paginate. Returns compact posts + next cursor."
        },
        {
          "name": "bluesky_search_actors",
          "description": "BlueSky: search for users (actors). Returns compact actor cards (did, handle, name, bio, viewer relationship) + next cursor. Pass maxItems to auto-paginate."
        },
        {
          "name": "bluesky_notifications",
          "description": "BlueSky: list your notifications (likes, reposts, replies, mentions, follows) as compact JSON. Pass markSeen:true to clear the unread badge, maxItems to auto-paginate."
        },
        {
          "name": "bluesky_graph",
          "description": "BlueSky: list an actor's followers or follows as compact actor cards + next cursor. Pass maxItems to auto-paginate."
        },
        {
          "name": "bluesky_likes",
          "description": "BlueSky: list likes. mode=post \u2192 the actors who liked a given post; mode=actor \u2192 the posts an actor has liked. Pass maxItems to auto-paginate."
        },
        {
          "name": "bluesky_feed",
          "description": "BlueSky: read a custom feed generator (mode=feed) or a list timeline (mode=list) by its AT-URI. Returns compact posts + next cursor. Pass maxItems to auto-paginate."
        },
        {
          "name": "bluesky_post",
          "description": "BlueSky: publish a post. Supports plain text with auto-facets (@mentions, links, #hashtags), replies (replyTo), quote-posts (quote), and up to 4 images (by url or local path, each with alt text). A link card (OG preview with thumbnail) is a"
        },
        {
          "name": "bluesky_action",
          "description": "BlueSky: act on a post or actor. Post: like/unlike, repost/unrepost, delete (your own). Actor: follow/unfollow, mute/unmute, block/unblock. Undo actions resolve the record key automatically \u2014 never pass rkeys."
        },
        {
          "name": "bluesky_resolve",
          "description": "BlueSky: resolve a handle to its DID (com.atproto.identity.resolveHandle)."
        },
        {
          "name": "bluesky_dm",
          "description": "BlueSky DMs (chat.bsky.*): list_convos, read messages in a convo, send a message (by convoId or members), or mark_read. Returns compact JSON."
        },
        {
          "name": "gsc_navigate",
          "description": "Open a Google Search Console page (overview, performance, inspect, pages, sitemaps, removals, links, security, settings, etc.). Always call before any gsc_* tool to land on the right report. Pages: overview, insights, performance_search, pe"
        },
        {
          "name": "gsc_property",
          "description": "Manage GSC property selection \u2014 list registered properties, switch the active one (re-navigates current page), read the active property from the URL, or open the Add Property dialog. [mutating for action=add \u2014 adds a new property to the Goo"
        },
        {
          "name": "gsc_inspect_url",
          "description": "Run URL Inspection on a URL \u2014 opens the inspect tool, fills the URL, polls up to 30s for the result panel, returns structured JSON (pageIndexed, verdict, indexingState, coverage, canonicalUser, canonicalGoogle, lastCrawl, crawlStatus, crawl"
        },
        {
          "name": "gsc_inspect_test_live",
          "description": "Click the \"Test live URL\" button on the URL Inspection page and poll up to 90s for results. Useful to verify a live page after a fix without waiting for re-indexing. Returns same shape as gsc_inspect_url with `liveTest:true`."
        },
        {
          "name": "gsc_inspect_request_indexing",
          "description": "[mutating \u2014 affects Google's crawl queue] Submit a URL to Google's indexing queue. Clicks \"Request indexing\" on the inspection result page (running a live test first if needed). Polls for the success/error modal and returns `{ requested, qu"
        },
        {
          "name": "gsc_inspect_view_crawled",
          "description": "Open the \"View crawled page\" panel from the URL Inspection result and switch to the requested view (html / screenshot / http_response / more_info). Use browser_screenshot or browser_snapshot afterwards to capture content."
        },
        {
          "name": "gsc_performance_query",
          "description": "Run a Performance report query \u2014 sets searchType, dateRange (preset or custom), primary dimension, chip filters, and optional comparison; returns total clicks/impressions/CTR/position plus full table rows as JSON. Auto-scrolls the grid to l"
        },
        {
          "name": "gsc_performance_export",
          "description": "Trigger Performance report export menu in the active tab. Format: csv \u2192 ZIP download; excel \u2192 XLSX; google_sheets \u2192 opens a new Sheet. Browser handles the actual download to its default download dir."
        }
      ],
      "toolCount": 80,
      "resourceCount": 0,
      "promptCount": 0,
      "stderrExcerpt": "[SynaBun] Tools (strict): browser,browser_twitter,browser_facebook,browser_tiktok,browser_whatsapp,browser_instagram,browser_linkedin,browser_bluesky,gsc,youtube,discord,whiteboard,card,git,image,styleguide,morelogin,tictactoe (18 groups, instructions: 4975 chars)\n[SynaBun] Changing this runtime's tools never rewrites ~/.codex/config.toml: the canonical Codex registration loads every SynaBun tool (SYNABUN_TOOLS=all, deferred catalog) and a tool list only sets a Codex runtime's focus.",
      "network": "disabled",
      "networkAttemptedWhileOffline": false,
      "outboundHosts": [],
      "requiresCredentials": false
    }
  },
  "tier": "tested",
  "tierReason": "Sandbox handshake completed, with warnings: advisories, install scripts present.",
  "logExcerpt": "[SynaBun] Tools (strict): browser,browser_twitter,browser_facebook,browser_tiktok,browser_whatsapp,browser_instagram,browser_linkedin,browser_bluesky,gsc,youtube,discord,whiteboard,card,git,image,styleguide,morelogin,tictactoe (18 groups, instructions: 4975 chars)\n[SynaBun] Changing this runtime's tools never rewrites ~/.codex/config.toml: the canonical Codex registration loads every SynaBun tool (SYNABUN_TOOLS=all, deferred catalog) and a tool list only sets a Codex runtime's focus."
}