@moejay/wrightty 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/client.d.ts +14 -0
  2. package/dist/client.js +83 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.js +8 -0
  5. package/dist/terminal.d.ts +48 -0
  6. package/dist/terminal.js +210 -0
  7. package/dist/types.d.ts +90 -0
  8. package/dist/types.js +3 -0
  9. package/package.json +35 -15
  10. package/.github/workflows/ci.yml +0 -90
  11. package/.github/workflows/release.yml +0 -177
  12. package/Cargo.lock +0 -2662
  13. package/Cargo.toml +0 -38
  14. package/PROTOCOL.md +0 -1351
  15. package/README.md +0 -386
  16. package/agents/ceo/AGENTS.md +0 -24
  17. package/agents/ceo/HEARTBEAT.md +0 -72
  18. package/agents/ceo/SOUL.md +0 -33
  19. package/agents/ceo/TOOLS.md +0 -3
  20. package/agents/founding-engineer/AGENTS.md +0 -44
  21. package/crates/wrightty/Cargo.toml +0 -43
  22. package/crates/wrightty/src/client_cmds.rs +0 -366
  23. package/crates/wrightty/src/discover.rs +0 -78
  24. package/crates/wrightty/src/main.rs +0 -100
  25. package/crates/wrightty/src/server.rs +0 -100
  26. package/crates/wrightty/src/term.rs +0 -338
  27. package/crates/wrightty-bridge-ghostty/Cargo.toml +0 -27
  28. package/crates/wrightty-bridge-ghostty/src/ghostty.rs +0 -422
  29. package/crates/wrightty-bridge-ghostty/src/lib.rs +0 -2
  30. package/crates/wrightty-bridge-ghostty/src/main.rs +0 -146
  31. package/crates/wrightty-bridge-ghostty/src/rpc.rs +0 -307
  32. package/crates/wrightty-bridge-kitty/Cargo.toml +0 -26
  33. package/crates/wrightty-bridge-kitty/src/kitty.rs +0 -269
  34. package/crates/wrightty-bridge-kitty/src/lib.rs +0 -2
  35. package/crates/wrightty-bridge-kitty/src/main.rs +0 -124
  36. package/crates/wrightty-bridge-kitty/src/rpc.rs +0 -304
  37. package/crates/wrightty-bridge-tmux/Cargo.toml +0 -26
  38. package/crates/wrightty-bridge-tmux/src/lib.rs +0 -2
  39. package/crates/wrightty-bridge-tmux/src/main.rs +0 -119
  40. package/crates/wrightty-bridge-tmux/src/rpc.rs +0 -291
  41. package/crates/wrightty-bridge-tmux/src/tmux.rs +0 -215
  42. package/crates/wrightty-bridge-wezterm/Cargo.toml +0 -26
  43. package/crates/wrightty-bridge-wezterm/src/lib.rs +0 -2
  44. package/crates/wrightty-bridge-wezterm/src/main.rs +0 -119
  45. package/crates/wrightty-bridge-wezterm/src/rpc.rs +0 -339
  46. package/crates/wrightty-bridge-wezterm/src/wezterm.rs +0 -190
  47. package/crates/wrightty-bridge-zellij/Cargo.toml +0 -27
  48. package/crates/wrightty-bridge-zellij/src/lib.rs +0 -2
  49. package/crates/wrightty-bridge-zellij/src/main.rs +0 -125
  50. package/crates/wrightty-bridge-zellij/src/rpc.rs +0 -328
  51. package/crates/wrightty-bridge-zellij/src/zellij.rs +0 -199
  52. package/crates/wrightty-client/Cargo.toml +0 -16
  53. package/crates/wrightty-client/src/client.rs +0 -254
  54. package/crates/wrightty-client/src/lib.rs +0 -2
  55. package/crates/wrightty-core/Cargo.toml +0 -21
  56. package/crates/wrightty-core/src/input.rs +0 -212
  57. package/crates/wrightty-core/src/lib.rs +0 -4
  58. package/crates/wrightty-core/src/screen.rs +0 -325
  59. package/crates/wrightty-core/src/session.rs +0 -249
  60. package/crates/wrightty-core/src/session_manager.rs +0 -77
  61. package/crates/wrightty-protocol/Cargo.toml +0 -13
  62. package/crates/wrightty-protocol/src/error.rs +0 -8
  63. package/crates/wrightty-protocol/src/events.rs +0 -138
  64. package/crates/wrightty-protocol/src/lib.rs +0 -4
  65. package/crates/wrightty-protocol/src/methods.rs +0 -321
  66. package/crates/wrightty-protocol/src/types.rs +0 -201
  67. package/crates/wrightty-server/Cargo.toml +0 -23
  68. package/crates/wrightty-server/src/lib.rs +0 -2
  69. package/crates/wrightty-server/src/main.rs +0 -65
  70. package/crates/wrightty-server/src/rpc.rs +0 -455
  71. package/crates/wrightty-server/src/state.rs +0 -39
  72. package/examples/basic_command.py +0 -53
  73. package/examples/interactive_tui.py +0 -86
  74. package/examples/record_session.py +0 -96
  75. package/install.sh +0 -81
  76. package/sdks/node/package-lock.json +0 -85
  77. package/sdks/node/package.json +0 -44
  78. package/sdks/node/src/client.ts +0 -94
  79. package/sdks/node/src/index.ts +0 -19
  80. package/sdks/node/src/terminal.ts +0 -258
  81. package/sdks/node/src/types.ts +0 -105
  82. package/sdks/node/tsconfig.json +0 -17
  83. package/sdks/python/README.md +0 -96
  84. package/sdks/python/pyproject.toml +0 -42
  85. package/sdks/python/wrightty/__init__.py +0 -6
  86. package/sdks/python/wrightty/cli.py +0 -210
  87. package/sdks/python/wrightty/client.py +0 -136
  88. package/sdks/python/wrightty/mcp_server.py +0 -434
  89. package/sdks/python/wrightty/terminal.py +0 -333
  90. package/skills/wrightty/SKILL.md +0 -261
  91. package/src/lib.rs +0 -1
  92. package/tests/integration_test.rs +0 -618
