Skip to content

channprj/kmsg

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

68 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

kmsg

kmsg logo

Disclaimer: kmsg๋Š” Kakao Corp. ์˜ ๊ณต์‹ ๋„๊ตฌ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ๋ณธ์ธ ๊ณ„์ •/ํ™˜๊ฒฝ์—์„œ ๊ด€๋ จ ๋ฒ•๊ทœ, ์„œ๋น„์Šค ์•ฝ๊ด€, ํšŒ์‚ฌ ๋ณด์•ˆ ์ •์ฑ…์„ ์ค€์ˆ˜ํ•  ์ฑ…์ž„์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋„๊ตฌ ์‚ฌ์šฉ์œผ๋กœ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ„์ • ์ œํ•œ, ์˜ค์ž‘๋™, ๋ฐ์ดํ„ฐ ์†์‹ค, ๊ธฐํƒ€ ์†ํ•ด์— ๋Œ€ํ•œ ์ฑ…์ž„์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค.

kmsg ๋Š” macOS์—์„œ ์นด์นด์˜คํ†ก ๋ฉ”์‹œ์ง€๋ฅผ CLI ๋กœ ์ฝ๊ณ  ๋ณด๋‚ด๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ๋‹จ์ˆœํ•œ ์ˆ˜๋™ CLI ๋ฅผ ๋„˜์–ด, AI Agent ๋˜๋Š” Hook ์ด๋ฒคํŠธ ๋“ฑ์˜ ์ž๋™ํ™” ํŒŒ์ดํ”„๋ผ์ธ์— ์—ฐ๊ฒฐํ•˜๊ธฐ ์‰ฝ๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. kmsg ๋Š” openclaw ์˜ ์ฐฝ์‹œ์ž์ธ steipete ๊ฐ€ ๋งŒ๋“  iMessage ์ปจํŠธ๋กค์„ ์œ„ํ•œ CLI ๋„๊ตฌ์ธ imsg ์— ์˜๊ฐ์„ ๋ฐ›์•„ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Demo

record.mp4

๋น ๋ฅธ ์‹œ์ž‘

์š”๊ตฌ์‚ฌํ•ญ:

์„ค์น˜ (Homebrew ๊ถŒ์žฅ)

brew install channprj/tap/kmsg

์„ค์น˜ (์ง์ ‘ ๋‹ค์šด๋กœ๋“œ)

mkdir -p ~/.local/bin && curl -fL https://github.com/channprj/kmsg/releases/latest/download/kmsg-macos-universal -o ~/.local/bin/kmsg && chmod +x ~/.local/bin/kmsg

์„ค์น˜ ํ™•์ธ์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

kmsg status

๊ถŒํ•œ ํŒ์—…์ด ๋œจ๋ฉด ํ—ˆ์šฉํ•ด ์ฃผ์„ธ์š”.

kmsg๋ฅผ ๋ฐ”๋กœ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด PATH ๋“ฑ๋ก์„ ํ•ด์ฃผ์„ธ์š”.

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc

๊ฐ€์žฅ ๋งŽ์ด ์“ฐ๋Š” ๋ช…๋ น

kmsg status
kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "์•ˆ๋…•ํ•˜์„ธ์š”"
kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "$(date '+%Y-%m-%d %H:%M:%S') ํ…Œ์ŠคํŠธ"
kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "ํ…Œ์ŠคํŠธ" --keep-window
kmsg send-image "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "/path/to/image.png"
kmsg chats
kmsg read "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" --limit 20
kmsg read "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" --limit 20 --keep-window
kmsg read "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" --limit 20 --json
kmsg read "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" --limit 20 --deep-recovery
kmsg inspect --window 0 --depth 20 --debug-layout

CLI ๋ช…๋ น์–ด ๋ ˆํผ๋Ÿฐ์Šค

์˜ต์…˜์€ ๋นŒ๋“œ ๊ธฐ์ค€ kmsg --help, kmsg <command> --help ์ถœ๋ ฅ๊ณผ ๋™์ผํ•˜๊ฒŒ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

