This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
tgdev — a Go CLI for interacting with the Telegram MTProto API. Call any TL method, trace API calls with correlation IDs, and expose Telegram as an MCP server for LLM-driven interaction.
Module: github.com/pageton/gotg-cli (Go 1.25.0)
Critical dependency: github.com/pageton/gotg is a local replace directive pointing to /home/sadiq/Projects/go/gotg. Changes to gotg affect this project.
# Build (basic)
go build -o tgdev ./cmd/tgdev/
# Build with version info
go build -ldflags "-X main.version=$(git describe --tags --always) \
-X main.commit=$(git rev-parse --short HEAD) \
-X main.buildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
-o tgdev ./cmd/tgdev/
# Test all
go test ./...
# Test specific package
go test ./invoke/...
go test ./internal/...
# Verbose
go test -v ./...
# Lint
go vet ./...Tests exist in: invoke/, internal/ipc/, internal/mcpserver/. No tests for cmd/tgdev/, trace/, or internal/config/.
cmd/tgdev/ CLI entry point — command dispatch, flag parsing, client creation (no CLI framework)
invoke/ Core: TL method registry (reflection-based), JSON unmarshal with interface resolution, invocation
internal/config Config layering: CLI flags > TGDEV_* env vars > ~/.tgdev.json
internal/ipc Unix domain socket IPC — avoids Telegram reconnects when listener is running
internal/mcpserver MCP server exposing 6 tools (list_methods, describe_method, invoke, get_me, listener_status, config_info)
trace/ Correlation ID tracing linking updates → API calls → responses
- Standalone invoke:
tgdev invoke→ create gotg client →invoke.Invoke()→ Telegram API - IPC fast path:
tgdev listenstarts IPC server → subsequenttgdev invokecalls go through Unix socket → reuse existing Telegram connection - MCP server:
tgdev mcp→ tool handlers → IPC socket (if listener running) or standalone client - Tracing:
tgdev trace→ middleware wraps invocations with[correlationID] >> method / << method [duration]
cmd/tgdev → invoke, internal/config, internal/ipc, internal/mcpserver, trace, gotg
invoke → gotd/td (tg, tdp, bin)
internal/ipc → stdlib only (net, encoding/json)
internal/mcpserver → invoke, internal/ipc, MCP Go SDK
trace → invoke, gotd/td
No circular dependencies. internal/ipc is fully self-contained.
- TL Registry (
invoke/registry.go): Singleton (sync.Once) mapping TL schema names ↔ type IDs ↔ Goreflect.Type. Built fromtg.TypesMap()andtg.TypesConstructorMap(). All method resolution flows throughGlobalRegistry(). - JSON unmarshalling (
invoke/unmarshal.go): Case-insensitive JSON → gotd struct. Interface fields (likeInputPeer) require"_"constructor key:{"_": "inputPeerUser", "UserID": 123}. - IPC protocol (
internal/ipc/ipc.go):InvokeRequest/InvokeResponseJSON over Unix socket. Limits: 1 MiB max request, 64 concurrent connections, 30s connection deadline, 60s invoke timeout. - Command dispatch (
cmd/tgdev/main.go): Hand-rolled flag parsing andswitchstatement — no CLI framework like cobra. Command functions followcmd<Name>(args []string) errorpattern.
- CLI commands: lowercase, no hyphens (
tgdev invoke,tgdev listen) - MCP tools:
tgdev_<action>with underscores - Method names are "bare" — without
#hashsuffix (messages.sendMessage, notmessages.sendMessage#545cd15a) - Commit style: semantic prefixes (
feat:,fix:,chore:,refactor:,docs:,test:), imperative mood, ≤72 chars - Error wrapping:
fmt.Errorf("context: %w", err)
- Session strings, bot tokens, and config files are equivalent to full account access
--debugflag logs full request/response payloads including session tokens- CLI args are visible in
ps aux— preferTGDEV_*env vars for secrets - Config file (
~/.tgdev.json), SQLite DB, and IPC socket all auto-restricted to0600 - Vector responses capped at 100,000 elements to prevent OOM
resolveMethodName()is duplicated betweeninvoke/invoke.goandtrace/tracer.gointernal/ipc/ipc.gouseswriterOnlywrapper to preventjson.Encoderfrom usingConn.Read()detectSessionFormat()auto-detects session types: gotg (native JSON), Pyrogram, Telethon, GramJS, mtcute- SQLite (
--db) takes priority over session string (--session) for auth - MCP HTTP mode (
--http) is stateless — each request may create a new Telegram connection unless listener is running