Power Tools νŒŒμ›Œ 툴즈

Six focused features that extend the pi agent's capabilities β€” URL fetching, editor state management, artifact persistence, structured commit metadata, branded startup, and real-time plan tracking. pi μ—μ΄μ „νŠΈμ˜ κΈ°λŠ₯을 ν™•μž₯ν•˜λŠ” 6개의 집쀑 κΈ°λŠ₯ β€” URL κ°€μ Έμ˜€κΈ°, 에디터 μƒνƒœ 관리, μ•„ν‹°νŒ©νŠΈ 지속성, κ΅¬μ‘°ν™”λœ 컀밋 메타데이터, λΈŒλžœλ””λ“œ μ‹œμž‘ ν™”λ©΄, μ‹€μ‹œκ°„ κ³„νš 좔적.

● WebFetch

URL β†’ Markdown conversion tool for agents. Fetches any URL, converts HTML to clean Markdown using Mozilla Readability + Turndown, and caches results for fast repeated access. μ—μ΄μ „νŠΈλ₯Ό μœ„ν•œ URL β†’ Markdown λ³€ν™˜ 도ꡬ. λͺ¨λ“  URL을 가져와 Mozilla Readability + Turndown으둜 HTML을 κΉ”λ”ν•œ Markdown으둜 λ³€ν™˜ν•˜κ³ , λΉ λ₯Έ 반볡 접근을 μœ„ν•΄ κ²°κ³Όλ₯Ό μΊμ‹œν•©λ‹ˆλ‹€.

Tool Parameters 도ꡬ νŒŒλΌλ―Έν„°

ParameterνŒŒλΌλ―Έν„° Typeνƒ€μž… Requiredν•„μˆ˜ DefaultκΈ°λ³Έκ°’
url string Yes예 β€”
raw boolean Noμ•„λ‹ˆμ˜€ false
includeScripts boolean Noμ•„λ‹ˆμ˜€ false
maxLength number Noμ•„λ‹ˆμ˜€ β€”

Cache μΊμ‹œ

In-memory LRU cache. 100 entries max, 15-minute TTL. Cache key is derived from JSON.stringify({url, mode, scripts}) where mode is "full" (default) or "full" when raw is true. 인메λͺ¨λ¦¬ LRU μΊμ‹œ. μ΅œλŒ€ 100개 ν•­λͺ©, 15λΆ„ TTL. μΊμ‹œ ν‚€λŠ” JSON.stringify({url, mode, scripts})μ—μ„œ νŒŒμƒλ©λ‹ˆλ‹€. μ—¬κΈ°μ„œ modeλŠ” κΈ°λ³Έκ°’ "auto" λ˜λŠ” rawκ°€ true일 λ•Œ "full"μž…λ‹ˆλ‹€.

Limits μ œν•œ

  • MAX_CONTENT_SIZE = 10 MB β€” checked via content-length header and actual byte count content-length 헀더와 μ‹€μ œ λ°”μ΄νŠΈ 수둜 확인
  • FETCH_TIMEOUT_MS = 30 s β€” hard abort via AbortController AbortControllerλ₯Ό ν†΅ν•œ κ°•μ œ 쀑단

User Agent μ‚¬μš©μž μ—μ΄μ „νŠΈ

Mozilla/5.0 (compatible; WebFetchTool/1.0)

Extraction Modes μΆ”μΆœ λͺ¨λ“œ

Modeλͺ¨λ“œ Trigger트리거 Behaviorλ™μž‘
full raw: false (default) Readable content β€” Mozilla Readability + Turndown + GFM읽을 수 μžˆλŠ” μ½˜ν…μΈ  β€” Mozilla Readability + Turndown + GFM
raw raw: true Full HTML converted to Markdown via Turndown (no Readability filter)전체 HTML을 Turndown으둜 Markdown λ³€ν™˜ (Readability ν•„ν„° μ—†μŒ)

Truncation 자λ₯΄κΈ°

