scaffolding: root README, plan, VS Code build tasks, Gitea Actions release workflow
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmdG9GqfSWCzts7AkDwRDh
This commit is contained in:
105
.gitea/workflows/release.yml
Normal file
105
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
name: release-tools
|
||||||
|
|
||||||
|
# På varje push till master/main: bygg de tools som fått ändringar
|
||||||
|
# (linux x64 + arm64) och lägg binärerna på en rullande
|
||||||
|
# "<tool>-latest"-release på släppsidan i Gitea.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master, main]
|
||||||
|
workflow_dispatch: {} # manuell körning bygger ALLA tools
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # hela historiken behövs för diffen mot 'before'
|
||||||
|
|
||||||
|
- name: Detektera ändrade tools
|
||||||
|
id: changed
|
||||||
|
run: |
|
||||||
|
TOOLS="pixel-sprite-maker mesh-tool"
|
||||||
|
BEFORE="${{ github.event.before }}"
|
||||||
|
CHANGED=""
|
||||||
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ] \
|
||||||
|
|| [ -z "$BEFORE" ] \
|
||||||
|
|| echo "$BEFORE" | grep -Eq '^0+$' \
|
||||||
|
|| ! git cat-file -e "$BEFORE" 2>/dev/null; then
|
||||||
|
echo "första push / manuell körning -> bygger alla tools"
|
||||||
|
CHANGED="$TOOLS"
|
||||||
|
else
|
||||||
|
for t in $TOOLS; do
|
||||||
|
if ! git diff --quiet "$BEFORE" "${{ github.sha }}" -- "$t/"; then
|
||||||
|
CHANGED="$CHANGED $t"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
CHANGED="$(echo $CHANGED)" # trimma whitespace
|
||||||
|
echo "tools=$CHANGED" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "bygger: ${CHANGED:-inget}"
|
||||||
|
|
||||||
|
- name: Installera Go
|
||||||
|
if: steps.changed.outputs.tools != ''
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.24"
|
||||||
|
cache: false
|
||||||
|
|
||||||
|
- name: Testa + bygg (x64 + arm64)
|
||||||
|
if: steps.changed.outputs.tools != ''
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
VERSION="latest-$(git rev-parse --short HEAD)"
|
||||||
|
for t in ${{ steps.changed.outputs.tools }}; do
|
||||||
|
case "$t" in
|
||||||
|
pixel-sprite-maker) BIN=spritec ;;
|
||||||
|
mesh-tool) BIN=mesht ;;
|
||||||
|
*) echo "okänt tool $t"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
echo "=== $t ($BIN) ==="
|
||||||
|
cd "$t"
|
||||||
|
go test ./...
|
||||||
|
mkdir -p build
|
||||||
|
GOOS=linux GOARCH=amd64 go build -trimpath \
|
||||||
|
-ldflags "-s -w -X main.version=$VERSION" -o "build/$BIN-linux-x64" .
|
||||||
|
GOOS=linux GOARCH=arm64 go build -trimpath \
|
||||||
|
-ldflags "-s -w -X main.version=$VERSION" -o "build/$BIN-linux-arm64" .
|
||||||
|
(cd build && sha256sum "$BIN"-linux-* > checksums.txt && ls -la)
|
||||||
|
cd ..
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Skapa/uppdatera releaser + ladda upp binärer
|
||||||
|
if: steps.changed.outputs.tools != ''
|
||||||
|
env:
|
||||||
|
API: http://gitea-d:3000/api/v1
|
||||||
|
REPO: ${{ github.repository }}
|
||||||
|
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
for t in ${{ steps.changed.outputs.tools }}; do
|
||||||
|
case "$t" in
|
||||||
|
pixel-sprite-maker) BIN=spritec ;;
|
||||||
|
mesh-tool) BIN=mesht ;;
|
||||||
|
esac
|
||||||
|
TAG="$t-latest"
|
||||||
|
BODY="$t (binär: $BIN) - rullande bygge från senaste master. Commit: ${{ github.sha }}. Arkitekturer: linux x64 + arm64 (Pi5)."
|
||||||
|
rid=$(curl -s -X POST "$API/repos/$REPO/releases" \
|
||||||
|
-H "Authorization: token $TOKEN" -H 'Content-Type: application/json' \
|
||||||
|
-d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\",\"body\":\"$BODY\"}" | jq -r '.id // empty')
|
||||||
|
[ -z "$rid" ] && rid=$(curl -s "$API/repos/$REPO/releases/tags/$TAG" \
|
||||||
|
-H "Authorization: token $TOKEN" | jq -r '.id')
|
||||||
|
echo "$t -> release id $rid"
|
||||||
|
for f in "$BIN-linux-x64" "$BIN-linux-arm64" checksums.txt; do
|
||||||
|
aid=$(curl -s "$API/repos/$REPO/releases/$rid/assets" \
|
||||||
|
-H "Authorization: token $TOKEN" | jq -r ".[] | select(.name==\"$f\") | .id")
|
||||||
|
if [ -n "$aid" ] && [ "$aid" != "null" ]; then
|
||||||
|
curl -s -X DELETE "$API/repos/$REPO/releases/$rid/assets/$aid" \
|
||||||
|
-H "Authorization: token $TOKEN" -o /dev/null
|
||||||
|
fi
|
||||||
|
curl -s -X POST "$API/repos/$REPO/releases/$rid/assets?name=$f" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-F "attachment=@$t/build/$f" -o /dev/null -w " $f -> HTTP %{http_code}\n"
|
||||||
|
done
|
||||||
|
done
|
||||||
44
.vscode/tasks.json
vendored
Normal file
44
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "build pixel-sprite-maker",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "go build -trimpath -ldflags '-s -w' -o build/spritec .",
|
||||||
|
"options": { "cwd": "${workspaceFolder}/pixel-sprite-maker" },
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": ["$go"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "build mesh-tool",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "go build -trimpath -ldflags '-s -w' -o build/mesht .",
|
||||||
|
"options": { "cwd": "${workspaceFolder}/mesh-tool" },
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": ["$go"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "test pixel-sprite-maker",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "go test ./...",
|
||||||
|
"options": { "cwd": "${workspaceFolder}/pixel-sprite-maker" },
|
||||||
|
"group": "test",
|
||||||
|
"problemMatcher": ["$go"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "test mesh-tool",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "go test ./...",
|
||||||
|
"options": { "cwd": "${workspaceFolder}/mesh-tool" },
|
||||||
|
"group": "test",
|
||||||
|
"problemMatcher": ["$go"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "build",
|
||||||
|
"dependsOn": ["build pixel-sprite-maker", "build mesh-tool"],
|
||||||
|
"dependsOrder": "parallel",
|
||||||
|
"group": { "kind": "build", "isDefault": true },
|
||||||
|
"problemMatcher": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
45
README.md
45
README.md
@@ -1,3 +1,46 @@
|
|||||||
# agent-tools
|
# agent-tools
|
||||||
|
|
||||||
smal tools for ai agents
|
Small, self-contained CLI tools built for **AI agents** to use during
|
||||||
|
development work. Every tool is a single static Go binary with a
|
||||||
|
text-first interface: input formats an agent can read and write
|
||||||
|
directly, and output (names, errors, previews) explicit enough that the
|
||||||
|
agent understands the result without opening an image viewer.
|
||||||
|
|
||||||
|
| Tool | Binary | What it does |
|
||||||
|
|------|--------|--------------|
|
||||||
|
| [`pixel-sprite-maker/`](pixel-sprite-maker/) | `spritec` | Turns `.sprite` text files (palette + character grid) into PNG/JPG/SVG pixel art, up to 256x256 px per sprite. Combines several sprites into sprite sheets / animation strips whose **file names document the layout** (`walk_8x8_4x1.png` = 8x8 px frames, 4 columns, 1 row). |
|
||||||
|
| [`mesh-tool/`](mesh-tool/) | `mesht` | Creates, inspects and edits 3D models (OBJ + STL). ASCII multi-view rendering + measurements (bbox, volume, watertightness) let an agent *see* a model, edit it (scale/rotate/mirror/merge/primitives) and verify the result. |
|
||||||
|
|
||||||
|
Each tool has its own folder, its own README with the full format/CLI
|
||||||
|
reference, its own tests and its own dev branch (`dev/<tool>`).
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Arch/Garuda prerequisite:
|
||||||
|
sudo pacman -S go
|
||||||
|
|
||||||
|
cd <tool>/ && go build -o build/<binary> . # per tool
|
||||||
|
go test ./... # per tool
|
||||||
|
```
|
||||||
|
|
||||||
|
VS Code: **Terminal → Run Build Task** — `build` builds every tool into
|
||||||
|
its own `<tool>/build/` folder; per-tool `build <tool>` and
|
||||||
|
`test <tool>` tasks also exist.
|
||||||
|
|
||||||
|
## CI / releases
|
||||||
|
|
||||||
|
`.gitea/workflows/release.yml` runs on every push to `master`/`main` on
|
||||||
|
the self-hosted runner: tools whose folders changed are tested, built
|
||||||
|
for **linux x64 + arm64** (the Pi5), and published to a rolling
|
||||||
|
release per tool on the repo's release page:
|
||||||
|
|
||||||
|
- tag `pixel-sprite-maker-latest` → assets `spritec-linux-x64`, `spritec-linux-arm64`, `checksums.txt`
|
||||||
|
- tag `mesh-tool-latest` → assets `mesht-linux-x64`, `mesht-linux-arm64`, `checksums.txt`
|
||||||
|
|
||||||
|
A manual `workflow_dispatch` run builds all tools regardless of diffs.
|
||||||
|
|
||||||
|
## Branch layout
|
||||||
|
|
||||||
|
- `main` — stable, releases are built from here
|
||||||
|
- `dev/pixel-sprite-maker`, `dev/mesh-tool` — per-tool development branches
|
||||||
|
|||||||
43
doc/plan.md
Normal file
43
doc/plan.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# agent-tools — plan
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
A collection of small, agent-friendly CLI tools. The common thread:
|
||||||
|
**text in, verifiable artifacts out**. An agent should be able to author
|
||||||
|
the input format directly, predict what the output will look like, and
|
||||||
|
verify results without a GUI.
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
- Go (single static binaries, zero deps, trivial cross-compile to the
|
||||||
|
Pi5's arm64 runner), one Go module per tool.
|
||||||
|
- Targets: linux x64 + linux arm64.
|
||||||
|
|
||||||
|
## Deploy target
|
||||||
|
|
||||||
|
Pattern A (distributable binaries): rolling `<tool>-latest` release per
|
||||||
|
tool on Gitea, built by `.gitea/workflows/release.yml` on push to
|
||||||
|
master/main. Only tools whose folders changed get rebuilt.
|
||||||
|
|
||||||
|
## Milestones
|
||||||
|
|
||||||
|
1. ✅ `pixel-sprite-maker` (`spritec`): .sprite text format → PNG/JPG/SVG,
|
||||||
|
sprite sheets with self-documenting file names, terminal preview.
|
||||||
|
2. ✅ `mesh-tool` (`mesht`): OBJ/STL create/inspect/edit with ASCII
|
||||||
|
multi-view rendering, measurements and watertightness checks.
|
||||||
|
3. ✅ Per-tool VS Code build tasks → `<tool>/build/`.
|
||||||
|
4. ✅ CI: changed-tool detection + per-tool rolling releases.
|
||||||
|
|
||||||
|
## Roadmap / expansion ideas (not agreed yet)
|
||||||
|
|
||||||
|
- spritec: palette import from image files, GIF export for animations,
|
||||||
|
tile-map composer (map file referencing sprite tiles).
|
||||||
|
- mesht: OBJ vertex-color support, simple boolean ops (union via
|
||||||
|
voxelization), PNG snapshot rendering, glTF export.
|
||||||
|
- New tools: bitmap-font maker, sound-effect generator (sfxr-style text
|
||||||
|
presets), tiled-map (.tmx) writer.
|
||||||
|
|
||||||
|
## Open questions
|
||||||
|
|
||||||
|
- Versioned releases (`vX.Y.Z` tags per tool) on top of the rolling
|
||||||
|
`latest` — add when something depends on a pinned version.
|
||||||
Reference in New Issue
Block a user