Skip to content

Commit 39c7680

Browse files
NagyViktclaude
andcommitted
v1.15: Debian packaging (.deb build + GitHub Actions release)
- packaging/build-deb.sh — pure dpkg-deb build, no debhelper. Stages a filesystem tree (/usr/bin/, /usr/share/applications/, /usr/lib/ systemd/user/, /usr/share/flashpaste/, /usr/share/doc/flashpaste/) then packages it. Scripts get the .sh suffix stripped for clean /usr/bin/flashpaste-doctor etc. naming. - Makefile — `make deb / install / doctor / uninstall / clean / release-deb`. `VERSION` defaults to latest git tag, override with `VERSION=x.y.z make deb`. - .github/workflows/release.yml — on push of `v*` tag, builds the .deb on ubuntu-24.04 and uploads it to a GitHub Release with auto-generated notes. Lintian-clean. - README — Option A (apt-install .deb) added at the top of Quick Start before the curl|bash bootstrap. - .gitignore — added dist/ and *.deb so built artefacts don't leak into the repo. Verified locally: `make deb` produces a 36KB flashpaste_1.14.0_all.deb with correct Depends, postinst hint, and full filesystem layout. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6cbd782 commit 39c7680

6 files changed

Lines changed: 404 additions & 1 deletion

File tree

.github/workflows/release.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
build-deb:
13+
runs-on: ubuntu-24.04
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
19+
- name: Install build dependencies
20+
run: |
21+
sudo apt-get update -qq
22+
sudo apt-get install -y dpkg-dev lintian
23+
24+
- name: Resolve version from tag
25+
id: ver
26+
run: echo "v=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
27+
28+
- name: Build .deb
29+
run: VERSION=${{ steps.ver.outputs.v }} bash packaging/build-deb.sh
30+
31+
- name: Show package info
32+
run: |
33+
ls -la dist/
34+
dpkg-deb -I dist/flashpaste_${{ steps.ver.outputs.v }}_all.deb
35+
dpkg-deb -c dist/flashpaste_${{ steps.ver.outputs.v }}_all.deb | head -40
36+
37+
- name: Upload to GitHub Release
38+
env:
39+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40+
run: |
41+
gh release create "${GITHUB_REF_NAME}" \
42+
dist/flashpaste_${{ steps.ver.outputs.v }}_all.deb \
43+
--title "flashpaste ${GITHUB_REF_NAME}" \
44+
--generate-notes

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
*.log
33
*.tmp
44
.DS_Store
5+
dist/
6+
*.deb