status

kmsg status [--verbose]
  • --verbose: ์ƒ์„ธ ์ƒํƒœ ์ถœ๋ ฅ

chats

kmsg chats [--verbose] [--limit <limit>] [--trace-ax]
  • -v, --verbose: ์ƒ์„ธ ์ •๋ณด ์ถœ๋ ฅ
  • -l, --limit <limit>: ์ตœ๋Œ€ ์ฑ„ํŒ… ๋ชฉ๋ก ๊ฐœ์ˆ˜ (๊ธฐ๋ณธ๊ฐ’: 20)
  • --trace-ax: AX ํƒ์ƒ‰/์žฌ์‹œ๋„ ๋กœ๊ทธ ์ถœ๋ ฅ

read

kmsg read <chat> [--limit <limit>] [--debug] [--trace-ax] [--keep-window] [--deep-recovery] [--json]
  • -l, --limit <limit>: ์ตœ๋Œ€ ๋ฉ”์‹œ์ง€ ๊ฐœ์ˆ˜ (๊ธฐ๋ณธ๊ฐ’: 20)
  • --debug: raw element ๋””๋ฒ„๊ทธ ์ •๋ณด ์ถœ๋ ฅ
  • --trace-ax: AX ํƒ์ƒ‰/์žฌ์‹œ๋„ ๋กœ๊ทธ ์ถœ๋ ฅ
  • -k, --keep-window: ์ž๋™์œผ๋กœ ์—ฐ ์ฑ„ํŒ…์ฐฝ ์œ ์ง€
  • --deep-recovery: ๋น ๋ฅธ ํƒ์ƒ‰ ์‹คํŒจ ์‹œ deep recovery ์ˆ˜ํ–‰
  • --json: JSON ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅ

send

kmsg send <recipient> <message> [--dry-run] [--trace-ax] [--no-cache] [--refresh-cache] [--keep-window] [--deep-recovery]
  • --dry-run: ์‹ค์ œ ์ „์†ก ์—†์ด ์‹œ๋ฎฌ๋ ˆ์ด์…˜
  • --trace-ax: AX ํƒ์ƒ‰/์žฌ์‹œ๋„ ๋กœ๊ทธ ์ถœ๋ ฅ
  • --no-cache: ์ด๋ฒˆ ์‹คํ–‰์—์„œ AX path cache ๋น„ํ™œ์„ฑํ™”
  • --refresh-cache: ์ด๋ฒˆ ์‹คํ–‰์—์„œ AX path cache ๊ฐ•์ œ ์žฌ๊ตฌ์„ฑ
  • -k, --keep-window: ์ž๋™์œผ๋กœ ์—ฐ ์ฑ„ํŒ…์ฐฝ ์œ ์ง€
  • --deep-recovery: ๋น ๋ฅธ ํƒ์ƒ‰ ์‹คํŒจ ์‹œ deep recovery ์ˆ˜ํ–‰

send-image

kmsg send-image <recipient> <image-path> [--trace-ax] [--no-cache] [--keep-window] [--deep-recovery]
  • --trace-ax: AX ํƒ์ƒ‰/์žฌ์‹œ๋„ ๋กœ๊ทธ ์ถœ๋ ฅ
  • --no-cache: ์ด๋ฒˆ ์‹คํ–‰์—์„œ AX path cache ๋น„ํ™œ์„ฑํ™”
  • -k, --keep-window: ์ž๋™์œผ๋กœ ์—ฐ ์ฑ„ํŒ…์ฐฝ ์œ ์ง€
  • --deep-recovery: ๋น ๋ฅธ ํƒ์ƒ‰ ์‹คํŒจ ์‹œ deep recovery ์ˆ˜ํ–‰

inspect

