Skip to content

Commit c4468bf

Browse files
add files
0 parents  commit c4468bf

19 files changed

Lines changed: 2865 additions & 0 deletions

File tree

.github/workflows/build.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: write
11+
12+
jobs:
13+
build:
14+
name: Build binaries
15+
runs-on: ubuntu-latest
16+
17+
strategy:
18+
matrix:
19+
include:
20+
- os: linux
21+
arch: amd64
22+
ext: ""
23+
- os: linux
24+
arch: arm64
25+
ext: ""
26+
- os: darwin
27+
arch: amd64
28+
ext: ""
29+
- os: darwin
30+
arch: arm64
31+
ext: ""
32+
- os: windows
33+
arch: amd64
34+
ext: ".exe"
35+
- os: windows
36+
arch: arm64
37+
ext: ".exe"
38+
39+
steps:
40+
- name: Checkout
41+
uses: actions/checkout@v4
42+
43+
- name: Setup Go
44+
uses: actions/setup-go@v5
45+
with:
46+
go-version: "1.23"
47+
48+
- name: Build
49+
env:
50+
GOOS: ${{ matrix.os }}
51+
GOARCH: ${{ matrix.arch }}
52+
CGO_ENABLED: "0"
53+
run: |
54+
mkdir -p dist
55+
go build -ldflags="-s -w" -o dist/wert-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }} .
56+
57+
- name: Upload artifact
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: wert-${{ matrix.os }}-${{ matrix.arch }}
61+
path: dist/wert-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }}
62+
63+
release:
64+
name: Create release
65+
runs-on: ubuntu-latest
66+
needs: build
67+
if: startsWith(github.ref, 'refs/tags/')
68+
69+
steps:
70+
- name: Download all artifacts
71+
uses: actions/download-artifact@v4
72+
with:
73+
path: dist
74+
merge-multiple: true
75+
76+
- name: Create release
77+
uses: softprops/action-gh-release@v2
78+
with:
79+
files: dist/*
80+
generate_release_notes: true

.gitignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# binary
2+
wert
3+
wert.exe
4+
5+
# build output
6+
dist/
7+
8+
# data file (has chat history and tasks, keep it local)
9+
wert-data.json
10+
*.json
11+
12+
# go
13+
vendor/
14+
15+
# os
16+
.DS_Store
17+
Thumbs.db
18+
19+
# editor
20+
.vscode/
21+
.idea/
22+
*.swp
23+
*.swo

CLAUDE.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# wert - codebase notes for Claude
2+
3+
## What this is
4+
5+
wert is a LAN terminal team tool. Admin runs a server, team members connect to it. Everyone gets a full screen TUI with tasks and chat. There is also an MCP server so Claude can manage tasks and send messages.
6+
7+
## Project structure
8+
9+
```
10+
wert/
11+
main.go entry point, just calls cmd.Execute()
12+
cmd/
13+
root.go cobra root command and banner
14+
serve.go admin mode, starts server then opens TUI
15+
join.go member mode, connects to server and opens TUI
16+
mcp.go starts MCP stdio server
17+
internal/
18+
protocol/
19+
messages.go all shared types: Task, Member, ChatMessage, Envelope, payloads
20+
server/
21+
store.go in-memory store with JSON file persistence
22+
hub.go websocket hub, connection management, message routing
23+
server.go http server, websocket upgrade, REST API for MCP
24+
client/
25+
client.go websocket client with Send/Recv channels
26+
tui/
27+
model.go full Bubble Tea TUI model, all rendering and input handling
28+
mcp/
29+
server.go MCP stdio server using mark3labs/mcp-go, calls REST API
30+
```
31+
32+
## How communication works
33+
34+
- Server runs on a port (default 8080)
35+
- Clients connect via WebSocket at /ws
36+
- All messages are JSON wrapped in an Envelope { type, payload }
37+
- payload is json.RawMessage so each type is decoded separately
38+
- The hub handles register, chat, task_create, task_update, task_delete
39+
- On connect the server sends a full sync payload with all tasks, members, messages
40+
- MCP server calls the REST API at /api/tasks, /api/members, /api/messages
41+
42+
## Key types
43+
44+
All in internal/protocol/messages.go
45+
46+
- Envelope - wraps every websocket message, has Type and raw Payload
47+
- Task - has ID (uuid), Title, Description, Assignee, Status, Priority, timestamps
48+
- Member - Username, Role (admin or member), Online bool
49+
- ChatMessage - ID, From, Content, Timestamp
50+
- SyncPayload - sent to new clients with full state
51+
52+
## TUI
53+
54+
Built with charmbracelet/bubbletea, bubbles, and lipgloss.
55+
56+
- Model in internal/client/tui/model.go
57+
- Two panes: Tasks (left, 40%) and Chat (right, 60%)
58+
- Tab switches active pane
59+
- Admin sees all tasks, members only see their own assigned tasks
60+
- Commands start with /
61+
- New task notification shows in status bar when a task is assigned to you
62+
- waitForMsg reads from client.Recv channel and feeds into bubbletea as ServerMsg
63+
64+
## Task IDs
65+
66+
Tasks have full UUIDs. The TUI shows the first 8 chars as the short ID.
67+
Commands like /done use the short prefix. The server does prefix matching via GetTaskByPrefix.
68+
69+
## Commands in TUI
70+
71+
Everyone: /done /wip /blocked /todo /members /help
72+
Admin only: /assign @user "title" ["desc"] [priority], /delete
73+
74+
## MCP tools
75+
76+
list_tasks, list_members, create_task, update_task, delete_task, send_message, get_dashboard
77+
All go through the REST API so no WebSocket needed for MCP.
78+
79+
## Persistence
80+
81+
Store writes to a JSON file (default wert-data.json) after every mutation.
82+
Writes happen in a goroutine so they do not block.
83+
On startup the store loads the file if it exists.
84+
85+
## Flags
86+
87+
wert serve --name --port --token --data
88+
wert join --host --name --token
89+
wert mcp --server
90+
91+
## Dependencies
92+
93+
- github.com/charmbracelet/bubbletea - TUI framework
94+
- github.com/charmbracelet/bubbles - viewport, textinput components
95+
- github.com/charmbracelet/lipgloss - styling
96+
- github.com/gorilla/websocket - websocket server and client
97+
- github.com/google/uuid - task IDs
98+
- github.com/spf13/cobra - CLI commands
99+
- github.com/mark3labs/mcp-go - MCP server
100+
101+
## Build
102+
103+
```bash
104+
go build -o wert .
105+
make cross-build # linux, darwin, windows amd64/arm64
106+
```
107+
108+
## Things to know
109+
110+
- The admin token is optional. If set, only people who pass it with --token get admin role.
111+
- If no token is set, the first person to run serve is just trusted as admin via WebSocket role.
112+
- Data file is only written on the server machine, not on clients.
113+
- The TUI uses alt screen mode so it takes over the full terminal.
114+
- Ctrl+Q or Ctrl+C to quit.

Makefile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.PHONY: build run-serve run-join tidy lint cross-build clean
2+
3+
BINARY := wert
4+
VERSION := 0.1.0
5+
6+
build: tidy
7+
go build -ldflags="-s -w" -o $(BINARY) .
8+
9+
run-serve:
10+
go run . serve --name Admin --port 8080
11+
12+
run-join:
13+
go run . join --host localhost:8080 --name Dev
14+
15+
tidy:
16+
go mod tidy
17+
18+
lint:
19+
go vet ./...
20+
21+
# Cross-platform builds
22+
cross-build: tidy
23+
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o dist/$(BINARY)-linux-amd64 .
24+
GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o dist/$(BINARY)-linux-arm64 .
25+
GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -o dist/$(BINARY)-darwin-amd64 .
26+
GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o dist/$(BINARY)-darwin-arm64 .
27+
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o dist/$(BINARY)-windows-amd64.exe .
28+
29+
clean:
30+
rm -f $(BINARY)
31+
rm -rf dist/

0 commit comments

Comments
 (0)