Skip to content

Commit ca1a790

Browse files
bobakemamianclaude
andcommitted
feat: initial release
Buttons is a CLI workflow engine for AI agents. Agents press buttons — self-contained, reusable actions with typed inputs, clear outputs, and structured status — instead of hoping an LLM follows a multi-step procedure correctly. This first release includes: - Core CLI: buttons create, press, list, history, delete, detail, version - Four button sources: shell/python/node code, HTTP API, script file, agent instruction - Structured JSON output on every command with non-TTY auto-detection - Context-aware {{arg}} template encoding in HTTP URLs and bodies - SSRF blocklist on HTTP buttons (opt out with --allow-private-networks) - Per-button response body size cap (default 10 MB) - Timeout + process-group reaping on shell/code buttons - Folder-per-button layout under ~/.buttons/ - Pressed-run history as JSON files per button Distribution: - install.sh for macOS + Linux (amd64/arm64) - Multi-arch Docker image at ghcr.io/autonoco/buttons - go install github.com/autonoco/buttons@latest - goreleaser release pipeline, multi-platform binaries with SHA256 checksums - GitHub Actions CI: test, vet, gosec, govulncheck, gitleaks, matrix on ubuntu+macos Documentation: - README.md with install, quick start, full CLI reference - SECURITY.md with threat model and private vulnerability reporting - CLAUDE.md for contributor context - LICENSE: Apache-2.0 Windows support is tracked as future work — current release targets darwin and linux only because internal/engine/execute.go uses Unix process-group syscalls for timeout reaping. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0 parents  commit ca1a790

61 files changed

Lines changed: 7123 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: gomod
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
day: monday
8+
time: "09:00"
9+
timezone: America/Los_Angeles
10+
open-pull-requests-limit: 5
11+
labels:
12+
- dependencies
13+
- buttons
14+
commit-message:
15+
prefix: chore
16+
include: scope
17+
18+
- package-ecosystem: github-actions
19+
directory: /
20+
schedule:
21+
interval: weekly
22+
day: monday
23+
time: "09:00"
24+
timezone: America/Los_Angeles
25+
open-pull-requests-limit: 5
26+
labels:
27+
- dependencies
28+
- buttons
29+
commit-message:
30+
prefix: chore
31+
include: scope