kmsg inspect [--depth <depth>] [--window <window>] [--show-attributes] [--show-path] [--show-frame] [--show-index] [--show-flags] [--show-actions] [--debug-layout] [--row-summary] [--row-range <start:end>]
  • -d, --depth <depth>: ์ตœ๋Œ€ ํƒ์ƒ‰ ๊นŠ์ด (๊ธฐ๋ณธ๊ฐ’: 4)
  • -w, --window <window>: inspect ๋Œ€์ƒ ์ฐฝ ์ธ๋ฑ์Šค (๊ธฐ๋ณธ๊ฐ’: main window)
  • --show-attributes: ๊ฐ ์š”์†Œ์˜ AX attribute ์ถœ๋ ฅ
  • --show-path: ๊ฐ ์š”์†Œ์˜ AX ๊ฒฝ๋กœ ์ถœ๋ ฅ
  • --show-frame: ๊ฐ ์š”์†Œ frame ์ถœ๋ ฅ
  • --show-index: sibling index ์ถœ๋ ฅ
  • --show-flags: ์ƒํƒœ ํ”Œ๋ž˜๊ทธ(enabled/focused/selected/editable) ์ถœ๋ ฅ
  • --show-actions: ์ง€์› AX action ์ถœ๋ ฅ
  • --debug-layout: path/frame/index/flags๋ฅผ ํ•œ ๋ฒˆ์— ์ผœ๋Š” ๋ ˆ์ด์•„์›ƒ ๋””๋ฒ„๊ทธ ๋ฒˆ๋“ค
  • --row-summary: ๋ฉ”์‹œ์ง€ row ์š”์•ฝ ์ถœ๋ ฅ
  • --row-range <start:end>: --row-summary ๊ฒฐ๊ณผ๋ฅผ ํŠน์ • ๋ฒ”์œ„๋งŒ ์ถœ๋ ฅ (inclusive, zero-based)

cache

kmsg help cache
  • status (default): ์บ์‹œ ์ƒํƒœ ์ถœ๋ ฅ
  • clear: ์บ์‹œ ์‚ญ์ œ
  • export <output-path>: ์บ์‹œ JSON ๋‚ด๋ณด๋‚ด๊ธฐ
  • import <input-path>: ์บ์‹œ JSON ๊ฐ€์ ธ์˜ค๊ธฐ
  • warmup [--recipient <recipient>] [--trace-ax] [--keep-window]: ๊ฒฝ๋กœ ์บ์‹œ ์›Œ๋ฐ์—…

๊ถŒํ•œ ๋ฌธ์ œ ํ•ด๊ฒฐ

kmsg๋Š” ์†์‰ฌ์šด ์‚ฌ์šฉ(Accessibility) ๊ถŒํ•œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์•ฑ์ด ์ž๋™ ์š”์ฒญ์— ์‹คํŒจํ•˜๋ฉด:

  1. ์‹œ์Šคํ…œ ์„ค์ • ์—ด๊ธฐ
  2. ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ ๋ฐ ๋ณด์•ˆ > ์†์‰ฌ์šด ์‚ฌ์šฉ
  3. kmsg ํ† ๊ธ€ ์ผœ๊ธฐ

JSON ์ถœ๋ ฅ

read ๋ช…๋ น์€ --json ํ”Œ๋ž˜๊ทธ๋กœ ๊ตฌ์กฐํ™”๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

kmsg read "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" --limit 20 --json

์ถœ๋ ฅ ํ˜•์‹

{
  "chat": "ํ™๊ธธ๋™",
  "fetched_at": "2026-02-26T01:23:45.678Z",
  "count": 20,
  "messages": [
    {
      "author": "ํ™๊ธธ๋™",
      "time_raw": "00:27",
      "body": "๋ฐค์ด ๊นŠ์—ˆ๋„ค"
    }
  ]
}

