Skip to content

Commit b730237

Browse files
committed
chore: document development modes in README.md
1 parent 594bfc5 commit b730237

6 files changed

Lines changed: 147 additions & 129 deletions

File tree

CONTRIBUTING.md

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Thanks for your interest in contributing. This is a small Go project; keeping ch
1010

1111
```bash
1212
go build -o intertui .
13-
./intertui init --server HOST --user YOU --pass SECRET # or --offline
13+
./intertui init --server HOST --user YOU --pass SECRET
1414
./intertui
1515
```
1616

@@ -33,28 +33,76 @@ Check open issues before starting large changes. For substantial features, open
3333

3434
## Development notes
3535

36-
### Package layout
36+
### Project layout
37+
38+
```
39+
intertui/
40+
main.go
41+
cmd/
42+
dev/ # offline mock server + TUI (not installed)
43+
probe/ # low-level protocol debugger
44+
internal/
45+
constants/ # DEFAULT_PORT
46+
config/ # CLI flags and config file
47+
intercept/ # protocol client and mock server
48+
ui/ # Bubble Tea TUI
49+
```
3750

3851
| Package | Role |
3952
|---------|------|
4053
| `internal/constants` | Default server host and port |
4154
| `internal/config` | CLI flags and environment variables |
4255
| `internal/intercept` | Network client, protocol parsing, mock server |
4356
| `internal/ui` | Bubble Tea model, view, input handling |
44-
| `cmd/probe` | Manual protocol debugging (not required for normal use) |
57+
| `cmd/dev` | Offline development entrypoint |
58+
| `cmd/probe` | Manual protocol debugging |
4559

4660
### Defaults and configuration
4761

4862
Put shared default values in `internal/constants/constants.go` (`DEFAULT_PORT`, etc.). Do not duplicate magic strings in config or client code.
4963

64+
Connection settings (`server`, `port`, transport mode) live in `~/.intertui/config.yaml` and are written by `intertui init`. The main binary only exposes `--user` and `--pass` on the command line; everything else is config-file driven.
65+
5066
### Offline development
5167

52-
Use `--offline` or the mock server in `internal/intercept/mock.go` when you do not have access to a live game server:
68+
Run the dev entrypoint when you do not have access to a live game server:
5369

5470
```bash
55-
go run . --offline
71+
go run ./cmd/dev
5672
```
5773