When maxLength is set and content exceeds it, the returned copy is sliced and suffixed with: maxLengthκ°€ μ„€μ •λ˜κ³  μ½˜ν…μΈ κ°€ μ΄ˆκ³Όν•˜λ©΄ λ°˜ν™˜λœ 사본은 잘리고 λ‹€μŒ 접미사가 λΆ™μŠ΅λ‹ˆλ‹€:

... (truncated)

The original content stored in cache is not truncated. μΊμ‹œμ— μ €μž₯된 원본 μ½˜ν…μΈ λŠ” 자λ₯΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

β–  Editor Stash

Session-scoped single-slot stash for editor text. Save a snippet, clear the editor, restore it later β€” all without leaving the editor. 에디터 ν…μŠ€νŠΈλ₯Ό μœ„ν•œ μ„Έμ…˜ λ²”μœ„μ˜ 단일 슬둯 μŠ€νƒœμ‹œ. μŠ€λ‹ˆνŽ«μ„ μ €μž₯ν•˜κ³ , 에디터λ₯Ό μ§€μš°κ³ , λ‚˜μ€‘μ— 볡원 β€” 에디터λ₯Ό λ– λ‚˜μ§€ μ•Šκ³  λͺ¨λ‘ κ°€λŠ₯ν•©λ‹ˆλ‹€.

Slash Commands μŠ¬λž˜μ‹œ λͺ…λ Ή

Commandλͺ…λ Ή Actionλ™μž‘
/stash-save Copy current editor text into the stash slotν˜„μž¬ 에디터 ν…μŠ€νŠΈλ₯Ό μŠ€νƒœμ‹œ μŠ¬λ‘―μ— 볡사
/stash-clear Clear the stash slot contentsμŠ€νƒœμ‹œ 슬둯 λ‚΄μš© μ§€μš°κΈ°
/stash-restore Replace editor text with stashed content에디터 ν…μŠ€νŠΈλ₯Ό μŠ€νƒœμ‹œλœ λ‚΄μš©μœΌλ‘œ ꡐ체

Keyboard Shortcuts ν‚€λ³΄λ“œ 단좕킀

Shortcut단좕킀 Byteλ°”μ΄νŠΈ Actionλ™μž‘
Ctrl+S \x13 Save to stashμŠ€νƒœμ‹œμ— μ €μž₯
Ctrl+R \x12 Restore from stashμŠ€νƒœμ‹œμ—μ„œ 볡원
Ctrl+K \x0b Clear stashμŠ€νƒœμ‹œ μ§€μš°κΈ°

Status Indicator μƒνƒœ ν‘œμ‹œκΈ°

An editor decorator appends a status line at the bottom of the editor showing stash size and shortcut hints. 에디터 λ°μ½”λ ˆμ΄ν„°κ°€ 에디터 ν•˜λ‹¨μ— μŠ€νƒœμ‹œ 크기와 단좕킀 힌트λ₯Ό λ³΄μ—¬μ£ΌλŠ” μƒνƒœ 쀄을 μΆ”κ°€ν•©λ‹ˆλ‹€.

β˜… Artifacts

Structured per-run artifact directories for subagent outputs. Each subagent invocation gets an isolated directory tree for its output, progress, and declared read files. μ„œλΈŒμ—μ΄μ „νŠΈ 좜λ ₯을 μœ„ν•œ κ΅¬μ‘°ν™”λœ 싀행별 μ•„ν‹°νŒ©νŠΈ 디렉토리. 각 μ„œλΈŒμ—μ΄μ „νŠΈ ν˜ΈμΆœμ€ 좜λ ₯, μ§„ν–‰, μ„ μ–Έλœ 읽기 νŒŒμΌμ„ μœ„ν•œ 격리된 디렉토리 트리λ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€.

Directory Layout 디렉토리 λ ˆμ΄μ•„μ›ƒ

<base>/<rootRunId>/subagents/<agentName>-<runId>/

Base Directory κΈ°λ³Έ 디렉토리