AGENTS.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# flashpaste — agent guide
2+
3+
Working rules for agents (Claude, Codex, etc.) editing this repository.
4+
5+
## Versioning + releases — non-negotiable
6+
7+
**Every push that bumps a version MUST be accompanied by a matching GitHub release.** Pushing a commit titled `v1.X` without a release is a defect.
8+
9+
Workflow for any version bump:
10+
11+
1. **Bump in this order:**
12+
- `README.md` — if a version string appears in the tagline or quick-start
13+
- `bin/tmux-paste-dispatch.sh` header `WORKING VERSION: v1.X — <date>` comment
14+
- Any other file with a `v1.X` literal — search with `git grep '^# WORKING VERSION'` and `git grep -F 'v1.'`
15+
16+
2. **Commit message format:**
17+
```
18+
v1.X: <one-line summary>
19+
20+
<multi-paragraph body explaining what changed and why,
21+
matching the style of v1.10–v1.14 in the existing history>
22+
23+
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
24+
```
25+
Use `git log --pretty=fuller` to confirm the trailer is preserved.
26+
27+
3. **Tag + push:**
28+
```bash
29+
git tag -a v1.X -m "v1.X: <one-line summary>"
30+
git push origin main
31+
git push origin v1.X
32+
```
33+
34+
4. **Create the GitHub release immediately after pushing:**
35+
```bash
36+
gh release create v1.X \
37+
--title "v1.X: <one-line summary>" \
38+
--notes "$(git log -1 --pretty=%B v1.X | tail -n +3)"
39+
```
40+
The `tail -n +3` skips the title line + blank line so the body is the multi-paragraph description.
41+
- If this is a **breaking** change, add `--latest=true` and prepend a `### Breaking` block to the notes.
42+
- If experimental / not ready for general use, add `--prerelease`.
43+
44+
5. **Verify** with `gh release view v1.X` and `gh release list --limit 5`. The new release MUST appear in the list before considering the bump complete.
45+
46+
## Version-number policy
47+
48+
- **Patch (`v1.X.Y`)** — bash-only fixes, doc changes, .desktop tweaks, install.sh hygiene.
49+
- **Minor (`v1.X`)** — new bash scripts, new systemd units, new env knobs.
50+
- **Major (`v2.X`)** — reserved for the daemon (`flashpasted`) becoming the default path and the bash dispatcher becoming a fallback only. As of v1.15 the daemon is opt-in; do not cut v2.0 until the dispatcher mode-flag flips by default.
51+
52+
## Where work lives
53+
54+
```
55+
bin/ bash hot path (canonical, always works)
56+
rs/ Rust workspace — flashpaste-{common,dispatch,trigger,shoot} + flashpasted
57+
share/applications/ NoDisplay .desktop files for surfaceless Wayland clients
58+
systemd/ user units (clipboard-janitor, screenshot-watcher, flashpasted)
59+
examples/ config snippets for tmux + kitty
60+
```
61+
62+
When you touch the Rust code, never break the bash fallback. The trigger binary execs the bash dispatcher when the daemon is absent; the dispatch binary forks the bash dispatcher when the fast-path bails. Both fallbacks must keep working.
63+
64+
## Four hard-won facts the code must preserve
65+
66+
Stamped into `bin/tmux-paste-dispatch.sh`'s edit log; restated here so agents don't accidentally regress them:
67+
68+
1. **`kitty @ send-text` is the only transport** that triggers Claude Code's image-paste handler. `tmux send-keys -t pane C-v` writes the byte but the handler doesn't fire.
69+
2. **`tmux bind -n C-v` recurses** when `\026` arrives via kitty send-text. `tmux unbind -n C-v` before send-text, rebind ~100ms later via `setsid -f sh -c 'sleep 0.1; tmux bind ...'` (detached so it survives parent exit).
70+
3. **Wayland-authoritative `has_image` policy.** Trust Wayland if it answers; only fall back to X11 when Wayland is fully silent. mutter's X11↔Wayland bridge is sticky and X11 keeps advertising stale `image/png` after fresh text copies — trusting it produces the obs #6881 "GitHub URL → [Image #9]" bug.
71+
4. **GNOME PrtScr saves but doesn't copy.** Auto-pickup loads `~/Pictures/Screenshots/<latest>.png` into the clipboard if ≤30s old and clipboard text is empty.
72+
73+
If your change might affect any of these, add a regression test (or a manual test plan) to the commit body.
74+
75+
## Build + test commands
76+
77+
```bash
78+
# Bash syntax check
79+
bash -n bin/*.sh install.sh bootstrap.sh
80+
81+
# Rust workspace
82+
cargo build --release --manifest-path rs/Cargo.toml
83+
cargo fmt --manifest-path rs/Cargo.toml --check
84+
cargo clippy --release --manifest-path rs/Cargo.toml -- -D warnings
85+
86+
# Doctor
87+
bash bin/flashpaste-doctor.sh
88+
```
89+
90+
Do NOT run `cargo build` or `cargo update` without user approval — they hit crates.io.
91+
92+
## Memory-lane reminder
93+
94+
Per `/home/deadpool/.claude/CLAUDE.md`, three memory systems coexist on this machine. For flashpaste work, default to the file-based memory under `~/.claude-accounts/account2/projects/-home-deadpool/memory/`. Do not write project notes to claude-mem or Colony.
95+
96+
## Parallel-agent workflow
97+
98+
When dispatching multiple agents:
99+
- Each agent owns disjoint file paths (no cross-edits).
100+
- Pre-create shared scaffolding (e.g. `rs/Cargo.toml` workspace root) before dispatching so agents don't race on it.
101+
- Agents that need types/wire-formats from sibling crates should duplicate small helpers inline rather than depend across in-flight crates. Refactor to a shared crate after all agents land.
102+
- After agents return, run the sanity sweep: `bash -n` on every script, `cargo metadata --offline --no-deps` on the workspace.
103+
104+
## Release notes voice
105+
106+
Match the existing v1.10–v1.14 voice:
107+
- Lead with what the change does.
108+
- One paragraph per concern, no bullets unless it's a list of bug-fixes.
109+
- Cite specific commit hashes / log timestamps / observation IDs when relevant.
110+
- End with the side-effects the user will see ("janitor restarted; live preload script symlinked…").
111+
- Co-Authored-By trailer for any AI-assisted change.