74+
This starts the built-in mock WebSocket server in `internal/intercept/mock.go` and launches the TUI against it. It is not part of the installed `intertui` binary.
75+
76+
### Alternate transports and servers
77+
78+
The live game server uses raw TCP on port `13373` by default. WebSocket mode and custom hosts are for development and testing.
79+
80+
Set transport options in config via `intertui init`:
81+
82+
```bash
83+
# Custom host or port
84+
./intertui init --server example.com --port 13373 --user YOU --pass SECRET --force
85+
86+
# WebSocket (alternate API; not what the live server uses by default)
87+
./intertui init --ws --user YOU --pass SECRET --server HOST --force
88+
89+
# Full WebSocket URL
90+
./intertui init --url wss://example.com/ws --user YOU --pass SECRET --force
91+
```
92+
93+
`init` also accepts `--tls` (with WebSocket) and `--token` (API token login for WebSocket mode).
94+
95+
### Protocol
96+
97+
JSON request/response protocol, informed by [intercept.py](https://github.com/Martmists-GH/intercept.py):
98+
99+
- **TCP (default):** one JSON object per line on port `13373``auth` (login) → `connect` (token)
100+
- **WebSocket:** JSON frames — `auth``systems``connect` (system)
101+
102+
Inbound events include `chat`, `broadcast`, `command`, `connect`, and others. Commands are sent as `{"request":"command","cmd":"..."}`.
103+
104+
WebSocket URLs are derived as `ws://host:port/ws` unless `url` is set in config.
105+
58106
### Live server tests
59107

60108
Live tests are behind the `live` build tag and require real credentials:

README.md

Lines changed: 10 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ This project is unofficial and not affiliated with the game or its authors.
88

99
## Features
1010

11-
- Fullscreen UI in the style of Claude Code: log fills the screen with input and status pinned at the bottom; mouse wheel scrolls, and click-drag selects text in-app, copying it to your clipboard on release
11+
- Fullscreen terminal UI with a scrollable log, input line, and status bar
12+
- Mouse: wheel scroll, click to copy a word, drag to select text (copied on release)
1213
- ANSI colors for in-game `¬` color codes
13-
- TCP transport (default) with optional WebSocket mode
14-
- Username/password login (TCP) or extended WebSocket login flows
15-
- Offline mode with a built-in mock server for development
14+
- Tab completion for commands, subcommands, and filesystem paths
15+
- Session logging to `~/.intertui/logs/`
1616

1717
## Requirements
1818

@@ -42,17 +42,8 @@ intertui init --server HOST --user YOU --pass SECRET
4242
# Connect using config file
4343
intertui
4444

45-
# Or pass flags (override config)
46-
intertui --server HOST --user YOU --pass SECRET
47-
48-
# Offline mock server (no network)
49-
./intertui --offline
50-
51-
# WebSocket (alternate API; not what the live server uses by default)
52-
./intertui --ws --user YOU --pass SECRET
53-
54-
# Custom host
55-
./intertui --server example.com --port 13373 --user YOU --pass SECRET
45+
# Override credentials for this session
46+
intertui --user YOU --pass SECRET
5647
```
5748

5849
### Flags
@@ -61,26 +52,13 @@ intertui --server HOST --user YOU --pass SECRET
6152
|------|-------------|
6253
| `--user` | Intercept username |
6354
| `--pass` | Intercept password |
64-
| `--token` | API token (WebSocket mode only) |
65-
| `--server` | Game server host |
66-
| `--port` | Server port (default: `13373`) |
67-
| `--ws` | Use WebSocket instead of TCP |
68-
| `--tls` | Use `wss://` instead of `ws://` (with `--ws`) |
69-
| `--url` | Full WebSocket URL (overrides `--server` / `--port`) |
70-
| `--offline` | Built-in mock WebSocket server |
7155

7256
### Environment variables
7357

7458
| Variable | Flag |
7559
|----------|------|
7660
| `INTERCEPT_USER` | `--user` |
7761
| `INTERCEPT_PASS` | `--pass` |
78-
| `INTERCEPT_TOKEN` | `--token` |
79-
| `INTERCEPT_SERVER` | `--server` |
80-
| `INTERCEPT_PORT` | `--port` |
81-
| `INTERCEPT_WS` | `--ws` (`1` or `true`) |
82-
| `INTERCEPT_TLS` | `--tls` (`1` or `true`) |
83-
| `INTERCEPT_URL` | `--url` |
8462

8563
### Keyboard shortcuts
8664

@@ -103,44 +81,22 @@ intertui --server HOST --user YOU --pass SECRET
10381

10482
### Tab completion
10583

106-
Press `Tab` to complete command names, subcommands, and filesystem paths. The first completion may query the server silently in the background; press `Tab` again if nothing happens immediately. Ambiguous matches are listed in the log.
84+
Press `Tab` to complete command names, subcommands, and filesystem paths. The first completion may query the server in the background; press `Tab` again if nothing appears right away. Ambiguous matches are listed in the log.
10785

108-
The command list learned from `cmds` is cached for the rest of the session. Directory listings used for path completion are cleared when you run commands that change the filesystem (`mkdir`, `rm`, and similar) or when you reconnect.
86+
Command names from `cmds` are cached for the session. Directory listings are cleared when you run commands that change the filesystem (`mkdir`, `rm`, and similar) or when you reconnect.
10987

110-
**Reconnecting:** Press `r` after a disconnect to reconnect. File-completion caches are reset, but the cached command vocabulary is kept on purpose — it reflects your account’s command set, not remote host state. If you reconnect to a **different** server or account (for example by changing flags and pressing `r`), tab completion may show stale commands until you restart `intertui`.
88+
If you reconnect to a different server or account, restart `intertui` to refresh the command cache.
11189

11290
## Configuration
11391

114-
Default settings live in `~/.intertui/config.yaml` (create with `intertui init`). Flags and environment variables override the file. Default port is in [`internal/constants/constants.go`](internal/constants/constants.go) (`DEFAULT_PORT`). WebSocket URLs are derived as `ws://host:port/ws` unless you pass `--url`.
92+
Default settings live in `~/.intertui/config.yaml` (create with `intertui init`). `--user` and `--pass` override the file for a single session.
11593

11694
Session logs are written to `~/.intertui/logs/latest.log`. On each launch, the previous `latest.log` is renamed to a timestamped file in the same directory (for example `2025-06-10T12-34-56.log`).
11795

11896
## Development
11997

12098
See [CONTRIBUTING.md](CONTRIBUTING.md).
12199

122-
## Protocol
123-
124-
JSON request/response protocol, informed by [intercept.py](https://github.com/Martmists-GH/intercept.py):
125-
126-
- **TCP (default):** one JSON object per line on port `13373``auth` (login) → `connect` (token)
127-
- **WebSocket:** JSON frames — `auth``systems``connect` (system)
128-
129-
Inbound events include `chat`, `broadcast`, `command`, `connect`, and others. Commands are sent as `{"request":"command","cmd":"..."}`.
130-
131-
## Project layout
132-
133-
```
134-
intertui/
135-
main.go
136-
internal/
137-
constants/ # DEFAULT_PORT
138-
config/ # flags and env
139-
intercept/ # protocol client
140-
ui/ # Bubble Tea TUI
141-
cmd/probe/ # optional protocol debugger
142-
```
143-
144100
## License
145101

146102
GNU General Public License v3.0 or later. See [LICENSE](LICENSE).

cmd/dev/main.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Dev entrypoint: built-in mock server for offline UI and protocol work.
2+
// Not installed with `go install`; run with `go run ./cmd/dev`.
3+
package main
4+
5+
import (
6+
"fmt"
7+
"os"
8+
9+
tea "charm.land/bubbletea/v2"
10+
11+
"intertui/internal/config"
12+
"intertui/internal/intercept"
13+
filelog "intertui/internal/log"
14+
"intertui/internal/ui"
15+
)
16+
17+
func main() {
18+
srv, url := intercept.StartMockServer()
19+
defer srv.Close()
20+
21+
cfg := config.Config{
22+
URL: url,
23+
WS: true,
24+
User: "offline",
25+
Pass: "offline",
26+
}
27+
28+
if err := run(cfg); err != nil {
29+
fmt.Fprintln(os.Stderr, err)
30+
os.Exit(1)
31+
}
32+
}
33+
34+
func run(cfg config.Config) error {
35+
if err := filelog.Open(); err != nil {
36+
fmt.Fprintf(os.Stderr, "warning: file logging disabled: %v\n", err)
37+
} else {
38+
defer filelog.Close()
39+
}
40+
41+
logPath, _ := filelog.Path()
42+
filelog.Info("start target=%s ws=%v user=%s log=%s", cfg.DialDescription(), cfg.WS, cfg.User, logPath)
43+
44+
p := tea.NewProgram(ui.New(cfg), tea.WithFPS(30))
45+
if _, err := p.Run(); err != nil {
46+
return err
47+
}
48+
return nil
49+
}

internal/config/config.go

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@ import (
1414

1515
// Config holds runtime options for intertui.
1616
type Config struct {
17-
User string
18-
Pass string
19-
Token string
20-
Offline bool
17+
User string
18+
Pass string
19+
Token string
2120

2221
Server string
2322
Port int
@@ -57,59 +56,41 @@ func RootCmd(run func(Config) error) *serpent.Command {
5756
Description: "Intercept password.",
5857
},
5958
{
60-
Name: "token",
61-
Flag: "token",
62-
Env: "INTERCEPT_TOKEN",
63-
YAML: "token",
64-
Value: serpent.StringOf(&cfg.Token),
65-
Description: "Intercept API token (WebSocket mode only).",
59+
Name: "server",
60+
YAML: "server",
61+
Hidden: true,
62+
Value: serpent.StringOf(&cfg.Server),
6663
},
6764
{
68-
Name: "server",
69-
Flag: "server",
70-
Env: "INTERCEPT_SERVER",
71-
YAML: "server",
72-
Value: serpent.StringOf(&cfg.Server),
73-
Description: "Game server host or IP.",
65+
Name: "port",
66+
YAML: "port",
67+
Hidden: true,
68+
Default: "0",
69+
Value: serpent.Int64Of(&port),
7470
},
7571
{
76-
Name: "port",
77-
Flag: "port",
78-
Env: "INTERCEPT_PORT",
79-
YAML: "port",
80-
Default: "0",
81-
Value: serpent.Int64Of(&port),
82-
Description: fmt.Sprintf("Server port (default %d).", constants.DEFAULT_PORT),
72+
Name: "token",
73+
YAML: "token",
74+
Hidden: true,
75+
Value: serpent.StringOf(&cfg.Token),
8376
},
8477
{
85-
Name: "ws",
86-
Flag: "ws",
87-
Env: "INTERCEPT_WS",
88-
YAML: "ws",
89-
Value: serpent.BoolOf(&cfg.WS),
90-
Description: fmt.Sprintf("Use WebSocket transport (default: raw TCP on port %d).", constants.DEFAULT_PORT),
78+
Name: "ws",
79+
YAML: "ws",
80+
Hidden: true,
81+
Value: serpent.BoolOf(&cfg.WS),
9182
},
9283
{
93-
Name: "tls",
94-
Flag: "tls",
95-
Env: "INTERCEPT_TLS",
96-
YAML: "tls",
97-
Value: serpent.BoolOf(&cfg.TLS),
98-
Description: "Use wss:// instead of ws:// (with --ws).",
84+
Name: "tls",
85+
YAML: "tls",
86+
Hidden: true,
87+
Value: serpent.BoolOf(&cfg.TLS),
9988
},
10089
{
101-
Name: "url",
102-
Flag: "url",
103-
Env: "INTERCEPT_URL",
104-
YAML: "url",
105-
Value: serpent.StringOf(&cfg.URL),
106-
Description: "Full endpoint URL (overrides --server; ws:// or wss:// enables WebSocket).",
107-
},
108-
{
109-
Name: "offline",
110-
Flag: "offline",
111-
Value: serpent.BoolOf(&cfg.Offline),
112-
Description: "Use built-in mock server.",
90+
Name: "url",
91+
YAML: "url",
92+
Hidden: true,
93+
Value: serpent.StringOf(&cfg.URL),
11394
},
11495
}
11596

@@ -172,9 +153,6 @@ func (c Config) ResolveURL() string {
172153

173154
// DialDescription returns a human-readable target for status output.
174155
func (c Config) DialDescription() string {
175-
if c.Offline {
176-
return "offline mock server"
177-
}
178156
if c.WS || strings.HasPrefix(c.URL, "ws") {
179157
return c.ResolveURL()
180158
}

internal/ui/model.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,12 @@ func New(cfg config.Config) Model {
8282
styles.Cursor.Blink = false
8383
ti.SetStyles(styles)
8484

85-
m := Model{
85+
return Model{
8686
cfg: cfg,
8787
input: ti,
8888
state: stateConnecting,
8989
completion: newCompletionState(),
9090
}
91-
if cfg.Offline && !cfg.HasCreds() {
92-
m.cfg.User = "offline"
93-
m.cfg.Pass = "offline"
94-
}
95-
return m
9691
}
9792

9893
func (m Model) Init() tea.Cmd {

0 commit comments

Comments
 (0)