PI_SUBAGENT_ARTIFACT_ROOT || cwd/.pi/agent/runs

run.json Schema run.json μŠ€ν‚€λ§ˆ

Field Typeνƒ€μž… Descriptionμ„€λͺ…
agentNamestringSubagent identifierμ„œλΈŒμ—μ΄μ „νŠΈ μ‹λ³„μž
runIdstringUnique run identifier고유 μ‹€ν–‰ μ‹λ³„μž
rootRunIdstringParent session run identifierλΆ€λͺ¨ μ„Έμ…˜ μ‹€ν–‰ μ‹λ³„μž
cwdstringWorking directory at creation time생성 μ‹œμ μ˜ μž‘μ—… 디렉토리
outputFilestring?Resolved output pathν•΄κ²°λœ 좜λ ₯ 경둜
progressFilestring?Resolved progress pathν•΄κ²°λœ μ§„ν–‰ 경둜
readFilesstring[]Declared read file pathsμ„ μ–Έλœ 읽기 파일 경둜
createdAtstringISO 8601 timestampISO 8601 νƒ€μž„μŠ€νƒ¬ν”„

Path Guards 경둜 κ°€λ“œ

All user-supplied paths are validated before resolution: λͺ¨λ“  μ‚¬μš©μž 제곡 κ²½λ‘œλŠ” ν•΄κ²° 전에 κ²€μ¦λ©λ‹ˆλ‹€:

  • Rejects absolute paths (/etc/passwd) μ ˆλŒ€ 경둜 κ±°λΆ€ (/etc/passwd)
  • Rejects home shortcuts (~, ~/...) ν™ˆ 단좕킀 κ±°λΆ€ (~, ~/...)
  • Rejects paths that escape the run directory (../../etc) 런 디렉토리λ₯Ό λ²—μ–΄λ‚˜λŠ” 경둜 κ±°λΆ€ (../../etc)
  • Rejects paths that escape the workspace (for declared reads) μ›Œν¬μŠ€νŽ˜μ΄μŠ€λ₯Ό λ²—μ–΄λ‚˜λŠ” 경둜 κ±°λΆ€ (μ„ μ–Έλœ 읽기용)

Segment Sanitization μ„Έκ·Έλ¨ΌνŠΈ μ •ν™”

sanitizeSegment() replaces non-alphanumeric characters (except ., _, -) with -, then strips leading and trailing dashes. Falls back to "run" if the result is empty. sanitizeSegment()은 μ˜μˆ«μžκ°€ μ•„λ‹Œ 문자(., _, - μ œμ™Έ)λ₯Ό -둜 κ΅μ²΄ν•˜κ³ , μ„ ν–‰ 및 ν›„ν–‰ λŒ€μ‹œλ₯Ό μ œκ±°ν•©λ‹ˆλ‹€. κ²°κ³Όκ°€ λΉ„μ–΄μžˆμœΌλ©΄ "run"을 μ‚¬μš©ν•©λ‹ˆλ‹€.

β—† Lore Commits

Structured git trailers that embed decision context directly into commit messages. Future agents and developers can query project knowledge via git log. 컀밋 λ©”μ‹œμ§€μ— κ²°μ • μ»¨ν…μŠ€νŠΈλ₯Ό 직접 μ‚½μž…ν•˜λŠ” κ΅¬μ‘°ν™”λœ git 트레일러. 미래의 μ—μ΄μ „νŠΈμ™€ κ°œλ°œμžκ°€ git logλ₯Ό 톡해 ν”„λ‘œμ νŠΈ 지식을 μ‘°νšŒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Trailer Vocabulary 트레일러 μ–΄νœ˜

