Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI

on:
push:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true

- name: Test
run: make test

- name: Build
run: make build

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true

- name: Format check
run: make fmt && git diff --exit-code -- '*.go'

- name: Vet
run: make vet

- name: Lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.10
args: --timeout 5m
34 changes: 34 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: PR

on:
pull_request:
branches: [main]

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true

- name: Format check
run: make fmt && git diff --exit-code -- '*.go'

- name: Vet
run: make vet

- name: Lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.10
args: --timeout 5m

- name: Test
run: make test

- name: Build
run: make build
30 changes: 30 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Release

on:
push:
tags:
- "v*"

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true

- name: Test
run: make test

- name: Release
uses: goreleaser/goreleaser-action@v6
with:
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ go.work
.DS_Store
Thumbs.db
.worktrees
bin/
9 changes: 9 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: "2"

linters:
default: none
enable:
- govet
- staticcheck
- unused
- ineffassign
55 changes: 55 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
version: 2
project_name: diary

before:
hooks:
- go mod tidy

builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm64

archives:
- formats: [tar.gz]
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else }}{{ .Arch }}{{ end }}

checksum:
name_template: checksums.txt

changelog:
sort: asc
filters:
exclude:
- "^docs"
- "^test"
- "^chore"

brews:
- name: diary
commit_author:
name: tta-lab-bot
email: bot@tta-lab.com
commit_msg_template: "feat(formula): update {{ .ProjectName }} to {{ .Tag }}"
directory: Formula
homepage: "https://github.com/tta-lab/diary-cli"
description: "Encrypted multi-user diary CLI for humans and agents"
license: "MIT"
install: |
bin.install "diary"
test: |
system "#{bin}/diary", "version"
repository:
owner: tta-lab
name: homebrew-ttal
branch: main
token: "{{ .Env.HOMEBREW_TAP_TOKEN }}"
29 changes: 26 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
.PHONY: help gifs append-gif edit-gif clean install-vhs install-ttyd
.PHONY: help build test fmt vet lint ci gifs append-gif edit-gif clean install-vhs install-ttyd

help:
@echo "diary-cli GIF generation"
@echo "diary-cli"
@echo ""
@echo "Usage:"
@echo " make build Build the diary binary"
@echo " make test Run tests"
@echo " make fmt Format code"
@echo " make vet Run go vet"
@echo " make lint Run golangci-lint"
@echo " make ci Run fmt + vet + lint + test + build"
@echo " make gifs Generate all demo GIFs"
@echo " make append-gif Generate append workflow GIF"
@echo " make edit-gif Generate edit workflow GIF"
@echo " make install-vhs Install VHS (required for GIF generation)"
@echo " make install-ttyd Install ttyd (required by VHS)"
@echo " make clean Remove generated GIFs"
@echo " make clean Remove generated artifacts"

build:
go build -o bin/diary ./cmd/diary

test:
go test ./...

fmt:
gofmt -w .

vet:
go vet ./...

lint:
golangci-lint run

ci: fmt vet lint test build

# Check if VHS is installed
check-vhs:
Expand Down
29 changes: 25 additions & 4 deletions cmd/diary/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
Expand All @@ -11,6 +12,8 @@ import (
"time"

tea "github.com/charmbracelet/bubbletea"
"golang.org/x/term"

"github.com/neilguion/diary-cli/internal/crypto"
"github.com/neilguion/diary-cli/internal/editor"
"github.com/neilguion/diary-cli/internal/git"
Expand Down Expand Up @@ -99,7 +102,7 @@ Usage:
Commands:
(none) Read latest entry in interactive viewer (default)
read [date] [-t] Show diary entry (plain text by default, -t for interactive viewer)
append "text" Append text to today's entry (auto-creates if needed)
append ["text"] Append text to today's entry (reads from stdin if no text given)
edit [date] Open entry in $EDITOR (today if no date, or specific date)
list List all available diary entries for user
search ["term"] Search across all diary entries (interactive if no term)
Expand Down Expand Up @@ -220,17 +223,35 @@ func handleRead(user string, args []string) {
os.Exit(1)
}

fmt.Print(string(plaintext))
now := time.Now()
fmt.Printf("Now: %s\n", now.Format("2006-01-02 (Mon) 15:04 -07:00"))
fmt.Printf("Entry: %s\n\n", date)
fmt.Print(strings.TrimLeft(string(plaintext), "\n"))
}
}

func handleAppend(user string, args []string) {
if len(args) < 1 {
var text string
if len(args) >= 1 {
text = args[0]
// If stdin is also a pipe, warn that it's being ignored
if !term.IsTerminal(int(os.Stdin.Fd())) {
fmt.Fprintln(os.Stderr, "Warning: ignoring stdin — using positional argument")
}
} else if !term.IsTerminal(int(os.Stdin.Fd())) {
// No positional arg: read from piped stdin
data, err := io.ReadAll(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: failed to read stdin: %v\n", err)
os.Exit(1)
}
text = strings.TrimRight(string(data), "\n\r")
}
if text == "" {
fmt.Fprintln(os.Stderr, "Error: text required for append command")
fmt.Fprintln(os.Stderr, "Usage: diary <user> append \"text\"")
os.Exit(1)
}
text := args[0]

// Get today's date
today := time.Now().Format("2006-01-02")
Expand Down
Loading
Loading