ํ•„๋“œ ์„ค๋ช…

  • chat: ์‹ค์ œ๋กœ ์ฝ์€ ์ฑ„ํŒ…๋ฐฉ ์ œ๋ชฉ
  • fetched_at: ๋ฉ”์‹œ์ง€ ์ˆ˜์ง‘ ์‹œ๊ฐ(ISO-8601 UTC)
  • count: ๋ฐ˜ํ™˜๋œ ๋ฉ”์‹œ์ง€ ๊ฐœ์ˆ˜
  • messages[].author: ์ž‘์„ฑ์ž ์ด๋ฆ„ ((me)๋Š” ๋‚ด ๋ฉ”์‹œ์ง€ ๋˜๋Š” ์ž‘์„ฑ์ž ์ถ”๋ก ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ)
  • messages[].time_raw: UI์—์„œ ์ฝํžŒ ์‹œ๊ฐ ๋ฌธ์ž์—ด(์—†์œผ๋ฉด null)
  • messages[].body: ๋ฉ”์‹œ์ง€ ๋ณธ๋ฌธ

์ฃผ์˜

  • --json ์‚ฌ์šฉ ์‹œ JSON์€ stdout์œผ๋กœ๋งŒ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.
  • --trace-ax ๋กœ๊ทธ๋Š” stderr๋กœ ๋ถ„๋ฆฌ๋˜๋ฏ€๋กœ OpenClaw ๊ฐ™์€ ํŒŒ์ดํ”„ ์—ฐ๋™์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

MCP ์—ฐ๋™

kmsg ๋Š” MCP ๋กœ ๋ถ™์—ฌ์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ์„ , ์•„๋ž˜์™€ ๊ฐ™์ด MCP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

python tools/kmsg-mcp.py

OpenClaw ์„ค์ • ์˜ˆ์‹œ

MCP ์„œ๋ฒ„๋ฅผ ๋„์› ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด JSON ์„ค์ •๊ฐ’์„ ์ฃผ๋ฉด์„œ MCP ์—ฐ๋™์„ ํ•ด๋‹ฌ๋ผ๊ณ  ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ •๋ง ๊ฐ„๋‹จํ•˜์ฃ ? ๊ทธ๋ž˜๋„ args ์˜ path ๋Š” ์ˆ˜์ •ํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

{
  "mcpServers": {
    "kmsg": {
      "command": "python3",
      "args": ["/path/to/kmsg/tools/kmsg-mcp.py"],
      "env": {
        "KMSG_BIN": "$HOME/.local/bin/kmsg",
        "KMSG_DEFAULT_DEEP_RECOVERY": "false",
        "KMSG_TRACE_DEFAULT": "false"
      }
    }
  }
}

์ œ๊ณต๋˜๋Š” ๋„๊ตฌ

  • kmsg_read: chat, limit, deep_recovery, keep_window, trace_ax
  • kmsg_send: chat, message, confirm, deep_recovery, keep_window, trace_ax
  • kmsg_send_image: chat, image_path, confirm, deep_recovery, keep_window, trace_ax

kmsg_send, kmsg_send_image๋Š” ๊ธฐ๋ณธ๊ฐ’(confirm=false, ๋˜๋Š” confirm ์ƒ๋žต)์—์„œ ์‹ค์ œ ์ „์†ก์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. confirm=true๋กœ ํ˜ธ์ถœํ•˜๋ฉด ์ „์†กํ•˜์ง€ ์•Š๊ณ  CONFIRMATION_REQUIRED๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

MCP ๋น ๋ฅธ ์‚ฌ์šฉ

MCP ์„œ๋ฒ„ ์—ฐ๊ฒฐ ํ›„, ์•„๋ž˜ ์ˆœ์„œ๋กœ ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

  1. ์ตœ๊ทผ ๋ฉ”์‹œ์ง€ ์ฝ๊ธฐ
{
  "name": "kmsg_read",
  "arguments": {
    "chat": "ํ™๊ธธ๋™",
    "limit": 20
  }
}
  1. ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ (๊ธฐ๋ณธ๊ฐ’: ์ฆ‰์‹œ ์ „์†ก)
{
  "name": "kmsg_send",
  "arguments": {
    "chat": "ํ™๊ธธ๋™",
    "message": "๋ฐ”๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค."
  }
}
  1. ์ด๋ฏธ์ง€ ๋ณด๋‚ด๊ธฐ (๊ธฐ๋ณธ๊ฐ’: ์ฆ‰์‹œ ์ „์†ก)
{
  "name": "kmsg_send_image",
  "arguments": {
    "chat": "ํ™๊ธธ๋™",
    "image_path": "/path/to/image.png"
  }
}
  1. ์ „์†ก ์ „ ํ™•์ธ ๋‹จ๊ณ„ ๊ฐ•์ œ (confirm=true)
{
  "name": "kmsg_send",
  "arguments": {
    "chat": "ํ™๊ธธ๋™",
    "message": "์‚ฌ์šฉ์ž ์Šน์ธ ํ›„ ๋‹ค์‹œ ์ „์†ก",
    "confirm": true
  }
}

