Skip to content

Commit f8c4c2c

Browse files
committed
Allow per-session GABS servers
1 parent 103db74 commit f8c4c2c

8 files changed

Lines changed: 25 additions & 274 deletions

File tree

AGENTS.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,18 @@ GABS creates configuration in the user's home directory:
755755

756756
- **All platforms**: `~/.gabs/{gameId}/bridge.json`
757757

758+
### Local Redeploy Preference
759+
760+
When redeploying GABS locally for this workspace:
761+
762+
- Keep the binary name as `gabs`
763+
- Overwrite the existing installed binary in place
764+
- Do not create backup copies like `gabs.bak-*`
765+
- Do not switch the MCP config to alternate binary filenames
766+
767+
This repository expects a stable binary path for local MCP clients, especially
768+
Codex sessions that launch `gabs server` directly.
769+
758770
### Environment Variables
759771

760772
- `GABS_LAUNCH_ID`: Unique session identifier

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ command = "/absolute/path/to/gabs"
133133
args = ["server"]
134134
```
135135

136+
Each Codex or Claude session starts its own stdio GABS process. That process is
137+
session-local; GABS only coordinates ownership at the game level so two live AI
138+
sessions do not both launch or attach to the same game by accident.
139+
136140
**Generic MCP client:**
137141

138142
Point your client at the `gabs` binary with the `server` subcommand:

cmd/gabs/main.go

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package main
99
import (
1010
"bufio"
1111
"context"
12-
"errors"
1312
"flag"
1413
"fmt"
1514
"os"
@@ -226,43 +225,14 @@ Once the server is running, use MCP tools to manage games:
226225
// === Server Command ===
227226

228227
func runServer(ctx context.Context, log util.Logger, opts options) int {
229-
// Enforce a single global GABS server process per user.
230-
lockPaths, err := config.NewConfigPaths("")
231-
if err != nil {
232-
log.Errorw("failed to resolve server lock path", "error", err)
233-
return 1
234-
}
235-
if err := lockPaths.EnsureBaseDir(); err != nil {
236-
log.Errorw("failed to create server lock directory", "path", lockPaths.GetBaseDir(), "error", err)
237-
return 1
238-
}
239-
240-
serverLock, err := config.AcquireServerLock(lockPaths.GetServerLockPath())
241-
if err != nil {
242-
var runningErr *config.ServerAlreadyRunningError
243-
if errors.As(err, &runningErr) {
244-
log.Errorw("another GABS server is already running",
245-
"pid", runningErr.Info.PID,
246-
"startedAt", runningErr.Info.StartedAt,
247-
"lockPath", runningErr.Path)
248-
} else {
249-
log.Errorw("failed to acquire server singleton lock", "lockPath", lockPaths.GetServerLockPath(), "error", err)
250-
}
251-
return 1
252-
}
253-
defer func() {
254-
if err := serverLock.Release(); err != nil {
255-
log.Warnw("failed to release server lock", "lockPath", lockPaths.GetServerLockPath(), "error", err)
256-
}
257-
}()
258-
259228
// Load games configuration
260229
gamesConfig, err := config.LoadGamesConfigFromDir(opts.configDir)
261230
if err != nil {
262231
log.Errorw("failed to load games config", "error", err)
263232
return 1
264233
}
265234

235+
log.Debugw("starting per-session GABS server", "transport", opts.transport, "configDir", opts.configDir)
266236
log.Infow("loaded games configuration", "gameCount", len(gamesConfig.Games))
267237

268238
// Create MCP server with game management tools

docs/AI_CLIENT_SETUP.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ args = ["server"]
109109

110110
On Windows, use the full path to `gabs.exe`.
111111

112+
Each live Codex session will start its own stdio GABS process. That is
113+
intentional. GABS coordinates shared ownership per game, not with a machine-wide
114+
`gabs server` singleton.
115+
112116
### Generic MCP Clients
113117

114118
If your MCP client supports stdio servers, the essential configuration is:

docs/INTEGRATION.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ command = "/path/to/gabs"
9898
args = ["server"]
9999
```
100100

101+
Each live Codex session runs its own stdio GABS process. Cross-session
102+
coordination happens only when those sessions interact with the same configured
103+
game.
104+
101105
### Custom AI Tools
102106

103107
Here's a Python example using an MCP client:

internal/config/paths.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,6 @@ func (cp *ConfigPaths) GetMainConfigPath() string {
3939
return filepath.Join(cp.baseDir, "config.json")
4040
}
4141

42-
// GetServerLockPath returns the path to the global server lock file.
43-
func (cp *ConfigPaths) GetServerLockPath() string {
44-
return filepath.Join(cp.baseDir, "server.lock")
45-
}
46-
4742
// GetGameDir returns the directory path for a specific game's configuration files
4843
func (cp *ConfigPaths) GetGameDir(gameID string) string {
4944
return filepath.Join(cp.baseDir, gameID)

internal/config/server_lock.go

Lines changed: 0 additions & 169 deletions
This file was deleted.

internal/config/server_lock_test.go

Lines changed: 0 additions & 69 deletions
This file was deleted.

0 commit comments

Comments
 (0)