Makefile

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# flashpaste — top-level make targets.
2+
#
3+
# Useful targets:
4+
# make deb build .deb package into dist/
5+
# make install run install.sh
6+
# make doctor run environment check
7+
# make uninstall remove symlinks (best-effort)
8+
# make clean remove dist/
9+
# make release-deb tag VERSION + build .deb + (manual) gh release upload
10+
11+
REPO_ROOT := $(shell pwd)
12+
VERSION ?= $(shell git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//')
13+
VERSION := $(if $(VERSION),$(VERSION),0.1.0)
14+
15+
.PHONY: deb install doctor uninstall clean release-deb help
16+
17+
help:
18+
@echo "flashpaste — make targets:"
19+
@echo " make deb build .deb (VERSION=$(VERSION))"
20+
@echo " make install run install.sh (symlinks into ~/.local/bin)"
21+
@echo " make doctor environment check"
22+
@echo " make uninstall remove symlinks"
23+
@echo " make clean delete dist/"
24+
@echo " make release-deb build .deb ready for GitHub Releases"
25+
26+
deb:
27+
VERSION=$(VERSION) bash packaging/build-deb.sh
28+
29+
install:
30+
bash install.sh
31+
32+
doctor:
33+
bash bin/flashpaste-doctor.sh
34+
35+
uninstall:
36+
@echo "Removing flashpaste symlinks from ~/.local/bin and ~/.local/share/applications"
37+
@for f in tmux-paste-dispatch.sh clipboard-set.sh clipboard-janitor.sh \
38+
get-clipboard-text.sh clip-pipeline-log.sh screenshot-to-clipboard \
39+
flashpaste-screenshot-preload.sh flashpaste-doctor.sh \
40+
flashpaste-trace.sh wl-paste; do \
41+
[ -L "$$HOME/.local/bin/$$f" ] && rm "$$HOME/.local/bin/$$f" && echo " removed ~/.local/bin/$$f" || true; \
42+
done
43+
@for f in wl-clipboard.desktop wl-paste.desktop wl-copy.desktop; do \
44+
[ -L "$$HOME/.local/share/applications/$$f" ] && rm "$$HOME/.local/share/applications/$$f" && echo " removed ~/.local/share/applications/$$f" || true; \
45+
done
46+
@[ -L "$$HOME/paste_image.sh" ] && rm "$$HOME/paste_image.sh" && echo " removed ~/paste_image.sh" || true
47+
@systemctl --user disable --now clipboard-janitor.service flashpaste-screenshot-watcher.path 2>/dev/null || true
48+
@echo "uninstall done"
49+
50+
clean:
51+
rm -rf dist/
52+
53+
release-deb: deb
54+
@echo "release-deb produced: dist/flashpaste_$(VERSION)_all.deb"
55+
@echo "Upload to GitHub Releases:"
56+
@echo " gh release create v$(VERSION) dist/flashpaste_$(VERSION)_all.deb --title 'flashpaste v$(VERSION)' --generate-notes"

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,36 @@ Total dispatch latency: **~120ms**, down from ~3 seconds and 4 paste-presses wit
6363

6464
## Quick start
6565

66-
**One line:**
66+
### Option A — Debian / Ubuntu .deb (recommended)
67+
68+
Each tagged release attaches a `.deb` to GitHub Releases. Install via apt:
69+
70+
```bash
71+
# Once a release exists:
72+
curl -fsSL -o /tmp/flashpaste.deb \
73+
https://github.com/NagyVikt/flashpaste/releases/latest/download/flashpaste_all.deb
74+
sudo apt install /tmp/flashpaste.deb
75+
76+
# Then per-user activation:
77+
systemctl --user daemon-reload
78+
systemctl --user enable --now clipboard-janitor.service
79+
systemctl --user enable --now flashpaste-screenshot-watcher.path
80+
cat /usr/share/flashpaste/examples/tmux.conf.snippet >> ~/.tmux.conf
81+
cat /usr/share/flashpaste/examples/kitty.conf.snippet >> ~/.config/kitty/kitty.conf
82+
ln -sf /usr/share/flashpaste/paste_image.sh ~/paste_image.sh
83+
flashpaste-doctor
84+
```
85+
86+
Or build the .deb yourself from a checkout:
87+
88+
```bash
89+
git clone https://github.com/NagyVikt/flashpaste.git
90+
cd flashpaste
91+
make deb # → dist/flashpaste_*_all.deb
92+
sudo apt install ./dist/flashpaste_*_all.deb
93+
```
94+
95+
### Option B — One-line dotfile install (no apt)
6796

6897
```bash
6998
curl -fsSL https://raw.githubusercontent.com/NagyVikt/flashpaste/main/bootstrap.sh | bash

0 commit comments

Comments
 (0)