openclaw ์™€์˜ ์ž์„ธํ•œ ์—ฐ๋™/์šด์˜ ๊ฐ€์ด๋“œ๋Š” docs/openclaw.md ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. ์„ค์ • ํ…œํ”Œ๋ฆฟ์€ docs/openclaw.mcp.example.json ์—๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋กœ์ปฌ ๋นŒ๋“œ ๋ฐ ๊ฐœ๋ฐœ

git clone https://github.com/channprj/kmsg.git
cd kmsg
swift build -c release
install -m 755 .build/release/kmsg ~/.local/bin/kmsg

๊ณ ๊ธ‰ ์˜ต์…˜

kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "ํ…Œ์ŠคํŠธ" --trace-ax
kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "ํ…Œ์ŠคํŠธ" --dry-run --trace-ax
kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "ํ…Œ์ŠคํŠธ" --no-cache
kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "ํ…Œ์ŠคํŠธ" --refresh-cache
kmsg send-image "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "/path/to/image.png" --trace-ax
KMSG_AX_TIMEOUT=0.25 kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "ํ…Œ์ŠคํŠธ"
kmsg inspect --window 0 --depth 20 --debug-layout
kmsg inspect --window 0 --depth 20 --row-summary
kmsg inspect --window 0 --depth 20 --row-summary --row-range 10:35
kmsg cache status
kmsg cache warmup --recipient "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" --trace-ax
kmsg cache warmup --recipient "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" --keep-window
kmsg cache export ./ax-cache.json
kmsg cache import ./ax-cache.json
kmsg read "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" --deep-recovery --trace-ax
kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "ํ…Œ์ŠคํŠธ" --deep-recovery --trace-ax
kmsg send-image "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "/path/to/image.png" --deep-recovery --trace-ax --keep-window

--deep-recovery๋Š” ๋น ๋ฅธ ์ฐฝ ํƒ์ƒ‰์ด ์‹คํŒจํ•  ๋•Œ๋งŒ relaunch/open ๋ณต๊ตฌ๋ฅผ ์ถ”๊ฐ€๋กœ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ž๋™์œผ๋กœ ์—ฐ ์นด์นด์˜คํ†ก ์ฐฝ์€ ๋ช…๋ น ์ข…๋ฃŒ ์‹œ ๋‹ซํžˆ๋ฉฐ, --keep-window(๋˜๋Š” -k)๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋””๋ฒ„๊น… ๊ฐ€์ด๋“œ (inspect / trace-ax)

๋ฉ”์‹œ์ง€ ์ฝ๊ธฐ/๋ณด๋‚ด๊ธฐ๊ฐ€ ๊ธฐ๋Œ€์™€ ๋‹ค๋ฅด๋ฉด ์•„๋ž˜ ์ˆœ์„œ๋กœ ์ƒํƒœ๋ฅผ ์ˆ˜์ง‘ํ•ด ์ฃผ์„ธ์š”.

# 1) ๋Œ€์ƒ ์ฑ„ํŒ…์ฐฝ ๊ตฌ์กฐ ํ™•์ธ
kmsg inspect --window 0 --depth 20 --debug-layout

# 1-1) ๋ฉ”์‹œ์ง€ row ํŒŒ์‹ฑ ์ง„๋‹จ
kmsg inspect --window 0 --depth 20 --row-summary
kmsg inspect --window 0 --depth 20 --row-summary --row-range 10:30

