newtype
::: newtype의 지식창고 :::
newtype
전체 방문자
오늘
어제
  • 분류 전체보기 (399)
    • Dev (221)
      • AI (1)
      • Go (6)
      • C, C++ (44)
      • Web (52)
      • DBMS (21)
      • DevOps (8)
      • Java (2)
      • Windows, Win32 (4)
      • Visual Basic (5)
      • C# (2)
      • Mobile (25)
      • SQL CE (7)
      • Google Map (6)
      • Python (2)
      • cygwin (2)
      • 기타 (33)
      • Ruby (1)
    • 명언 (10)
    • 모임 (18)
      • 붕주회 (3)
      • 신흥컴정 (14)
      • 웹20기 (1)
    • 사진 (8)
    • 불펌 (29)
    • 막글 (98)
    • 게임 (6)
    • 여행 (8)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 관리

공지사항

  • whoami
02-18 00:03
hELLO · Designed By 정상우.
newtype

::: newtype의 지식창고 :::

Dev/AI

Mac mini 에 openclaw 설치기.

2026. 2. 17. 21:24

내 봇이 멍청하다.

  • 처음에 설치하고 원인 모를 오동작, 멍청한 답변 토해냈다.
  • mac mini 기본형에 ollama를 올려서 local LLM을 사용한 것이 잘못된 선택이었다.
  • 무조건 LLM api키를 받아서 연동해야하며 비싼 모델일수록 똑똑해진다.

 

openclaw-bundled 스킬들이 제대로 동작하지 않는다

  • 최초 설치를 npm으로 했는데, 뭔가 경로가 꼬였는지, summarize 등을 실행하지 못해서 유튜브 요약등이 동작하지 않았다.
curl -fsSL https://openclaw.ai/install.sh | bash
  • 위 명령으로 해결했다. 

 

토큰 불일치 오류

% openclaw gateway status
 gateway connect failed: Error: unauthorized: device token mismatch (rotate/reissue device token)
  • 몇 번 재설치를 하다보니, gateway 상태를 보면 토큰 불일치 오류가 발생했다.
  • 이 상태에선 cron 등록등 여러 가지 기능이 동작하지 않는다.
  • 설치하면 gateway 토큰이 openclaw.json 에도 저장되는데, osx의 launchctl(linux의 systemd)의 plist 파일에도 저장된다. - 이걸 몰라서 한참 고생함.
  • openclaw.json의 token을 복사해서, launchctl plist파일에도 수정해줘야 한다.
% grep token ~/.openclaw/openclaw.json
      "token": "토큰 문자열"

% grep -A 1 TOKEN ~/Library/LaunchAgents/ai.openclaw.gateway.plist
    <key>OPENCLAW_GATEWAY_TOKEN</key>
    <string>토큰 문자열</string>

 

web_search가 동작하지 않는다.

  • 번들은 web_search는 brave_api_key를 필요로 하는데, api 발급을 받으려 해도 무료 플랜이 사라졌다.
  • clawhub.ai 에서 설치해도 되는데, 왠지 꺼림직해서 직접 만들었다.
% cat ~/.openclaw/workspace/skills/ddg-search/SKILL.md
---
name: ddg-search
description: |
  DuckDuckGo-based web search without requiring API keys. Use this skill whenever the user asks to search the web, find information online, look up current events, or needs any information that might be on the internet. Triggers include: "검색해줘", "찾아봐", "search for", "look up", "find information about", or any request for web/online information. This skill is ALWAYS preferred over web_search (which requires Brave API key). Use it liberally - if there's any chance the answer is online, use this skill.
compatibility:
  tools_required:
    - Bash
  dependencies:
    - duckduckgo-search (Python package)
---

# DuckDuckGo Search Skill

Fast, API-key-free web search using DuckDuckGo.

## When to Use

- User asks to search the web ("검색해줘", "찾아봐", "search for X")
- Looking up current information, news, or facts
- Finding websites, documentation, or resources
- Any query that might benefit from web search

## Usage

```bash
python3 ~/.openclaw/workspace/.skills/skills/ddg-search/scripts/search.py "검색어" --max-results 5
```

## Output Format

Returns JSON:
```json
{
  "query": "search query",
  "results": [
    {
      "title": "Result title",
      "url": "https://example.com",
      "snippet": "Description of the result"
    }
  ],
  "count": 5
}
```

## Examples

### Search for Python latest version
```bash
python3 scripts/search.py "Python latest version" --max-results 5
```

### Search in Korean
```bash
python3 scripts/search.py "파이썬 최신 버전" --max-results 5
```

## Installation

```bash
pip install ddgs --break-system-packages
```

## Notes

- No API key required
- Returns up to specified max results (default: 5)
- Works with any language
- Safe for frequent use (no rate limits with API keys)
% cat ~/.openclaw/workspace/skills/ddg-search/scripts/search.py
#!/usr/bin/env python3
"""
DuckDuckGo Search Script for OpenClaw
No API key required - uses ddgs package
"""

import sys
import json
import argparse
from typing import List, Dict

try:
    from ddgs import DDGS
except ImportError:
    print(json.dumps({
        "error": "ddgs 패키지가 설치되지 않았습니다",
        "install": "pip install ddgs --break-system-packages",
        "results": []
    }), file=sys.stderr)
    sys.exit(1)

def search_ddg(query: str, max_results: int = 5) -> List[Dict[str, str]]:
    """
    Search DuckDuckGo and return results

    Args:
        query: Search query string
        max_results: Maximum number of results to return

    Returns:
        List of dictionaries with title, url, and snippet
    """
    results = []

    try:
        with DDGS() as ddgs:
            search_results = ddgs.text(query, max_results=max_results)

            for result in search_results:
                results.append({
                    "title": result.get("title", ""),
                    "url": result.get("href", ""),
                    "snippet": result.get("body", "")
                })

    except Exception as e:
        error_msg = {
            "error": str(e),
            "query": query,
            "results": []
        }
        print(json.dumps(error_msg, ensure_ascii=False, indent=2), file=sys.stderr)
        return []

    return results

def main():
    parser = argparse.ArgumentParser(
        description='Search DuckDuckGo without API keys'
    )
    parser.add_argument(
        'query',
        type=str,
        help='Search query'
    )
    parser.add_argument(
        '--max-results',
        type=int,
        default=5,
        help='Maximum number of results (default: 5)'
    )

    args = parser.parse_args()

    # Perform search
    results = search_ddg(args.query, args.max_results)

    # Output JSON
    output = {
        "query": args.query,
        "results": results,
        "count": len(results)
    }

    print(json.dumps(output, ensure_ascii=False, indent=2))

if __name__ == "__main__":
    main()
반응형
저작자표시 (새창열림)
    newtype
    newtype
    지극히 개인적인 지식의 창고

    티스토리툴바