Trailer트레일러 Formatν˜•μ‹ Exampleμ˜ˆμ‹œ
Constraint: Free text자유 ν…μŠ€νŠΈ Constraint: must support Node 18+
Rejected: <alt> | <reason> Rejected: SQLite | adds native dependency
Confidence: high / medium / lowhigh / medium / low Confidence: high
Scope-risk: narrow / moderate / broadnarrow / moderate / broad Scope-risk: narrow
Reversibility: clean / moderate / difficultclean / moderate / difficult Reversibility: clean
Directive: Free text자유 ν…μŠ€νŠΈ Directive: keep backwards compat
Tested: Free text자유 ν…μŠ€νŠΈ Tested: manual verification on macOS
Not-tested: Free text자유 ν…μŠ€νŠΈ Not-tested: Windows path handling
Related: Free text자유 ν…μŠ€νŠΈ Related: #42

Querying Lore Lore 쑰회

Filter commits by any trailer key: λͺ¨λ“  트레일러 ν‚€λ‘œ 컀밋 필터링:

git log --trailer=Constraint: -- path

Setup μ„€μ •

The lore-setup skill writes Lore commit format rules to AGENTS.md or CLAUDE.md so all agents automatically use structured git trailers in commit messages. lore-setup μŠ€ν‚¬μ΄ AGENTS.md λ˜λŠ” CLAUDE.md에 Lore 컀밋 ν˜•μ‹ κ·œμΉ™μ„ μž‘μ„±ν•˜μ—¬ λͺ¨λ“  μ—μ΄μ „νŠΈκ°€ 컀밋 λ©”μ‹œμ§€μ— μžλ™μœΌλ‘œ κ΅¬μ‘°ν™”λœ git 트레일러λ₯Ό μ‚¬μš©ν•˜λ„λ‘ ν•©λ‹ˆλ‹€.

β–Ά Welcome Banner

ROACH PI branded header that replaces the generic pi startup listing. Shows the ASCII art logo and quick-start hints when the session begins. 일반적인 pi μ‹œμž‘ λͺ©λ‘μ„ λŒ€μ²΄ν•˜λŠ” ROACH PI λΈŒλžœλ””λ“œ 헀더. μ„Έμ…˜ μ‹œμž‘ μ‹œ ASCII μ•„νŠΈ λ‘œκ³ μ™€ λΉ λ₯Έ μ‹œμž‘ 힌트λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€.

/welcome Command /welcome λͺ…λ Ή

Inputμž…λ ₯ Effect효과
off, hide, dismiss Hide the bannerλ°°λ„ˆ 숨기기
on, show, restore Show the bannerλ°°λ„ˆ ν‘œμ‹œ
(bare) /welcome Toggle visibilityκ°€μ‹œμ„± ν† κΈ€

Interaction with /setup /setup과의 μƒν˜Έμž‘μš©

/setup sets quietStartup: true so the pi agent's generic startup listing is suppressed, making the ROACH PI banner the main startup surface. /setup이 quietStartup: trueλ₯Ό μ„€μ •ν•˜μ—¬ pi μ—μ΄μ „νŠΈμ˜ 일반적인 μ‹œμž‘ λͺ©λ‘μ΄ μ–΅μ œλ˜κ³ , ROACH PI λ°°λ„ˆκ°€ μ£Ό μ‹œμž‘ 화면이 λ©λ‹ˆλ‹€.

Interaction with /init /init과의 μƒν˜Έμž‘μš©

/init also configures banner visibility as part of the initial project setup flow. /init도 초기 ν”„λ‘œμ νŠΈ μ„€μ • νλ¦„μ˜ μΌλΆ€λ‘œ λ°°λ„ˆ κ°€μ‹œμ„±μ„ κ΅¬μ„±ν•©λ‹ˆλ‹€.

◐ Plan Progress & Milestone TUI

Real-time plan and milestone progress displayed in the TUI footer. Shows task completion, running state, and milestone lifecycle at a glance. TUI 푸터에 ν‘œμ‹œλ˜λŠ” μ‹€μ‹œκ°„ κ³„νš 및 λ§ˆμΌμŠ€ν†€ μ§„ν–‰ 상황. μž‘μ—… μ™„λ£Œ, μ‹€ν–‰ μƒνƒœ, λ§ˆμΌμŠ€ν†€ 수λͺ… μ£ΌκΈ°λ₯Ό ν•œλˆˆμ— λ³΄μ—¬μ€λ‹ˆλ‹€.

