diff --git a/.github/workflows/release-bundle.yml b/.github/workflows/release-bundle.yml
new file mode 100644
index 000000000..03aa8f0ed
--- /dev/null
+++ b/.github/workflows/release-bundle.yml
@@ -0,0 +1,407 @@
+name: Release Bundle
+
+on:
+ workflow_dispatch:
+ inputs:
+ tag:
+ description: "Release tag (e.g. v0.2.0)"
+ required: true
+ type: string
+ prerelease:
+ description: "Mark as pre-release"
+ required: false
+ type: boolean
+ default: false
+ draft:
+ description: "Create as draft"
+ required: false
+ type: boolean
+ default: true
+
+jobs:
+ # ──────────────────────────────────────────────────────────────────────────
+ # 1. Create Git tag
+ # ──────────────────────────────────────────────────────────────────────────
+ create-tag:
+ name: Create Git Tag
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Create and push tag
+ env:
+ RELEASE_TAG: ${{ inputs.tag }}
+ run: |
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+ git tag -a "$RELEASE_TAG" -m "Release $RELEASE_TAG"
+ git push origin "$RELEASE_TAG"
+
+ # ──────────────────────────────────────────────────────────────────────────
+ # 2. Build picoclaw (CGO_ENABLED=0, pure Go, cross-compile on ubuntu)
+ # ──────────────────────────────────────────────────────────────────────────
+ build-picoclaw:
+ name: Build picoclaw (${{ matrix.goos }}/${{ matrix.goarch }})
+ needs: create-tag
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ strategy:
+ matrix:
+ include:
+ - goos: linux
+ goarch: amd64
+ suffix: ""
+ - goos: linux
+ goarch: arm64
+ suffix: ""
+ - goos: linux
+ goarch: arm
+ goarm: "7"
+ suffix: ""
+ - goos: linux
+ goarch: riscv64
+ suffix: ""
+ - goos: linux
+ goarch: loong64
+ suffix: ""
+ - goos: windows
+ goarch: amd64
+ suffix: ".exe"
+ - goos: darwin
+ goarch: amd64
+ suffix: ""
+ - goos: darwin
+ goarch: arm64
+ suffix: ""
+
+ steps:
+ - name: Checkout tag
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: ${{ inputs.tag }}
+
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+
+ - name: Generate embedded assets
+ run: go generate ./...
+
+ - name: Build picoclaw
+ env:
+ GOOS: ${{ matrix.goos }}
+ GOARCH: ${{ matrix.goarch }}
+ GOARM: ${{ matrix.goarm }}
+ CGO_ENABLED: "0"
+ VERSION: ${{ inputs.tag }}
+ run: |
+ mkdir -p dist
+ OUTPUT="dist/picoclaw${{ matrix.suffix }}"
+ go build \
+ -tags stdjson \
+ -ldflags "-s -w \
+ -X github.com/sipeed/picoclaw/cmd/picoclaw/internal.version=${VERSION} \
+ -X github.com/sipeed/picoclaw/cmd/picoclaw/internal.gitCommit=$(git rev-parse --short HEAD) \
+ -X github.com/sipeed/picoclaw/cmd/picoclaw/internal.buildTime=$(date -u +%FT%TZ)" \
+ -o "${OUTPUT}" \
+ ./cmd/picoclaw
+
+ - name: Upload picoclaw artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: picoclaw-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarm && format('-armv{0}', matrix.goarm) || '' }}
+ path: dist/picoclaw${{ matrix.suffix }}
+ retention-days: 1
+
+ # ──────────────────────────────────────────────────────────────────────────
+ # 3a. Build Launcher — Windows (Wails requires WebView2)
+ # Note: continue-on-error=true so packaging still runs if wails build fails
+ # ──────────────────────────────────────────────────────────────────────────
+ build-launcher-windows:
+ name: Build launcher (windows/amd64)
+ needs: create-tag
+ runs-on: windows-latest
+ continue-on-error: true
+ permissions:
+ contents: read
+ steps:
+ - name: Checkout tag
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: ${{ inputs.tag }}
+
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+
+ - name: Build launcher
+ working-directory: cmd/picoclaw-launcher
+ run: |
+ go tool wails build -tags stdjson -ldflags "-s -w" -o picoclaw-launcher.exe
+
+ - name: Upload launcher artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: launcher-windows-amd64
+ path: cmd/picoclaw-launcher/build/bin/picoclaw-launcher.exe
+ retention-days: 1
+
+ # ──────────────────────────────────────────────────────────────────────────
+ # 3b. Build Launcher — Linux/amd64 (Wails requires GTK/WebKit)
+ # ──────────────────────────────────────────────────────────────────────────
+ build-launcher-linux:
+ name: Build launcher (linux/amd64)
+ needs: create-tag
+ runs-on: ubuntu-latest
+ continue-on-error: true
+ permissions:
+ contents: read
+ steps:
+ - name: Checkout tag
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: ${{ inputs.tag }}
+
+ - name: Install WebKit/GTK dependencies
+ run: |
+ sudo apt-get update -qq
+ sudo apt-get install -y --no-install-recommends \
+ libgtk-3-dev \
+ libwebkit2gtk-4.0-dev \
+ pkg-config \
+ build-essential
+
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+
+ - name: Build launcher
+ working-directory: cmd/picoclaw-launcher
+ run: |
+ go tool wails build -tags stdjson -ldflags "-s -w" -o picoclaw-launcher
+
+ - name: Upload launcher artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: launcher-linux-amd64
+ path: cmd/picoclaw-launcher/build/bin/picoclaw-launcher
+ retention-days: 1
+
+ # ──────────────────────────────────────────────────────────────────────────
+ # 3c. Build Launcher — macOS (universal binary: amd64 + arm64)
+ # ──────────────────────────────────────────────────────────────────────────
+ build-launcher-macos:
+ name: Build launcher (darwin/universal)
+ needs: create-tag
+ runs-on: macos-latest
+ continue-on-error: true
+ permissions:
+ contents: read
+ steps:
+ - name: Checkout tag
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: ${{ inputs.tag }}
+
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+
+ - name: Build launcher (universal)
+ working-directory: cmd/picoclaw-launcher
+ run: |
+ go tool wails build -tags stdjson -ldflags "-s -w" -platform darwin/universal -o picoclaw-launcher
+
+ - name: Upload launcher artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: launcher-darwin-universal
+ path: cmd/picoclaw-launcher/build/bin/picoclaw-launcher
+ retention-days: 1
+
+ # ──────────────────────────────────────────────────────────────────────────
+ # 4. Package: assemble zip bundles per platform and create GitHub Release
+ # Runs even if launcher builds fail (if: ${{ !cancelled() }})
+ # Launcher is included only if its artifact was successfully uploaded
+ # ──────────────────────────────────────────────────────────────────────────
+ package-and-release:
+ name: Package & Create Release
+ needs:
+ - build-picoclaw
+ - build-launcher-windows
+ - build-launcher-linux
+ - build-launcher-macos
+ # Run even if launcher jobs fail; only skip if workflow is cancelled
+ if: ${{ !cancelled() && needs.build-picoclaw.result == 'success' }}
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout tag
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: ${{ inputs.tag }}
+
+ # ── Download picoclaw artifacts (always present) ──
+ - name: Download picoclaw artifacts
+ uses: actions/download-artifact@v4
+ with:
+ pattern: picoclaw-*
+ path: artifacts
+ merge-multiple: false
+
+ # ── Download launcher artifacts (may be missing if build failed) ──
+ - name: Download launcher-windows artifact
+ uses: actions/download-artifact@v4
+ if: ${{ needs.build-launcher-windows.result == 'success' }}
+ with:
+ name: launcher-windows-amd64
+ path: artifacts/launcher-windows-amd64
+ continue-on-error: true
+
+ - name: Download launcher-linux artifact
+ uses: actions/download-artifact@v4
+ if: ${{ needs.build-launcher-linux.result == 'success' }}
+ with:
+ name: launcher-linux-amd64
+ path: artifacts/launcher-linux-amd64
+ continue-on-error: true
+
+ - name: Download launcher-macos artifact
+ uses: actions/download-artifact@v4
+ if: ${{ needs.build-launcher-macos.result == 'success' }}
+ with:
+ name: launcher-darwin-universal
+ path: artifacts/launcher-darwin-universal
+ continue-on-error: true
+
+ - name: List downloaded artifacts
+ run: find artifacts -type f | sort
+
+ # ── Assemble zip bundles ──
+ - name: Assemble zip bundles
+ env:
+ TAG: ${{ inputs.tag }}
+ run: |
+ set -euo pipefail
+ mkdir -p release staging
+
+ # ── helper: bundle picoclaw + optional launcher into a zip ──
+ make_zip() {
+ local NAME="$1" # bundle name, e.g. picoclaw_v0.1.0_windows_amd64
+ local PICOCLAW="$2" # source path of picoclaw binary
+ local LAUNCHER="${3:-}" # source path of launcher binary (empty = omit)
+ local EXT="${4:-}" # ".exe" or ""
+
+ local DIR="staging/${NAME}"
+ mkdir -p "${DIR}"
+
+ chmod +x "${PICOCLAW}" 2>/dev/null || true
+ cp "${PICOCLAW}" "${DIR}/picoclaw${EXT}"
+
+ if [ -n "${LAUNCHER}" ] && [ -f "${LAUNCHER}" ]; then
+ chmod +x "${LAUNCHER}" 2>/dev/null || true
+ cp "${LAUNCHER}" "${DIR}/picoclaw-launcher${EXT}"
+ echo "PicoClaw Bundle (picoclaw + picoclaw-launcher)" > "${DIR}/README.txt"
+ else
+ echo "PicoClaw CLI only (picoclaw-launcher not available for this platform)" > "${DIR}/README.txt"
+ fi
+
+ (cd staging && zip -r "../release/${NAME}.zip" "${NAME}/")
+ echo " created: release/${NAME}.zip"
+ }
+
+ WINLAUNCHER=""
+ LINLAUNCHER=""
+ MACLAUNCHER=""
+
+ [ -f "artifacts/launcher-windows-amd64/picoclaw-launcher.exe" ] \
+ && WINLAUNCHER="artifacts/launcher-windows-amd64/picoclaw-launcher.exe"
+ [ -f "artifacts/launcher-linux-amd64/picoclaw-launcher" ] \
+ && LINLAUNCHER="artifacts/launcher-linux-amd64/picoclaw-launcher"
+ [ -f "artifacts/launcher-darwin-universal/picoclaw-launcher" ] \
+ && MACLAUNCHER="artifacts/launcher-darwin-universal/picoclaw-launcher"
+
+ # Windows amd64
+ make_zip \
+ "picoclaw_${TAG}_windows_amd64" \
+ "artifacts/picoclaw-windows-amd64/picoclaw.exe" \
+ "${WINLAUNCHER}" \
+ ".exe"
+
+ # Linux amd64
+ make_zip \
+ "picoclaw_${TAG}_linux_amd64" \
+ "artifacts/picoclaw-linux-amd64/picoclaw" \
+ "${LINLAUNCHER}" \
+ ""
+
+ # macOS amd64 (with universal launcher if available)
+ make_zip \
+ "picoclaw_${TAG}_darwin_amd64" \
+ "artifacts/picoclaw-darwin-amd64/picoclaw" \
+ "${MACLAUNCHER}" \
+ ""
+
+ # macOS arm64 (with universal launcher if available)
+ make_zip \
+ "picoclaw_${TAG}_darwin_arm64" \
+ "artifacts/picoclaw-darwin-arm64/picoclaw" \
+ "${MACLAUNCHER}" \
+ ""
+
+ # Linux arm64 (picoclaw only)
+ make_zip \
+ "picoclaw_${TAG}_linux_arm64" \
+ "artifacts/picoclaw-linux-arm64/picoclaw" \
+ "" ""
+
+ # Linux armv7 (picoclaw only)
+ make_zip \
+ "picoclaw_${TAG}_linux_armv7" \
+ "artifacts/picoclaw-linux-arm-armv7/picoclaw" \
+ "" ""
+
+ # Linux riscv64 (picoclaw only)
+ make_zip \
+ "picoclaw_${TAG}_linux_riscv64" \
+ "artifacts/picoclaw-linux-riscv64/picoclaw" \
+ "" ""
+
+ # Linux loong64 (picoclaw only)
+ make_zip \
+ "picoclaw_${TAG}_linux_loong64" \
+ "artifacts/picoclaw-linux-loong64/picoclaw" \
+ "" ""
+
+ echo ""
+ echo "=== Final release assets ==="
+ ls -lh release/
+
+ # ── Create GitHub Release ──
+ - name: Create GitHub Release
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: ${{ inputs.tag }}
+ name: "PicoClaw ${{ inputs.tag }}"
+ draft: ${{ inputs.draft }}
+ prerelease: ${{ inputs.prerelease }}
+ generate_release_notes: true
+ files: release/*.zip
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/README.md b/README.md
index 6714ac6eb..88d2355ad 100644
--- a/README.md
+++ b/README.md
@@ -82,6 +82,87 @@
+## 🧠 Our Thinking
+
+PicoClaw isn't just small — it **thinks differently**. While most AI agent frameworks treat the LLM as a black box that swallows everything (all tools, all history, all context), PicoClaw introduces a structured **Runtime Loop** that makes every token count.
+
+### Three-Phase Runtime Loop
+
+Every user interaction flows through three distinct phases:
+
+```
+┌──────────────┐ ┌──────────────┐ ┌──────────────┐
+│ Phase 1 │ → │ Phase 2 │ → │ Phase 3 │
+│ Analyse │ │ ExecuteLLM │ │ Reflect │
+│ (Orchestrate) │ (Execute) │ │ (Learn) │
+└──────────────┘ └──────────────┘ └──────────────┘
+```
+
+- **Phase 1 — Analyse**: A lightweight LLM call (can use a cheaper/faster model) that understands intent, assigns semantic tags, and prepares the optimal context. No tools, no history bloat — just pure comprehension.
+- **Phase 2 — ExecuteLLM**: The main LLM iterates with only the tools and context that Phase 1 deemed relevant. Fewer tools = less confusion = better decisions.
+- **Phase 3 — Reflect**: Synchronous scoring + context update (< 2ms) before the user sees the reply, followed by async persistence. The agent learns from every interaction without adding latency.
+
+### Turn Scoring & Instant Memory
+
+Every Turn gets a **score** based on tool activity, intent weight, content density, and explicit user markers. This score drives a novel context selection algorithm:
+
+```
+Instant Memory = { high-score Turns } // always kept, unconditionally
+ ∪ { tag-matched Turns, score > 0 } // relevant old Turns "resurrected"
+ ∪ { recent M Turns } // continuity baseline
+ → sorted by time, truncated to capacity
+```
+
+**No Turn is ever deleted.** Low-score Turns are simply excluded from context — but when a future Phase 1 produces matching tags, they can be recalled. It's like human memory: you don't forget things, you just can't always access them until something triggers the recall.
+
+### Tag-Gated Tool Loading
+
+Instead of feeding 20+ tool definitions to the LLM every request (wasting ~3,000 tokens per iteration), PicoClaw categorizes tools:
+
+| Layer | Tools | Loading |
+|-------|-------|---------|
+| **always-on** | `read_file`, `write_file`, `shell`, etc. | Always present |
+| **tag-gated** | MCP servers, Skills, `web_search`, `cron` | Only when Phase 1 tags match |
+
+As MCP servers and Skills grow, the savings compound exponentially — and the LLM makes better decisions with a focused toolset.
+
+### KV Cache-Friendly Message Ordering
+
+We obsess over **prefix stability** to maximize KV cache hits across providers (Gemini implicit cache, Anthropic `cache_control`, OpenAI prompt caching):
+
+```
+[system_prompt] ← always cached ✅
+[long_term_memory by tags] ← stable when same tags ✅
+[high-score Turns, ASC by ID] ← fixed positions, append-only ✅
+[tag-matched Turns] ← may vary
+[recent Turns] ← rolling window
+[current user message] ← always new
+```
+
+High-score Turns are **pinned** right after long-term memory in ascending order. New Turns only append — they never shift existing content. This maximizes the cache-hit prefix length, and the cost difference is dramatic at scale.
+
+### Three-Layer Memory Hierarchy
+
+| Layer | Lifecycle | Source | Consumer |
+|-------|-----------|--------|----------|
+| **Instant Memory** | Assembled per-Turn | Turn Store (score + tag filter) | Phase 2 (ExecuteLLM) |
+| **Active Context** | Rolling update per `channel:chatID` | Phase 3 sync update | Phase 1 (Analyse) |
+| **Long-Term Memory** | Persistent | MemoryDigest batch worker | Phase 1 (via tag retrieval) |
+
+Each layer serves a different phase. No overlap, no waste. Active Context (current files, recent errors) helps Phase 1 understand terse messages like "fix it". Instant Memory gives Phase 2 the right historical context. Long-term memory accumulates wisdom across sessions.
+
+### Why This Matters
+
+Traditional agent loops dump everything into one LLM call and hope for the best. PicoClaw's approach means:
+
+- 📉 **~60% fewer wasted tokens** from irrelevant tools and stale context
+- 🎯 **Higher decision quality** — focused toolsets reduce LLM confusion
+- ⚡ **Sub-2ms overhead** for scoring and context updates (zero perceived latency)
+- 🧲 **Associative recall** — old conversations resurface when relevant, like human memory
+- 💰 **Multi-model cost optimization** — use cheap models for analysis, strong models for execution
+
+> *"The best token is the one you never send."*
+
## 🦾 Demonstration
### 🛠️ Standard Assistant Workflows
diff --git a/README.zh.md b/README.zh.md
index d3a49ee8d..824e7f521 100644
--- a/README.zh.md
+++ b/README.zh.md
@@ -80,6 +80,87 @@
+## 🧠 我们的思考
+
+PicoClaw 不只是小——它的**思维方式**和其他 AI Agent 框架根本不同。大多数框架把 LLM 当黑箱,把所有工具、所有历史、所有上下文一股脑塞进去。PicoClaw 引入了结构化的 **Runtime Loop**,让每一个 token 都物尽其用。
+
+### 三阶段 Runtime Loop
+
+每次用户交互都经过三个清晰的阶段:
+
+```
+┌──────────────┐ ┌──────────────┐ ┌──────────────┐
+│ Phase 1 │ → │ Phase 2 │ → │ Phase 3 │
+│ 分析 Analyse│ │ 执行 ExecuteLLM│ │ 反思 Reflect │
+│ (编排器) │ │ (执行器) │ │ (学习器) │
+└──────────────┘ └──────────────┘ └──────────────┘
+```
+
+- **Phase 1 — 分析**:轻量 LLM 调用(可用便宜/快速模型),理解用户意图、分配语义标签、准备最优上下文。无工具、无历史膨胀——纯粹的理解力。
+- **Phase 2 — 执行**:主 LLM 只携带 Phase 1 认为相关的工具和上下文进行迭代。工具越少 = 干扰越少 = 决策越好。
+- **Phase 3 — 反思**:同步打分 + 上下文更新(< 2ms),在用户看到回复之前完成,然后异步持久化。Agent 从每次交互中学习,且不增加延迟。
+
+### Turn 打分 & 瞬时记忆
+
+每个 Turn 都会根据工具活动、意图权重、内容密度和用户显式标记获得一个**分数**。这个分数驱动一个新颖的上下文选择算法:
+
+```
+瞬时记忆 = { 高分 Turn } // 无条件保留
+ ∪ { tag 匹配的 Turn, score > 0 } // 旧 Turn 被"唤醒"
+ ∪ { 最近 M 个 Turn } // 连贯性保底
+ → 按时间排序,截断到容量上限
+```
+
+**Turn 永不删除。** 低分 Turn 只是被排除在上下文之外——但当未来 Phase 1 产生匹配的 tags 时,它们可以被重新召回。就像人类记忆:你不会忘记东西,只是在某个触发点之前无法访问它们。
+
+### Tag 驱动的工具加载
+
+传统框架每次请求都把 20+ 个工具定义喂给 LLM(每次迭代浪费 ~3,000 tokens)。PicoClaw 把工具分为两层:
+
+| 层级 | 工具 | 加载方式 |
+|------|------|---------|
+| **always-on** | `read_file`、`write_file`、`shell` 等 | 始终加载 |
+| **tag-gated** | MCP servers、Skills、`web_search`、`cron` | 仅当 Phase 1 的 tags 匹配时加载 |
+
+随着 MCP Servers 和 Skills 的增多,节省量呈指数级增长——而且 LLM 在精简的工具集下做出更好的决策。
+
+### KV Cache 友好的消息排列
+
+我们执着于**前缀稳定性**,以最大化跨 Provider 的 KV Cache 命中率(Gemini 隐式缓存、Anthropic `cache_control`、OpenAI prompt caching):
+
+```
+[system_prompt] ← 始终缓存 ✅
+[long_term_memory by tags] ← 相同 tags 时稳定 ✅
+[高分 Turn, 按 ID 升序] ← 位置固定,只增不移 ✅
+[tag 匹配的 Turn] ← 可能变化
+[最近的 Turn] ← 滚动窗口
+[当前用户消息] ← 总是新内容
+```
+
+高分 Turn 被**固定**在长期记忆之后,按升序排列。新 Turn 只追加到末尾,不改变已有内容的位置。这最大化了缓存命中的前缀长度,在规模化场景下成本差异显著。
+
+### 三层记忆体系
+
+| 层次 | 生命周期 | 数据来源 | 消费者 |
+|------|---------|---------|--------|
+| **瞬时记忆** | 每轮动态组装 | Turn 库(score + tag 筛选)| Phase 2(ExecuteLLM)|
+| **活跃上下文** | 跨 Turn 滚动更新,per `channel:chatID` | Phase 3 同步维护 | Phase 1(Analyse)|
+| **长期记忆** | 持久化 | MemoryDigest 定时批量提炼 | Phase 1(通过 tag 检索)|
+
+每层服务不同的阶段。没有重叠,没有浪费。活跃上下文(当前文件、近期错误)帮助 Phase 1 理解简短消息如"修一下"。瞬时记忆为 Phase 2 提供正确的历史上下文。长期记忆跨会话积累智慧。
+
+### 为什么这很重要
+
+传统的 Agent 循环把所有东西塞进一个 LLM 调用,然后听天由命。PicoClaw 的方式意味着:
+
+- 📉 **减少 ~60% 的浪费 token** — 排除无关工具和陈旧上下文
+- 🎯 **更高的决策质量** — 精简工具集减少 LLM 的"选择困难症"
+- ⚡ **< 2ms 的额外开销** — 打分和上下文更新零感知延迟
+- 🧲 **联想式召回** — 旧对话在相关时自动浮现,就像人类记忆
+- 💰 **多模型成本优化** — 分析用便宜模型,执行用强模型
+
+> *"最好的 token 是你永远不需要发送的那个。"*
+
## 🦾 演示
### 🛠️ 标准助手工作流
diff --git a/Taskfile.yml b/Taskfile.yml
new file mode 100644
index 000000000..31a38ca73
--- /dev/null
+++ b/Taskfile.yml
@@ -0,0 +1,139 @@
+version: '3'
+
+vars:
+ BINARY_NAME: picoclaw
+ CMD_DIR: cmd/picoclaw
+ BUILD_DIR: build
+ LAUNCHER_DIR: cmd/picoclaw-launcher
+ LAUNCHER_BUILD_DIR: cmd/picoclaw-launcher/build/bin
+ INTERNAL: github.com/sipeed/picoclaw/cmd/picoclaw/internal
+ VERSION:
+ sh: git describe --tags --always --dirty 2>{{if eq OS "windows"}}nul{{else}}/dev/null{{end}} || echo dev
+ GIT_COMMIT:
+ sh: git rev-parse --short=8 HEAD 2>{{if eq OS "windows"}}nul{{else}}/dev/null{{end}} || echo dev
+ LDFLAGS: -ldflags "-X {{.INTERNAL}}.version={{.VERSION}} -X {{.INTERNAL}}.gitCommit={{.GIT_COMMIT}} -s -w"
+
+tasks:
+ default:
+ desc: Build the project
+ cmds:
+ - task: build
+
+ all:
+ desc: Build picoclaw + launcher (both binaries)
+ deps:
+ - build
+ - build-launcher
+
+ build:
+ desc: Build picoclaw binary (dev, skip generate)
+ cmds:
+ - go build -v {{.LDFLAGS}} -o {{.BUILD_DIR}}/{{.BINARY_NAME}}{{exeExt}} ./{{.CMD_DIR}}
+ sources:
+ - "**/*.go"
+ generates:
+ - "{{.BUILD_DIR}}/{{.BINARY_NAME}}{{exeExt}}"
+
+ build-full:
+ desc: Build with go generate (release)
+ cmds:
+ - task: generate
+ - task: build
+
+ build-launcher:
+ desc: Build picoclaw-launcher (Wails desktop GUI)
+ dir: '{{.LAUNCHER_DIR}}'
+ cmds:
+ - go tool wails build -tags stdjson -ldflags "-s -w" -o picoclaw-launcher{{exeExt}}
+ sources:
+ - "**/*.go"
+ - frontend/**
+ generates:
+ - '../../{{.LAUNCHER_BUILD_DIR}}/picoclaw-launcher{{exeExt}}'
+
+ generate:
+ desc: Run go generate
+ cmds:
+ - cmd: powershell -Command "Remove-Item -Recurse -Force '{{.CMD_DIR}}/internal/onboard/workspace' -ErrorAction SilentlyContinue"
+ platforms: [windows]
+ - cmd: rm -rf {{.CMD_DIR}}/internal/onboard/workspace
+ platforms: [linux, darwin]
+ - go generate ./...
+
+ test:
+ desc: Run all tests
+ cmds:
+ - go test -count=1 ./pkg/...
+
+ test-v:
+ desc: Run all tests (verbose)
+ cmds:
+ - go test -v -count=1 ./pkg/...
+
+ test-agent:
+ desc: Run agent tests
+ cmds:
+ - go test -v -count=1 ./pkg/agent/
+
+ test-config:
+ desc: Run config tests
+ cmds:
+ - go test -v -count=1 ./pkg/config/
+
+ test-init:
+ desc: Run init command tests
+ cmds:
+ - go test -v -count=1 ./cmd/picoclaw/internal/initcmd/
+
+ lint:
+ desc: Run linters
+ cmds:
+ - golangci-lint run
+
+ fmt:
+ desc: Format code
+ cmds:
+ - gofmt -w .
+
+ vet:
+ desc: Run go vet
+ cmds:
+ - go vet ./...
+
+ clean:
+ desc: Remove build artifacts
+ cmds:
+ - cmd: powershell -Command "Remove-Item -Recurse -Force '{{.BUILD_DIR}}' -ErrorAction SilentlyContinue"
+ platforms: [windows]
+ - cmd: rm -rf {{.BUILD_DIR}}
+ platforms: [linux, darwin]
+
+ deps:
+ desc: Download and verify dependencies
+ cmds:
+ - go mod download
+ - go mod verify
+
+ tidy:
+ desc: Tidy dependencies
+ cmds:
+ - go mod tidy
+
+ check:
+ desc: Full check (fmt + vet + test)
+ cmds:
+ - task: fmt
+ - task: vet
+ - task: test
+
+ install:
+ desc: Install picoclaw to system
+ cmds:
+ - task: build
+ - go install ./{{.CMD_DIR}}
+
+ run:
+ desc: Build and run
+ cmds:
+ - task: build
+ - "{{.BUILD_DIR}}/{{.BINARY_NAME}}{{exeExt}} {{.CLI_ARGS}}"