# 2) ์ฝ๊ธฐ ๊ฒฝ๋กœ/AX ๋กœ๊ทธ ํ™•์ธ
kmsg read "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" --limit 20 --trace-ax

# 3) ๋ณด๋‚ด๊ธฐ ๊ฒฝ๋กœ/AX ๋กœ๊ทธ ํ™•์ธ
kmsg send "๋ณธ์ธ, ์นœ๊ตฌ, ๋˜๋Š” ๋‹จํ†ก๋ฐฉ ์ด๋ฆ„" "ํ…Œ์ŠคํŠธ" --trace-ax --dry-run
  • AXTextArea, value: "..." ๋Š” ์‹ค์ œ ๋ฉ”์‹œ์ง€ ๋ณธ๋ฌธ ํ›„๋ณด์ž…๋‹ˆ๋‹ค.
  • AXStaticText, value: "5\n00:27" ๊ฐ™์€ ๊ฐ’์€ ๋ณดํ†ต ์นด์šดํŠธ/์‹œ๊ฐ„ ๋ฉ”ํƒ€ ์ •๋ณด์ž…๋‹ˆ๋‹ค.
  • --debug-layout์„ ์ผœ๋ฉด path/frame/index/flags๊ฐ€ ํ•จ๊ป˜ ์ถœ๋ ฅ๋˜์–ด ์œ„์น˜ ๊ธฐ๋ฐ˜ ๋ถ„์„์ด ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค.
  • --row-summary๋Š” read ํŒŒ์„œ ๊ธฐ์ค€์œผ๋กœ row๋ณ„ authorCandidates, time, buttonTitles๋ฅผ ๋น ๋ฅด๊ฒŒ ์ ๊ฒ€ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์ด์Šˆ ๋ณด๊ณ  ์‹œ inspect ์ถœ๋ ฅ๊ณผ --trace-ax ์ถœ๋ ฅ์„ ํ•จ๊ป˜ ์ฒจ๋ถ€ํ•˜๋ฉด ์›์ธ ํŒŒ์•…์ด ๋นจ๋ผ์ง‘๋‹ˆ๋‹ค.

Coding Agent์—๊ฒŒ ์š”์ฒญํ•˜๊ธฐ

๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜๊ฑฐ๋‚˜ ๋ฒ„๊ทธ ์ˆ˜์ •์„ ์›ํ•  ๋•Œ Coding Agent์—๊ฒŒ ์•„๋ž˜ ์ •๋ณด์™€ ํ•จ๊ป˜ ์š”์ฒญํ•˜๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค.

  1. ์‹คํ–‰ํ•œ ๋ช…๋ น์–ด: kmsg read ... --trace-ax, kmsg inspect ...
  2. ๊ธฐ๋Œ€ ๊ฒฐ๊ณผ: ๋ฌด์—‡์ด ๋ณด์—ฌ์•ผ ํ•˜๋Š”์ง€
  3. ์‹ค์ œ ๊ฒฐ๊ณผ: ํ˜„์žฌ ๋ฌด์—‡์ด ์ถœ๋ ฅ๋˜๋Š”์ง€
  4. ๊ด€๋ จ ๋กœ๊ทธ: inspect ๋ณธ๋ฌธ ๊ตฌ๊ฐ„ (AXRow > AXCell > AXTextArea) + trace-ax
kmsg read๊ฐ€ ๋ฉ”์‹œ์ง€ ๋ณธ๋ฌธ ๋Œ€์‹  ์‹œ๊ฐ„/์ˆซ์ž๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
inspect ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ์ค€์œผ๋กœ AXRow > AXCell > AXTextArea.value๋ฅผ ์šฐ์„  ์ถ”์ถœํ•˜๋„๋ก ์ˆ˜์ •ํ•ด ์ฃผ์„ธ์š”.
README ๋””๋ฒ„๊น… ๊ฐ€์ด๋“œ๋„ ํ•จ๊ป˜ ์—…๋ฐ์ดํŠธํ•ด ์ฃผ์„ธ์š”.

