Repository Analysis

qwibitai/nanoclaw

A lightweight alternative to OpenClaw that runs in containers for security. Connects to WhatsApp, Telegram, Slack, Discord, Gmail and other messaging apps,, has memory, scheduled jobs, and runs directly on Anthropic's Agents SDK

3.5 Likely human-written View on GitHub
3.5
Adjusted Score
3.5
Raw Score
100%
Time Factor
2026-05-30
Last Push
29,535
Stars
TypeScript
Language
73,163
Lines of Code
456
Files
147
Pattern Hits
2026-05-31
Scan Date

Score History

Severity Breakdown

CRITICAL 0HIGH 1MEDIUM 50LOW 96

Pattern Findings

147 matches across 9 categories. Click a row to expand file-level details.

Decorative Section Separators49 hits · 146 pts
SeverityFileLineSnippet
MEDIUMnanoclaw.sh40# ─── log helpers ────────────────────────────────────────────────────────
MEDIUMnanoclaw.sh99# ─── bash-side "clack-alike" status line ────────────────────────────────
MEDIUMnanoclaw.sh125# ─── fresh-run setup ────────────────────────────────────────────────────
MEDIUMnanoclaw.sh140# ─── pre-flight: minimum hardware specs ────────────────────────────────
MEDIUMnanoclaw.sh190# ─── pre-flight: Google Cloud VM warning (Linux) ──────────────────────
MEDIUMnanoclaw.sh217# ─── pre-flight: root user warning (Linux) ────────────────────────────
MEDIUMnanoclaw.sh250# ─── pre-flight: Homebrew on macOS ─────────────────────────────────────
MEDIUMnanoclaw.sh298# ─── first step: install the basics (Node + pnpm + native modules) ─────
MEDIUMnanoclaw.sh351# ─── hand off to setup:auto ────────────────────────────────────────────
MEDIUMmigrate-v2.sh111# ─── output helpers ──────────────────────────────────────────────────────
MEDIUMmigrate-v2.sh131# ─── init logs ───────────────────────────────────────────────────────────
MEDIUMmigrate-v2.sh145# ─── phase 0a: bootstrap prerequisites ──────────────────────────────────
MEDIUMmigrate-v2.sh192# ─── phase 0b: find v1 install ──────────────────────────────────────────
MEDIUMmigrate-v2.sh241# ─── phase 0c: validate v1 DB ───────────────────────────────────────────
MEDIUMmigrate-v2.sh277# ─── run_step helper ─────────────────────────────────────────────────────
MEDIUMmigrate-v2.sh324# ─── phase 1: core state ────────────────────────────────────────────────
MEDIUMmigrate-v2.sh353# ─── phase 2: channels (interactive) ────────────────────────────────────
MEDIUMmigrate-v2.sh427# ─── phase 3: infrastructure ────────────────────────────────────────────
MEDIUMmigrate-v2.sh556# ─── service switchover ─────────────────────────────────────────────────
MEDIUMmigrate-v2.sh681# ─── phase 4: handoff ───────────────────────────────────────────────────
MEDIUMmigrate-v2.sh736# ─── hand off to Claude ─────────────────────────────────────────────────
MEDIUMsetup/auto.ts598// ─── first-chat step ───────────────────────────────────────────────────
MEDIUMsetup/auto.ts705// ─── auth step (select → branch) ────────────────────────────────────────
MEDIUMsetup/auto.ts952// ─── timezone step ─────────────────────────────────────────────────────
MEDIUMsetup/auto.ts1078// ─── prompts owned by the sequencer ────────────────────────────────────
MEDIUMsetup/auto.ts1164// ─── interactive / env helpers ─────────────────────────────────────────
MEDIUMsetup/auto.ts1260// ─── intro + progression-log init ──────────────────────────────────────
MEDIUMsetup/migrate-v2/shared.ts5// ── JID parsing ─────────────────────────────────────────────────────────
MEDIUMsetup/migrate-v2/shared.ts98// ── Trigger mapping ─────────────────────────────────────────────────────
MEDIUMsetup/migrate-v2/shared.ts128// ── ID generation ───────────────────────────────────────────────────────
MEDIUMsetup/migrate-v2/shared.ts134// ── Channel auth registry ───────────────────────────────────────────────
MEDIUMsetup/lib/setup-config.ts137// ─── name derivation ───────────────────────────────────────────────────
MEDIUMsetup/lib/teams-manifest.ts111// ─── Minimal PNG encoder (solid color, no external deps) ──────────────────
MEDIUMsetup/channels/teams.ts124// ─── step: intro / prereqs ──────────────────────────────────────────────
MEDIUMsetup/channels/teams.ts187// ─── step: public URL ──────────────────────────────────────────────────
MEDIUMsetup/channels/teams.ts240// ─── step: Azure App Registration ──────────────────────────────────────
MEDIUMsetup/channels/teams.ts326// ─── step: client secret ───────────────────────────────────────────────
MEDIUMsetup/channels/teams.ts385// ─── step: Azure Bot resource ──────────────────────────────────────────
MEDIUMsetup/channels/teams.ts437// ─── step: enable Teams channel ────────────────────────────────────────
MEDIUMsetup/channels/teams.ts464// ─── step: manifest zip ────────────────────────────────────────────────
MEDIUMsetup/channels/teams.ts508// ─── step: sideload ────────────────────────────────────────────────────
MEDIUMsetup/channels/teams.ts540// ─── step: install adapter ─────────────────────────────────────────────
MEDIUMsetup/channels/teams.ts577// ─── post-install: hand off to Claude for the final wiring ────────────
MEDIUMsetup/channels/teams.ts644// ─── shared step gate ──────────────────────────────────────────────────
MEDIUMsetup/channels/teams.ts708// ─── shared: UUID paste with help escape ───────────────────────────────
MEDIUMsetup/channels/teams.ts744// ─── path helpers ──────────────────────────────────────────────────────
MEDIUMdocs/ollama.md15│ http://host.docker. │ ┌──────────────────┐
MEDIUMsrc/host-sweep.test.ts157// ─────────────────────────────────────────────────────────────────────────────
MEDIUMsrc/host-sweep.test.ts168// ─────────────────────────────────────────────────────────────────────────────
Hyper-Verbose Identifiers59 hits · 62 pts
SeverityFileLineSnippet
LOWsetup/environment.ts38export function detectExistingDisplayName(projectRoot: string): string | null {
LOWsetup/onecli.ts124function removeLegacyOnecliContainers(): string {
LOWsetup/channels/imessage.ts186async function walkThroughFullDiskAccess(): Promise<void> {
LOWsetup/channels/discord.ts186function showTokenLocationReminder(hasExistingBot: boolean): void {
LOWsetup/channels/discord.ts219async function walkThroughServerCreation(): Promise<void> {
LOWsetup/channels/discord.ts407async function promptForUserIdWithDevMode(): Promise<string> {
LOWsetup/channels/whatsapp.ts437function writeAssistantHasOwnNumber(): void {
LOWdocs/SPEC.md152export function getRegisteredChannelNames(): string[] {
LOWcontainer/agent-runner/src/poll-loop.ts265function formatMessagesWithCommands(messages: MessageInRow[], nativeSlashCommands: boolean): string {
LOWcontainer/agent-runner/src/destinations.ts82export function buildSystemPromptAddendum(assistantName?: string): string {
LOWcontainer/agent-runner/src/db/session-state.ts52export function migrateLegacyContinuation(providerName: string): string | undefined {
LOWcontainer/agent-runner/src/db/connection.ts136export function clearContainerToolInFlight(): void {
LOWsrc/host-sweep.ts228function enforceRunningContainerSla(
LOWsrc/container-restart.ts21export function restartAgentGroupContainers(agentGroupId: string, reason: string, wakeMessage?: string): number {
LOWsrc/claude-md-compose.ts152export function migrateGroupsToClaudeLocal(): void {
LOWsrc/container-runtime.ts37export function ensureContainerRuntimeRunning(): void {
LOWsrc/container-runner.ts225function resolveProviderContribution(
LOWsrc/providers/provider-container-registry.ts45export function registerProviderContainerConfig(name: string, fn: ProviderContainerConfigFn): void {
LOWsrc/providers/provider-container-registry.ts52export function getProviderContainerConfig(name: string): ProviderContainerConfigFn | undefined {
LOWsrc/providers/provider-container-registry.ts56export function listProviderContainerConfigNames(): string[] {
LOWsrc/cli/resources/destinations.ts18async function projectDestinationsToSessions(agentGroupId: string): Promise<void> {
LOWsrc/cli/commands/help.ts73export function registerResourceHelpCommands(): void {
LOWsrc/db/session-db.ts213export function deleteOrphanProcessingClaims(outDb: Database.Database): number {
LOWsrc/db/session-db.ts340export function getInboundSourceSessionId(db: Database.Database, messageId: string): string | null {
LOWsrc/db/session-db.ts358export function getMostRecentPeerSourceSessionId(db: Database.Database, peerAgentGroupId: string): string | null {
LOWsrc/db/container-configs.ts53export function updateContainerConfigScalars(
LOWsrc/db/container-configs.ts83export function updateContainerConfigJson(
LOWsrc/db/sessions.ts183export function updatePendingApprovalStatus(approvalId: string, status: PendingApproval['status']): void {
LOWsrc/db/sessions.ts191export function getPendingApprovalsByAction(action: string): PendingApproval[] {
LOWsrc/db/messaging-groups.ts34export function getMessagingGroupByPlatform(channelType: string, platformId: string): MessagingGroup | undefined {
LOWsrc/db/messaging-groups.ts53export function getMessagingGroupWithAgentCount(
LOWsrc/db/messaging-groups.ts75export function getMessagingGroupsByChannel(channelType: string): MessagingGroup[] {
LOWsrc/db/messaging-groups.ts113export function setMessagingGroupDeniedAt(id: string, deniedAt: string | null): void {
LOWsrc/db/messaging-groups.ts132export function createMessagingGroupAgent(mga: MessagingGroupAgent): void {
LOWsrc/db/messaging-groups.ts199export function getMessagingGroupAgentByPair(
LOWsrc/db/messaging-groups.ts214export function updateMessagingGroupAgent(
LOWsrc/db/messaging-groups.ts239export function deleteMessagingGroupAgent(id: string): void {
LOWsrc/db/messaging-groups.ts244export function getMessagingGroupsByAgentGroup(agentGroupId: string): MessagingGroup[] {
LOWsrc/modules/mount-security/index.ts361export function generateAllowlistTemplate(): string {
LOWsrc/modules/permissions/channel-approval.ts80function visibleAgentGroupsForApprover(
LOWsrc/modules/permissions/channel-approval.ts254export function buildAgentSelectionOptions(
LOWsrc/modules/permissions/index.ts225async function handleSenderApprovalResponse(payload: ResponsePayload): Promise<boolean> {
LOWsrc/modules/permissions/index.ts310async function handleChannelApprovalResponse(payload: ResponsePayload): Promise<boolean> {
LOWsrc/modules/permissions/db/pending-channel-approvals.ts26export function createPendingChannelApproval(row: PendingChannelApproval): void {
LOWsrc/modules/permissions/db/pending-channel-approvals.ts41export function getPendingChannelApproval(messagingGroupId: string): PendingChannelApproval | undefined {
LOWsrc/modules/permissions/db/pending-channel-approvals.ts47export function hasInFlightChannelApproval(messagingGroupId: string): boolean {
LOWsrc/modules/permissions/db/pending-channel-approvals.ts54export function updatePendingChannelApprovalCard(messagingGroupId: string, title: string, optionsJson: string): void {
LOWsrc/modules/permissions/db/pending-channel-approvals.ts60export function deletePendingChannelApproval(messagingGroupId: string): void {
LOWsrc/modules/permissions/db/pending-sender-approvals.ts28export function createPendingSenderApproval(row: PendingSenderApproval): void {
LOWsrc/modules/permissions/db/pending-sender-approvals.ts51export function hasInFlightSenderApproval(messagingGroupId: string, senderIdentity: string): boolean {
LOWsrc/modules/permissions/db/pending-sender-approvals.ts58export function deletePendingSenderApproval(id: string): void {
LOWsrc/modules/agent-to-agent/db/agent-destinations.ts107export function deleteAllDestinationsTouching(agentGroupId: string): void {
LOWsrc/modules/agent-to-agent/db/agent-destinations.ts120export function getDestinationReferencers(targetAgentGroupId: string): string[] {
LOWsrc/modules/typing/index.ts154export function pauseTypingRefreshAfterDelivery(sessionId: string): void {
LOWsrc/modules/interactive/index.ts20async function handleInteractiveResponse(payload: ResponsePayload): Promise<boolean> {
LOWsrc/modules/approvals/onecli-approvals.ts85export function startOneCLIApprovalHandler(deliveryAdapter: ChannelDeliveryAdapter): void {
LOWsrc/modules/approvals/onecli-approvals.ts103export function stopOneCLIApprovalHandler(): void {
LOWsrc/channels/channel-registry.ts40export function getRegisteredChannelNames(): string[] {
LOWsrc/channels/channel-registry.ts45export function getChannelContainerConfig(name: string): ChannelRegistration['containerConfig'] {
Over-Commented Block33 hits · 33 pts
SeverityFileLineSnippet
LOWsetup.sh1#!/bin/bash
LOWnanoclaw.sh1#!/usr/bin/env bash
LOWmigrate-v2.sh1#!/usr/bin/env bash
LOWmigrate-v2-reset.sh1#!/usr/bin/env bash
LOWsetup/add-discord.sh1#!/usr/bin/env bash
LOWsetup/add-telegram.sh1#!/usr/bin/env bash
LOWsetup/install-matrix.sh1#!/usr/bin/env bash
LOWsetup/add-teams.sh1#!/usr/bin/env bash
LOWsetup/add-imessage.sh1#!/usr/bin/env bash
LOWsetup/probe.sh1#!/bin/bash
LOWsetup/register-claude-token.sh1#!/usr/bin/env bash
LOWsetup/install-signal-cli.sh1#!/usr/bin/env bash
LOWsetup/install-claude.sh1#!/usr/bin/env bash
LOWsetup/install-linear.sh1#!/usr/bin/env bash
LOWsetup/install-whatsapp.sh1#!/usr/bin/env bash
LOWsetup/add-signal.sh1#!/usr/bin/env bash
LOWsetup/add-whatsapp.sh1#!/usr/bin/env bash
LOWsetup/add-slack.sh1#!/usr/bin/env bash
LOWsetup/lib/install-slug.sh1# install-slug.sh — shell mirror of setup/lib/install-slug.ts.
LOWsetup/lib/channels-remote.sh1# channels-remote.sh — resolve the git remote that carries the `channels`
LOWsetup/lib/diagnostics.sh1# diagnostics.sh — shared PostHog emitter for bash-side setup code.
LOWcontainer/build.sh1#!/bin/bash
LOWcontainer/entrypoint.sh1#!/bin/bash
LOWcontainer/agent-runner/src/poll-loop.ts341 // Skip system messages (MCP tool responses).
LOWcontainer/agent-runner/src/poll-loop.ts421 try {
LOWscripts/cleanup-sessions.sh1#!/bin/bash
LOWsrc/delivery.ts261 // Guarded by the channel_type check. If the module isn't installed the
LOWsrc/delivery.ts281 // targeting that messaging group. createMessagingGroupAgent() inserts
LOWsrc/providers/index.ts1// Host-side provider container-config barrel.
LOWsrc/cli/dispatch.ts141 // - `list` → drop rows that don't belong to the caller's agent group
LOWsrc/db/messaging-groups.ts141 @id, @messaging_group_id, @agent_group_id,
LOWsrc/channels/chat-sdk-bridge.ts521 return true;
LOWsrc/channels/index.ts1// Channel self-registration barrel.
Magic Placeholder Names1 hit · 5 pts
SeverityFileLineSnippet
HIGH.claude/skills/add-imessage/SKILL.md95IMESSAGE_API_KEY=your-api-key
AI Slop Vocabulary1 hit · 3 pts
SeverityFileLineSnippet
MEDIUMsetup/signal-auth.ts158 // rather than scraping stdout — more robust across signal-cli versions.
Redundant / Tautological Comments1 hit · 2 pts
SeverityFileLineSnippet
LOWmigrate-v2.sh597# Check if v1 service is running
Fake / Example Data1 hit · 1 pts
SeverityFileLineSnippet
LOWcontainer/skills/agent-browser/SKILL.md144agent-browser fill @e1 "user@example.com"
Excessive Try-Catch Wrapping1 hit · 1 pts
SeverityFileLineSnippet
LOWrepo-tokens/action.yml92 except Exception as e:
Overly Generic Function Names1 hit · 1 pts
SeverityFileLineSnippet
LOWsrc/modules/approvals/onecli-approvals.ts113async function handleRequest(request: ApprovalRequest): Promise<Decision> {