.github/workflows/ci.yml

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
# Cancel older runs on the same branch/PR when a new commit is pushed.
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
permissions:
15+
contents: read
16+
17+
env:
18+
# Pinned Go toolchain. Bumping this also resolves stdlib CVEs
19+
# tracked in autonoco/autono#331. 1.26.2 adds fixes for four
20+
# more vulnerabilities (GO-2026-4866 x509 auth bypass, -4870
21+
# TLS 1.3 KeyUpdate DoS, -4946/-4947 x509 DoS) that 1.26.1
22+
# is still exposed to.
23+
GO_VERSION: "1.26.2"
24+
25+
jobs:
26+
test:
27+
name: Test (${{ matrix.os }})
28+
runs-on: ${{ matrix.os }}
29+
timeout-minutes: 10
30+
strategy:
31+
fail-fast: false
32+
matrix:
33+
os: [ubuntu-latest, macos-latest]
34+
steps:
35+
- name: Check out code
36+
uses: actions/checkout@v4
37+
38+
- name: Set up Go
39+
uses: actions/setup-go@v5
40+
with:
41+
go-version: ${{ env.GO_VERSION }}
42+
cache: true
43+
44+
- name: Verify module integrity
45+
run: go mod verify
46+
47+
- name: Build
48+
run: go build ./...
49+
50+
- name: Vet
51+
run: go vet ./...
52+
53+
- name: Unit tests (with race detector)
54+
run: go test -race -count=1 ./internal/...
55+
56+
- name: Integration tests
57+
run: go test -count=1 ./test/integration/...
58+
59+
gosec:
60+
name: gosec
61+
runs-on: ubuntu-latest
62+
timeout-minutes: 10
63+
steps:
64+
- name: Check out code
65+
uses: actions/checkout@v4
66+
67+
- name: Set up Go
68+
uses: actions/setup-go@v5
69+
with:
70+
go-version: ${{ env.GO_VERSION }}
71+
cache: true
72+
73+
- name: Install gosec
74+
run: go install github.com/securego/gosec/v2/cmd/gosec@latest
75+
76+
- name: Run gosec
77+
run: gosec ./...
78+
79+
govulncheck:
80+
name: govulncheck
81+
runs-on: ubuntu-latest
82+
timeout-minutes: 10
83+
steps:
84+
- name: Check out code
85+
uses: actions/checkout@v4
86+
87+
- name: Set up Go
88+
uses: actions/setup-go@v5
89+
with:
90+
go-version: ${{ env.GO_VERSION }}
91+
cache: true
92+
93+
- name: Install govulncheck
94+
run: go install golang.org/x/vuln/cmd/govulncheck@latest
95+
96+
- name: Run govulncheck
97+
run: govulncheck ./...
98+
99+
gitleaks:
100+
name: gitleaks
101+
runs-on: ubuntu-latest
102+
timeout-minutes: 5
103+
env:
104+
# Pinned so Dependabot (or a follow-up PR) can bump it intentionally.
105+
# gitleaks-action@v2 requires a license for private repos, so we
106+
# install the binary directly instead — free regardless of repo
107+
# visibility and also faster.
108+
GITLEAKS_VERSION: "8.30.1"
109+
steps:
110+
- name: Check out code
111+
uses: actions/checkout@v4
112+
with:
113+
fetch-depth: 0 # Full history so gitleaks can scan every commit.
114+
115+
- name: Install gitleaks
116+
run: |
117+
curl -sSfL -o gitleaks.tar.gz \
118+
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
119+
tar -xzf gitleaks.tar.gz gitleaks
120+
sudo install -m 0755 gitleaks /usr/local/bin/gitleaks
121+
rm -f gitleaks gitleaks.tar.gz
122+
gitleaks version
123+
124+
- name: Scan repository
125+
run: gitleaks detect --source . --verbose --redact --no-banner
126+
127+
build-release:
128+
name: Build (release ldflags)
129+
runs-on: ubuntu-latest
130+
timeout-minutes: 10
131+
steps:
132+
- name: Check out code
133+
uses: actions/checkout@v4
134+
with:
135+
fetch-depth: 0 # Tags + full history so `git describe` works.
136+
137+
- name: Set up Go
138+
uses: actions/setup-go@v5
139+
with:
140+
go-version: ${{ env.GO_VERSION }}
141+
cache: true
142+
143+
- name: Build with version injection (make build)
144+
run: make build
145+
146+
- name: Smoke test binary
147+
run: ./buttons --help

.github/workflows/release.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Release
2+
3+
# Runs goreleaser on every semver tag push (v*). For a snapshot build
4+
# that doesn't publish, run locally:
5+
#
6+
# goreleaser release --snapshot --clean --skip=publish
7+
8+
on:
9+
push:
10+
tags:
11+
- 'v*'
12+
13+
permissions:
14+
contents: write # Create the GitHub Release.
15+
packages: write # Push Docker images to ghcr.io.
16+
17+
jobs:
18+
goreleaser:
19+
name: goreleaser
20+
runs-on: ubuntu-latest
21+
timeout-minutes: 30
22+
steps:
23+
- name: Check out code
24+
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0 # Full history + tags for goreleaser changelog.
27+
28+
- name: Set up Go
29+
uses: actions/setup-go@v5
30+
with:
31+
go-version: "1.26.2"
32+
cache: true
33+
34+
# QEMU + Buildx let us build the linux/arm64 image from an amd64
35+
# runner. goreleaser's dockers: block drives `docker buildx build`
36+
# with per-platform flags; buildx transparently uses QEMU for the
37+
# non-native arch.
38+
- name: Set up QEMU
39+
uses: docker/setup-qemu-action@v3
40+
41+
- name: Set up Docker Buildx
42+
uses: docker/setup-buildx-action@v3
43+
44+
# Log in to GHCR so goreleaser can push the built images. The
45+
# default GITHUB_TOKEN has packages:write from the permissions
46+
# block above, so no PAT is required for pushes to ghcr.io.
47+
- name: Log in to GHCR
48+
uses: docker/login-action@v3
49+
with:
50+
registry: ghcr.io
51+
username: ${{ github.actor }}
52+
password: ${{ secrets.GITHUB_TOKEN }}
53+
54+
- name: Run goreleaser
55+
uses: goreleaser/goreleaser-action@v6
56+
with:
57+
distribution: goreleaser
58+
version: "~> v2" # Track the v2 major.
59+
args: release --clean
60+
env:
61+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
buttons
2+
dist/
3+
.claude/
4+
.env
5+
.env.*
6+
*.pem
7+
*.key
8+
AUDIT.md
9+
.DS_Store

0 commit comments

Comments
 (0)