Deploy

v* ํƒœ๊ทธ๋ฅผ ํ‘ธ์‹œํ•˜๋ฉด GitHub Actions๊ฐ€ ์ž๋™์œผ๋กœ ๋นŒ๋“œํ•ด์„œ kmsg-macos-universal ํŒŒ์ผ์„ Releases์— ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ TAP_REPO_TOKEN์ด ์„ค์ •๋˜์–ด ์žˆ์œผ๋ฉด channprj/homebrew-tap์˜ Formula/kmsg.rb๋ฅผ ์ž๋™์œผ๋กœ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.

๋ฐฐํฌ ์ „์— VERSION ํŒŒ์ผ ๊ฐ’์„ ๋จผ์ € ์—…๋ฐ์ดํŠธํ•˜์„ธ์š”.

# gh ํ† ํฐ์ด ๋งŒ๋ฃŒ๋์œผ๋ฉด ์žฌ๋กœ๊ทธ์ธ
gh auth login -h github.com

# ๋ฐฐํฌ ํƒœ๊ทธ ์ƒ์„ฑ/ํ‘ธ์‹œ
git tag v0.2.3
git push origin v0.2.3

ํ•„์š”ํ•˜๋ฉด Actions๋ฅผ ์ˆ˜๋™ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. workflow_dispatch์—์„œ tag๋ฅผ ๋น„์›Œ๋‘๋ฉด VERSION ํŒŒ์ผ์„ ์ฝ์–ด v<version>์œผ๋กœ ์ž๋™ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. tag๋ฅผ ์ง์ ‘ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ vX.Y.Z ํ˜•์‹๋งŒ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค.

# ํƒœ๊ทธ๋ฅผ ์ง์ ‘ ์ง€์ •ํ•ด์„œ ์‹คํ–‰
gh workflow run release.yml -f tag=v0.2.4

# tag ๋ฏธ์ง€์ • ์‹œ VERSION(์˜ˆ: 0.2.4) ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰
gh workflow run release.yml

Homebrew ์ž๋™ ๋™๊ธฐํ™” ์„ค์ • (์ตœ์ดˆ 1ํšŒ)

  1. channprj/homebrew-tap ์ €์žฅ์†Œ๋ฅผ ๋งŒ๋“ค๊ณ  Formula/ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.
  2. kmsg ์ €์žฅ์†Œ Secrets์— TAP_REPO_TOKEN์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ถŒํ•œ: homebrew-tap ์ €์žฅ์†Œ contents: write
  3. tap ์ €์žฅ์†Œ ๊ธฐ๋ณธ ๋ธŒ๋žœ์น˜๊ฐ€ main์ด ์•„๋‹ˆ๋ฉด .github/workflows/release.yml์˜ TAP_REPO_REF ๊ฐ’์„ ๋งž์ถฐ ์ฃผ์„ธ์š”.

๋ฆด๋ฆฌ์ฆˆ ํ›„ ์‚ฌ์šฉ์ž๋Š” ์•„๋ž˜ ๋ช…๋ น์œผ๋กœ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

brew install channprj/tap/kmsg

๊ธฐํƒ€

  • Homebrew ์„ค์น˜: brew install channprj/tap/kmsg
  • ์ง์ ‘ ์„ค์น˜๋Š” kmsg-macos-universal ์•„ํ‹ฐํŒฉํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋‹ค์šด๋กœ๋“œ ์‹คํŒจ ์‹œ https://github.com/channprj/kmsg/releases ์—์„œ ์ง์ ‘ ๋‚ด๋ ค๋ฐ›์•„ ~/.local/bin/kmsg๋กœ ์ €์žฅ ํ›„ chmod +x ~/.local/bin/kmsg ๋ฅผ ์ง„ํ–‰ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Inspiration

This project is strongly inspired by steipete and his works.

References

About

CLI for KakaoTalk.app so your agent can send and receive k-messages.

Topics

Resources

License

Stars

Watchers

Forks

Contributors