@@ -1,338 +0,0 @@
1
- use std::process;
2
-
3
- use clap::Args;
4
-
5
- use crate::server::{self, PORT_RANGE_START, PORT_RANGE_END};
6
-
7
- #[derive(Args)]
8
- pub struct TermArgs {
9
- #[command(flatten)]
10
- mode: TermMode,
11
-
12
- /// Host to bind on
13
- #[arg(long, default_value = "127.0.0.1")]
14
- host: String,
15
-
16
- /// Port to listen on (default: auto-select)
17
- #[arg(long)]
18
- port: Option<u16>,
19
-
20
- /// Max sessions for headless mode
21
- #[arg(long, default_value_t = 64)]
22
- max_sessions: usize,
23
-
24
- /// Watchdog interval in seconds for bridges (0 to disable)
25
- #[arg(long, default_value_t = 5)]
26
- watchdog_interval: u64,
27
- }
28
-
29
- #[derive(Args)]
30
- #[group(required = true, multiple = false)]
31
- struct TermMode {
32
- /// Start the headless terminal server (virtual PTY, no GUI)
33
- #[cfg(feature = "headless")]
34
- #[arg(long)]
35
- headless: bool,
36
-
37
- /// Launch the Alacritty fork with built-in wrightty support
38
- #[arg(long)]
39
- alacritty: bool,
40
-
41
- /// Bridge to a running WezTerm instance
42
- #[cfg(feature = "bridge-wezterm")]
43
- #[arg(long)]
44
- bridge_wezterm: bool,
45
-
46
- /// Bridge to a running tmux server
47
- #[cfg(feature = "bridge-tmux")]
48
- #[arg(long)]
49
- bridge_tmux: bool,
50
-
51
- /// Bridge to a running Kitty instance
52
- #[cfg(feature = "bridge-kitty")]
53
- #[arg(long)]
54
- bridge_kitty: bool,
55
-
56
- /// Bridge to a running Zellij session
57
- #[cfg(feature = "bridge-zellij")]
58
- #[arg(long)]
59
- bridge_zellij: bool,
60
-
61
- /// Bridge to a running Ghostty instance
62
- #[cfg(feature = "bridge-ghostty")]
63
- #[arg(long)]
64
- bridge_ghostty: bool,
65
- }
66
-
67
- pub async fn run(args: TermArgs) -> anyhow::Result<()> {
68
- #[cfg(feature = "headless")]
69
- if args.mode.headless {
70
- return run_headless(args).await;
71
- }
72
-
73
- if args.mode.alacritty {
74
- return run_alacritty(args).await;
75
- }
76
-
77
- #[cfg(feature = "bridge-wezterm")]
78
- if args.mode.bridge_wezterm {
79
- return run_bridge_wezterm(args).await;
80
- }
81
-
82
- #[cfg(feature = "bridge-tmux")]
83
- if args.mode.bridge_tmux {
84
- return run_bridge_tmux(args).await;
85
- }
86
-
87
- #[cfg(feature = "bridge-kitty")]
88
- if args.mode.bridge_kitty {
89
- return run_bridge_kitty(args).await;
90
- }
91
-
92
- #[cfg(feature = "bridge-zellij")]
93
- if args.mode.bridge_zellij {
94
- return run_bridge_zellij(args).await;
95
- }
96
-
97
- #[cfg(feature = "bridge-ghostty")]
98
- if args.mode.bridge_ghostty {
99
- return run_bridge_ghostty(args).await;
100
- }
101
-
102
- anyhow::bail!("No terminal mode selected. Use --headless, --bridge-tmux, etc.")
103
- }
104
-
105
- fn resolve_port(args: &TermArgs) -> anyhow::Result<u16> {
106
- match args.port {
107
- Some(p) => Ok(p),
108
- None => server::find_available_port(&args.host, PORT_RANGE_START, PORT_RANGE_END)
109
- .ok_or_else(|| {
110
- anyhow::anyhow!("No available port in range {PORT_RANGE_START}-{PORT_RANGE_END}")
111
- }),
112
- }
113
- }
114
-
115
- // --- Headless mode ---
116
-
117
- #[cfg(feature = "headless")]
118
- async fn run_headless(args: TermArgs) -> anyhow::Result<()> {
119
- let port = resolve_port(&args)?;
120
- let state = wrightty_server::state::AppState::new(args.max_sessions);
121
- let module = wrightty_server::rpc::build_rpc_module(state)?;
122
- server::start_server(&args.host, port, "wrightty (headless)", module).await
123
- }
124
-
125
- // --- Alacritty mode ---
126
-
127
- async fn run_alacritty(args: TermArgs) -> anyhow::Result<()> {
128
- let port = args.port.unwrap_or(PORT_RANGE_START);
129
-
130
- // Find the alacritty binary — check for wrightty-patched version
131
- let alacritty = which_alacritty()?;
132
-
133
- tracing::info!("Launching {alacritty} --wrightty {port}");
134
- println!("Launching {alacritty} --wrightty {port}");
135
-
136
- let status = tokio::process::Command::new(&alacritty)
137
- .arg("--wrightty")
138
- .arg(port.to_string())
139
- .status()
140
- .await?;
141
-
142
- if !status.success() {
143
- anyhow::bail!("Alacritty exited with status {status}");
144
- }
145
-
146
- Ok(())
147
- }
148
-
149
- fn which_alacritty() -> anyhow::Result<String> {
150
- // Check PATH for alacritty
151
- let output = std::process::Command::new("which")
152
- .arg("alacritty")
153
- .output();
154
-
155
- match output {
156
- Ok(o) if o.status.success() => {
157
- let path = String::from_utf8_lossy(&o.stdout).trim().to_string();
158
- // Verify it supports --wrightty
159
- let check = std::process::Command::new(&path)
160
- .arg("--help")
161
- .output();
162
- if let Ok(help) = check {
163
- let help_text = String::from_utf8_lossy(&help.stdout);
164
- if help_text.contains("wrightty") {
165
- return Ok(path);
166
- }
167
- }
168
- anyhow::bail!(
169
- "Found alacritty at {path} but it doesn't support --wrightty.\n\
170
- Install the wrightty-patched fork:\n \
171
- git clone -b wrightty-support https://github.com/moejay/alacritty.git\n \
172
- cd alacritty && cargo install --path alacritty --features wrightty"
173
- );
174
- }
175
- _ => anyhow::bail!(
176
- "alacritty not found in PATH.\n\
177
- Install the wrightty-patched fork:\n \
178
- git clone -b wrightty-support https://github.com/moejay/alacritty.git\n \
179
- cd alacritty && cargo install --path alacritty --features wrightty"
180
- ),
181
- }
182
- }
183
-
184
- // --- Bridge modes ---
185
-
186
- #[cfg(feature = "bridge-wezterm")]
187
- async fn run_bridge_wezterm(args: TermArgs) -> anyhow::Result<()> {
188
- tracing::info!("Checking WezTerm connectivity...");
189
- match wrightty_bridge_wezterm::wezterm::health_check().await {
190
- Ok(()) => tracing::info!("WezTerm is reachable"),
191
- Err(e) => {
192
- eprintln!("error: Cannot connect to WezTerm: {e}");
193
- eprintln!();
194
- eprintln!("Make sure WezTerm is running. If using flatpak, set:");
195
- eprintln!(
196
- " WEZTERM_CMD=\"flatpak run --command=wezterm org.wezfurlong.wezterm\""
197
- );
198
- process::exit(1);
199
- }
200
- }
201
-
202
- let port = resolve_port(&args)?;
203
- let module = wrightty_bridge_wezterm::rpc::build_rpc_module()?;
204
- server::start_server_with_watchdog(
205
- &args.host,
206
- port,
207
- "wrightty (wezterm bridge)",
208
- module,
209
- args.watchdog_interval,
210
- || async { wrightty_bridge_wezterm::wezterm::health_check().await.map_err(|e| e.into()) },
211
- )
212
- .await
213
- }
214
-
215
- #[cfg(feature = "bridge-tmux")]
216
- async fn run_bridge_tmux(args: TermArgs) -> anyhow::Result<()> {
217
- tracing::info!("Checking tmux connectivity...");
218
- match wrightty_bridge_tmux::tmux::health_check().await {
219
- Ok(()) => tracing::info!("tmux is reachable"),
220
- Err(e) => {
221
- eprintln!("error: Cannot connect to tmux: {e}");
222
- eprintln!();
223
- eprintln!("Make sure a tmux server is running. Start one with:");
224
- eprintln!(" tmux new-session -d -s main");
225
- process::exit(1);
226
- }
227
- }
228
-
229
- let port = resolve_port(&args)?;
230
- let module = wrightty_bridge_tmux::rpc::build_rpc_module()?;
231
- server::start_server_with_watchdog(
232
- &args.host,
233
- port,
234
- "wrightty (tmux bridge)",
235
- module,
236
- args.watchdog_interval,
237
- || async { wrightty_bridge_tmux::tmux::health_check().await.map_err(|e| e.into()) },
238
- )
239
- .await
240
- }
241
-
242
- #[cfg(feature = "bridge-kitty")]
243
- async fn run_bridge_kitty(args: TermArgs) -> anyhow::Result<()> {
244
- tracing::info!("Checking kitty connectivity...");
245
- match wrightty_bridge_kitty::kitty::health_check().await {
246
- Ok(()) => tracing::info!("kitty is reachable"),
247
- Err(e) => {
248
- eprintln!("error: Cannot connect to kitty: {e}");
249
- eprintln!();
250
- eprintln!("Make sure kitty is running with remote control enabled.");
251
- eprintln!("Add to kitty.conf:");
252
- eprintln!(" allow_remote_control yes");
253
- eprintln!("Or launch kitty with:");
254
- eprintln!(" kitty --listen-on unix:/tmp/kitty.sock");
255
- process::exit(1);
256
- }
257
- }
258
-
259
- let port = resolve_port(&args)?;
260
- let module = wrightty_bridge_kitty::rpc::build_rpc_module()?;
261
- server::start_server_with_watchdog(
262
- &args.host,
263
- port,
264
- "wrightty (kitty bridge)",
265
- module,
266
- args.watchdog_interval,
267
- || async { wrightty_bridge_kitty::kitty::health_check().await.map_err(|e| e.into()) },
268
- )
269
- .await
270
- }
271
-
272
- #[cfg(feature = "bridge-zellij")]
273
- async fn run_bridge_zellij(args: TermArgs) -> anyhow::Result<()> {
274
- tracing::info!("Checking zellij connectivity...");
275
- match wrightty_bridge_zellij::zellij::health_check().await {
276
- Ok(()) => tracing::info!("zellij is reachable"),
277
- Err(e) => {
278
- eprintln!("error: Cannot connect to zellij: {e}");
279
- eprintln!();
280
- eprintln!("This bridge must run from within a zellij session.");
281
- eprintln!("Start zellij first:");
282
- eprintln!(" zellij");
283
- process::exit(1);
284
- }
285
- }
286
-
287
- let port = resolve_port(&args)?;
288
- let module = wrightty_bridge_zellij::rpc::build_rpc_module()?;
289
- server::start_server_with_watchdog(
290
- &args.host,
291
- port,
292
- "wrightty (zellij bridge)",
293
- module,
294
- args.watchdog_interval,
295
- || async { wrightty_bridge_zellij::zellij::health_check().await.map_err(|e| e.into()) },
296
- )
297
- .await
298
- }
299
-
300
- #[cfg(feature = "bridge-ghostty")]
301
- async fn run_bridge_ghostty(args: TermArgs) -> anyhow::Result<()> {
302
- tracing::info!("Checking Ghostty connectivity...");
303
- match wrightty_bridge_ghostty::ghostty::health_check().await {
304
- Ok(()) => tracing::info!("Ghostty IPC socket is reachable"),
305
- Err(e) => {
306
- eprintln!("error: Cannot connect to Ghostty: {e}");
307
- eprintln!();
308
- eprintln!("Make sure Ghostty is running. The bridge connects to:");
309
- eprintln!(" $XDG_RUNTIME_DIR/ghostty/sock (Linux)");
310
- eprintln!(" $TMPDIR/ghostty-<uid>.sock (macOS)");
311
- eprintln!("Override with: GHOSTTY_SOCKET=/path/to/sock");
312
- process::exit(1);
313
- }
314
- }
315
-
316
- let backend = wrightty_bridge_ghostty::ghostty::InputBackend::detect();
317
- if backend == wrightty_bridge_ghostty::ghostty::InputBackend::None {
318
- tracing::warn!(
319
- "No input backend detected. \
320
- Install xdotool (Linux/X11) or enable Accessibility (macOS) for \
321
- Input.sendText / Input.sendKeys support."
322
- );
323
- } else {
324
- tracing::info!("Input backend: {:?}", backend);
325
- }
326
-
327
- let port = resolve_port(&args)?;
328
- let module = wrightty_bridge_ghostty::rpc::build_rpc_module()?;
329
- server::start_server_with_watchdog(
330
- &args.host,
331
- port,
332
- "wrightty (ghostty bridge)",
333
- module,
334
- args.watchdog_interval,
335
- || async { wrightty_bridge_ghostty::ghostty::health_check().await.map_err(|e| e.into()) },
336
- )
337
- .await
338
- }
@@ -1,27 +0,0 @@
1
- [package]
2
- name = "wrightty-bridge-ghostty"
3
- version.workspace = true
4
- edition.workspace = true
5
- license.workspace = true
6
- authors.workspace = true
7
- repository.workspace = true
8
- homepage.workspace = true
9
- description = "Bridge that translates wrightty protocol calls into Ghostty IPC commands"
10
-
11
- [[bin]]
12
- name = "wrightty-bridge-ghostty"
13
- path = "src/main.rs"
14
-
15
- [dependencies]
16
- wrightty-protocol = { version = "0.1.0", path = "../wrightty-protocol" }
17
-
18
- jsonrpsee = { version = "0.24", features = ["server"] }
19
- tokio = { version = "1", features = ["full"] }
20
- clap = { version = "4", features = ["derive"] }
21
- tracing = "0.1"
22
- tracing-subscriber = { version = "0.3", features = ["env-filter"] }
23
- anyhow = "1"
24
- serde = { version = "1", features = ["derive"] }
25
- serde_json = "1"
26
- thiserror = "1"
27
- libc = "0.2"