Task Statuses μž‘μ—… μƒνƒœ

Statusμƒνƒœ Meaning의미
pendingNot yet started아직 μ‹œμž‘ μ•ˆ 됨
runningCurrently executingν˜„μž¬ μ‹€ν–‰ 쀑
completedFinished successfullyμ„±κ³΅μ μœΌλ‘œ μ™„λ£Œ
failedFinished with error였λ₯˜λ‘œ μ™„λ£Œ

Milestone Statuses λ§ˆμΌμŠ€ν†€ μƒνƒœ

Statusμƒνƒœ Meaning의미
pendingWaiting to startμ‹œμž‘ λŒ€κΈ° 쀑
planningPlan being draftedκ³„νš μž‘μ„± 쀑
executingTasks runningμž‘μ—… μ‹€ν–‰ 쀑
validatingReview underway리뷰 μ§„ν–‰ 쀑
completedAll tasks passedλͺ¨λ“  μž‘μ—… 톡과
failedValidation failed검증 μ‹€νŒ¨
skippedExplicitly skippedλͺ…μ‹œμ μœΌλ‘œ κ±΄λ„ˆλœ€

Spinner μŠ€ν”Όλ„ˆ

A 400ms interval spinner (PLAN_PROGRESS_SPINNER_MS) runs only while tasks are in the running state. Frames cycle through ◐ β—“ β—‘ β—’. μž‘μ—…μ΄ running μƒνƒœμΈ λ™μ•ˆλ§Œ 400ms 간격 μŠ€ν”Όλ„ˆ(PLAN_PROGRESS_SPINNER_MS)κ°€ μ‹€ν–‰λ©λ‹ˆλ‹€. ν”„λ ˆμž„μ€ ◐ β—“ β—‘ ◒을 μˆœν™˜ν•©λ‹ˆλ‹€.

Milestone File Detection λ§ˆμΌμŠ€ν†€ 파일 감지

File Type파일 μœ ν˜• PatternνŒ¨ν„΄
Milestone fileλ§ˆμΌμŠ€ν†€ 파일 /(M\d+)-([^/\s]+)\.md$/i
State tableμƒνƒœ ν…Œμ΄λΈ” /state.md$/
Todoν•  일 /todo.md$/
Completionμ™„λ£Œ /completion.md$/

/reset-phase Command /reset-phase λͺ…λ Ή

Clears all plan and milestone state from the tracker, returning to a clean slate. νŠΈλž˜μ»€μ—μ„œ λͺ¨λ“  κ³„νš 및 λ§ˆμΌμŠ€ν†€ μƒνƒœλ₯Ό μ§€μš°κ³  κΉ¨λ—ν•œ μƒνƒœλ‘œ λŒμ•„κ°‘λ‹ˆλ‹€.

Footer Integration ν‘Έν„° 톡합

The footer subscribes to PlanProgressTracker change notifications via setOnChange(). When progress changes, the footer calls tui.requestRender(true) to update the display. The spinner timer is started on demand and cleaned up in dispose(). ν‘Έν„°λŠ” setOnChange()을 톡해 PlanProgressTracker λ³€κ²½ μ•Œλ¦Όμ„ κ΅¬λ…ν•©λ‹ˆλ‹€. μ§„ν–‰ 상황이 λ³€κ²½λ˜λ©΄ ν‘Έν„°λŠ” tui.requestRender(true)λ₯Ό ν˜ΈμΆœν•˜μ—¬ ν‘œμ‹œλ₯Ό μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€. μŠ€ν”Όλ„ˆ νƒ€μ΄λ¨ΈλŠ” ν•„μš”ν•  λ•Œ μ‹œμž‘λ˜κ³  dispose()μ—μ„œ μ •λ¦¬λ©λ‹ˆλ‹€.