cselab 0.2.0__tar.gz
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.
- cselab-0.2.0/.gitignore +8 -0
- cselab-0.2.0/CLAUDE.md +54 -0
- cselab-0.2.0/LICENSE +21 -0
- cselab-0.2.0/PKG-INFO +467 -0
- cselab-0.2.0/README.md +446 -0
- cselab-0.2.0/README_CN.md +199 -0
- cselab-0.2.0/assets/demo-hero.gif +0 -0
- cselab-0.2.0/assets/demo-hero.mp4 +0 -0
- cselab-0.2.0/assets/demo-hero.tape +139 -0
- cselab-0.2.0/assets/demo-repl.gif +0 -0
- cselab-0.2.0/assets/demo-repl.mp4 +0 -0
- cselab-0.2.0/assets/demo-repl.tape +31 -0
- cselab-0.2.0/assets/demo-typing.gif +0 -0
- cselab-0.2.0/assets/demo-typing.mp4 +0 -0
- cselab-0.2.0/assets/demo-typing.tape +37 -0
- cselab-0.2.0/assets/fake-autotest.sh +27 -0
- cselab-0.2.0/assets/fake-repl-autotest.sh +38 -0
- cselab-0.2.0/assets/fake-repl-bye.sh +6 -0
- cselab-0.2.0/assets/fake-repl-cmd.sh +32 -0
- cselab-0.2.0/assets/fake-repl-demo.sh +148 -0
- cselab-0.2.0/assets/fake-repl-hello.sh +18 -0
- cselab-0.2.0/assets/fake-repl-startup.sh +33 -0
- cselab-0.2.0/assets/fake-repl.sh +43 -0
- cselab-0.2.0/assets/render-banner.py +23 -0
- cselab-0.2.0/docs/brand-guide.md +145 -0
- cselab-0.2.0/docs/deployment.md +140 -0
- cselab-0.2.0/docs/index.html +664 -0
- cselab-0.2.0/docs/plans/2026-03-10-repl-mode-design.md +570 -0
- cselab-0.2.0/examples/autotest.sh +19 -0
- cselab-0.2.0/examples/submit.sh +20 -0
- cselab-0.2.0/examples/watch-test.sh +14 -0
- cselab-0.2.0/install.sh +77 -0
- cselab-0.2.0/pyproject.toml +36 -0
- cselab-0.2.0/skills/AGENTS.md +57 -0
- cselab-0.2.0/skills/GEMINI.md +27 -0
- cselab-0.2.0/skills/cselab.md +191 -0
- cselab-0.2.0/src/cselab/__init__.py +1 -0
- cselab-0.2.0/src/cselab/__main__.py +10 -0
- cselab-0.2.0/src/cselab/assets/zap-default.png +0 -0
- cselab-0.2.0/src/cselab/banner.py +44 -0
- cselab-0.2.0/src/cselab/cli.py +385 -0
- cselab-0.2.0/src/cselab/config.py +112 -0
- cselab-0.2.0/src/cselab/connection.py +229 -0
- cselab-0.2.0/src/cselab/mascot.py +100 -0
- cselab-0.2.0/src/cselab/repl.py +321 -0
- cselab-0.2.0/src/cselab/theme.py +44 -0
- cselab-0.2.0/task.json +173 -0
- cselab-0.2.0/tests/__init__.py +0 -0
- cselab-0.2.0/tests/test_cli.py +286 -0
- cselab-0.2.0/tests/test_config.py +209 -0
- cselab-0.2.0/tests/test_connection.py +328 -0
- cselab-0.2.0/tests/test_mascot.py +151 -0
- cselab-0.2.0/tests/test_repl.py +207 -0
cselab-0.2.0/.gitignore
ADDED
cselab-0.2.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What This Is
|
|
6
|
+
|
|
7
|
+
cselab is a Python CLI that lets UNSW CSE students run server commands (`autotest`, `give`, etc.) from their local machine. It syncs files via rsync and executes remotely via SSH ControlMaster — no manual SSH or file copying needed.
|
|
8
|
+
|
|
9
|
+
## Build & Run
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install -e . # editable install
|
|
13
|
+
cselab --version # verify
|
|
14
|
+
cselab init --user z5555555 # setup config
|
|
15
|
+
cselab run "echo hello" # test
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Build system is hatchling. No test suite yet. No linter configured.
|
|
19
|
+
|
|
20
|
+
## Architecture
|
|
21
|
+
|
|
22
|
+
Modules in `src/cselab/`, one dependency (`prompt-toolkit>=3.0` for rich REPL UI, optional `tomli` for Python <3.11):
|
|
23
|
+
|
|
24
|
+
**`connection.py`** — SSH/rsync transport layer
|
|
25
|
+
- `connect()` starts an SSH ControlMaster (`ssh -fNM`) with ControlPersist=1800s
|
|
26
|
+
- Password auth uses a temp SSH_ASKPASS script (written to `/tmp/cselab_askpass_*`, cleaned up in finally block)
|
|
27
|
+
- `rsync_up/rsync_down` pass `-e "ssh <control-args>"` so rsync reuses the ControlMaster socket
|
|
28
|
+
- rsync respects `.gitignore` via `--filter=:- .gitignore`
|
|
29
|
+
- Socket path: `/tmp/cselab-{user}@{host}-{port}`
|
|
30
|
+
|
|
31
|
+
**`config.py`** — TOML config at `~/.config/cselab/config.toml`
|
|
32
|
+
- `Config` dataclass holds all settings
|
|
33
|
+
- `remote_workspace()` generates a deterministic remote path from MD5 of the local cwd: `~/.cselab/workspaces/{dirname}-{hash12}`
|
|
34
|
+
- Supports password auth (SSH_ASKPASS) and key auth (`-i`)
|
|
35
|
+
|
|
36
|
+
**`cli.py`** — 9 subcommands, all follow the same pattern: `load_config() → connect() → do_work()`
|
|
37
|
+
- `run` is the main command: connect → rsync_up → ssh_exec (3-step with timing output)
|
|
38
|
+
- `watch` uses fswatch on macOS (preferred) with polling fallback
|
|
39
|
+
- Lazy imports (`from cselab.connection import ...` inside functions) keep `--help` fast
|
|
40
|
+
|
|
41
|
+
## Key Design Decisions
|
|
42
|
+
|
|
43
|
+
- **SSH ControlMaster over libssh2**: persistent socket means 0ms reconnect on subsequent commands
|
|
44
|
+
- **rsync over SFTP**: delta compression, .gitignore support, `--delete` keeps remote clean
|
|
45
|
+
- **SSH_ASKPASS trick**: password auth without interactive TTY — creates temp script, sets `SSH_ASKPASS_REQUIRE=force`, connects with `stdin=DEVNULL`
|
|
46
|
+
- **No dependencies**: runs on stock Python 3.10+ with system ssh/rsync (pre-installed on macOS/Linux)
|
|
47
|
+
|
|
48
|
+
## Remote File Layout
|
|
49
|
+
|
|
50
|
+
On the CSE server, cselab creates:
|
|
51
|
+
```
|
|
52
|
+
~/.cselab/workspaces/{dirname}-{md5_12char}/
|
|
53
|
+
```
|
|
54
|
+
Each local directory maps to a unique remote workspace. `cselab clean` removes all of them.
|
cselab-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Steven Cai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
cselab-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cselab
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Run UNSW CSE commands locally with fast sync and interactive support
|
|
5
|
+
Project-URL: Repository, https://github.com/Genius-Cai/cselab
|
|
6
|
+
Project-URL: Homepage, https://github.com/Genius-Cai/cselab
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/Genius-Cai/cselab/issues
|
|
8
|
+
Author: Steven Cai
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: autotest,cse,ssh,unsw
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Education
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: prompt-toolkit>=3.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
<div align="center">
|
|
23
|
+
|
|
24
|
+
# cselab
|
|
25
|
+
|
|
26
|
+
**Run UNSW CSE commands from your local machine — fast, reliable, interactive.**
|
|
27
|
+
|
|
28
|
+
<p>
|
|
29
|
+
<img src="https://img.shields.io/pypi/v/cselab?color=blue&label=PyPI" alt="PyPI version" />
|
|
30
|
+
<img src="https://img.shields.io/badge/Python-3.10+-blue?logo=python&logoColor=white" alt="Python 3.10+" />
|
|
31
|
+
<img src="https://img.shields.io/badge/License-MIT-yellow" alt="MIT License" />
|
|
32
|
+
<img src="https://img.shields.io/badge/SSH-ControlMaster-orange" alt="SSH ControlMaster" />
|
|
33
|
+
<img src="https://img.shields.io/badge/Sync-rsync-green" alt="rsync" />
|
|
34
|
+
</p>
|
|
35
|
+
|
|
36
|
+
English | [简体中文](README_CN.md)
|
|
37
|
+
|
|
38
|
+
[Features](#why-cselab) · [Comparison](#comparison-with-other-approaches) · [Quick Start](#quick-start) · [For CSE Staff](#for-cse-staff--administrators) · [AI Integration](#ai-platform-integration)
|
|
39
|
+
|
|
40
|
+
<!-- TODO: Replace with actual GIF recording (use `vhs` or OBS) -->
|
|
41
|
+
<!-- <p><img src="assets/demo.gif" alt="cselab demo — autotest in one command" width="700" /></p> -->
|
|
42
|
+
<pre>
|
|
43
|
+
$ cselab run "1521 autotest"
|
|
44
|
+
[1/3] Connecting to cse.unsw.edu.au... OK (0.0s)
|
|
45
|
+
[2/3] Syncing files... OK (0.2s)
|
|
46
|
+
[3/3] Running: 1521 autotest
|
|
47
|
+
========================================
|
|
48
|
+
Test 1 - ... passed
|
|
49
|
+
Test 2 - ... passed
|
|
50
|
+
All tests passed!
|
|
51
|
+
========================================
|
|
52
|
+
Exit: OK
|
|
53
|
+
</pre>
|
|
54
|
+
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Why cselab?
|
|
60
|
+
|
|
61
|
+
UNSW CSE students must run `autotest`, `give`, and other course commands on the CSE server (`cse.unsw.edu.au`). The typical workflow is:
|
|
62
|
+
|
|
63
|
+
1. SSH into CSE server
|
|
64
|
+
2. Edit code there (or manually copy files back and forth)
|
|
65
|
+
3. Run the command
|
|
66
|
+
4. Repeat
|
|
67
|
+
|
|
68
|
+
This is painful. You lose your local editor, extensions, and tools. Or you waste time copying files manually.
|
|
69
|
+
|
|
70
|
+
**cselab lets you write code locally and run CSE commands as if you were on the server.** One command syncs your files and executes remotely — your local VS Code / Vim stays untouched.
|
|
71
|
+
|
|
72
|
+
## How It Works
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Local Machine (your laptop) CSE Server
|
|
76
|
+
┌─────────────────────────┐ ┌──────────────────────┐
|
|
77
|
+
│ │ 1. SSH │ │
|
|
78
|
+
│ ~/COMP1521/lab01/ │──────────────│ ControlMaster │
|
|
79
|
+
│ hello.c │ (once) │ (persistent conn) │
|
|
80
|
+
│ Makefile │ │ │
|
|
81
|
+
│ │ 2. rsync │ ~/.cselab/ │
|
|
82
|
+
│ │──────────────│ workspaces/ │
|
|
83
|
+
│ │ (delta) │ lab01-a3f2/ │
|
|
84
|
+
│ │ │ hello.c │
|
|
85
|
+
│ │ 3. ssh │ Makefile │
|
|
86
|
+
│ │──────────────│ │
|
|
87
|
+
│ │ (exec) │ $ 1521 autotest │
|
|
88
|
+
│ │ │ │
|
|
89
|
+
│ Terminal: │ 4. output │ │
|
|
90
|
+
│ ✅ All tests passed │◄─────────────│ │
|
|
91
|
+
│ │ (stream) │ │
|
|
92
|
+
└─────────────────────────┘ └──────────────────────┘
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Step-by-step flow
|
|
96
|
+
|
|
97
|
+
When you run `cselab run "1521 autotest"`:
|
|
98
|
+
|
|
99
|
+
1. **Connect** — Establishes an SSH ControlMaster connection (reused across all subsequent commands, password entered only once)
|
|
100
|
+
2. **Sync** — `rsync` uploads your local directory to the server, using delta compression (only changed bytes are transferred)
|
|
101
|
+
3. **Execute** — Runs your command on the server in the synced directory, with full interactive terminal support
|
|
102
|
+
4. **Stream** — Output streams back to your terminal in real-time, exit code is preserved
|
|
103
|
+
|
|
104
|
+
Subsequent runs reuse the SSH connection (0ms reconnect) and rsync only transfers changes (sub-second for typical edits).
|
|
105
|
+
|
|
106
|
+
## Installation
|
|
107
|
+
|
|
108
|
+
**Requirements:** Python 3.10+, `rsync`, `ssh` (pre-installed on macOS and most Linux)
|
|
109
|
+
|
|
110
|
+
**One-line install (recommended):**
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
curl -sSL https://raw.githubusercontent.com/Genius-Cai/cselab/master/install.sh | bash
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Or via pip:**
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
pip install git+https://github.com/Genius-Cai/cselab.git
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Or clone and install locally:**
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
git clone https://github.com/Genius-Cai/cselab.git
|
|
126
|
+
cd cselab
|
|
127
|
+
pip install .
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Quick Start
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
# 1. One-time setup
|
|
134
|
+
cselab init
|
|
135
|
+
# Enter your zID and password when prompted
|
|
136
|
+
|
|
137
|
+
# 2. Go to your assignment directory
|
|
138
|
+
cd ~/COMP1521/lab01
|
|
139
|
+
|
|
140
|
+
# 3. Run any CSE command
|
|
141
|
+
cselab run "1521 autotest"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
That's it. Your local files are synced and the command runs on CSE.
|
|
145
|
+
|
|
146
|
+
## Interactive Mode
|
|
147
|
+
|
|
148
|
+
Just type `cselab` with no arguments to enter the REPL:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
$ cd ~/COMP1521/lab01
|
|
152
|
+
$ cselab
|
|
153
|
+
|
|
154
|
+
cselab v0.2.0
|
|
155
|
+
z5502277@cse.unsw.edu.au
|
|
156
|
+
|
|
157
|
+
Type any CSE command. Ctrl+C to exit.
|
|
158
|
+
|
|
159
|
+
Connecting... OK
|
|
160
|
+
|
|
161
|
+
⚡ 1521 autotest collatz
|
|
162
|
+
[sync] OK (0.1s)
|
|
163
|
+
5 tests passed 0 tests failed
|
|
164
|
+
|
|
165
|
+
⚡ give cs1521 lab01 collatz.c
|
|
166
|
+
[sync] OK (0.1s)
|
|
167
|
+
Submission received.
|
|
168
|
+
|
|
169
|
+
⚡ exit
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Same commands as the CSE server — zero learning curve.
|
|
173
|
+
|
|
174
|
+
The headless mode still works for scripts:
|
|
175
|
+
```bash
|
|
176
|
+
cselab run "1521 autotest collatz"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Usage
|
|
180
|
+
|
|
181
|
+
### `cselab run <command>`
|
|
182
|
+
|
|
183
|
+
Sync files + run command on CSE server.
|
|
184
|
+
|
|
185
|
+
```sh
|
|
186
|
+
cselab run "1521 autotest" # sync + autotest
|
|
187
|
+
cselab run "2521 autotest" # works with any course
|
|
188
|
+
cselab run "give cs1521 lab01 hello.c" # submit assignment
|
|
189
|
+
cselab run --no-sync "1521 classrun -sturec" # skip sync for non-file commands
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Example output:
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
[1/3] Connecting to cse.unsw.edu.au... OK (0.0s)
|
|
196
|
+
[2/3] Syncing files... OK (0.2s)
|
|
197
|
+
[3/3] Running: 1521 autotest
|
|
198
|
+
========================================
|
|
199
|
+
Test 1 - ... passed
|
|
200
|
+
Test 2 - ... passed
|
|
201
|
+
All tests passed!
|
|
202
|
+
========================================
|
|
203
|
+
Exit: OK
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### `cselab pull`
|
|
207
|
+
|
|
208
|
+
Download files from the server back to your local machine. Useful when the server generates output files.
|
|
209
|
+
|
|
210
|
+
```sh
|
|
211
|
+
cselab run "make" # compile on server, generates binary
|
|
212
|
+
cselab pull # pull generated files back
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### `cselab watch <command>`
|
|
216
|
+
|
|
217
|
+
Watch for local file changes and auto-run a command. Save a file, autotest runs automatically.
|
|
218
|
+
|
|
219
|
+
```sh
|
|
220
|
+
cselab watch "1521 autotest"
|
|
221
|
+
# Now edit hello.c in your editor, save, and autotest runs automatically
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### `cselab ssh`
|
|
225
|
+
|
|
226
|
+
Open an interactive SSH session directly in your synced workspace directory.
|
|
227
|
+
|
|
228
|
+
```sh
|
|
229
|
+
cselab ssh
|
|
230
|
+
# You're now in a shell on CSE, in the same directory as your local files
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### `cselab sync`
|
|
234
|
+
|
|
235
|
+
Sync files without running a command.
|
|
236
|
+
|
|
237
|
+
```sh
|
|
238
|
+
cselab sync
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Other commands
|
|
242
|
+
|
|
243
|
+
```sh
|
|
244
|
+
cselab config # show config file location and contents
|
|
245
|
+
cselab clean # remove all remote workspace directories
|
|
246
|
+
cselab disconnect # close SSH connection
|
|
247
|
+
cselab --help # full help
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Configuration
|
|
251
|
+
|
|
252
|
+
Config file: `~/.config/cselab/config.toml`
|
|
253
|
+
|
|
254
|
+
```toml
|
|
255
|
+
[server]
|
|
256
|
+
host = "cse.unsw.edu.au"
|
|
257
|
+
port = 22
|
|
258
|
+
user = "z5555555" # your zID
|
|
259
|
+
|
|
260
|
+
[auth]
|
|
261
|
+
method = "password"
|
|
262
|
+
password = "your_password" # optional, will prompt if missing
|
|
263
|
+
|
|
264
|
+
# Alternative: SSH key auth (no password needed)
|
|
265
|
+
# [auth]
|
|
266
|
+
# method = "key"
|
|
267
|
+
# key_path = "~/.ssh/id_rsa"
|
|
268
|
+
|
|
269
|
+
[sync]
|
|
270
|
+
# Directories excluded from sync (in addition to .gitignore)
|
|
271
|
+
exclude = [".git", "__pycache__", "node_modules", ".venv", "target"]
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
cselab respects `.gitignore` and `.ignore` files — directories like `node_modules/` and `__pycache__/` are automatically excluded from sync.
|
|
275
|
+
|
|
276
|
+
## How cselab Helps Students
|
|
277
|
+
|
|
278
|
+
### The problem
|
|
279
|
+
|
|
280
|
+
CSE students face a daily friction loop:
|
|
281
|
+
|
|
282
|
+
- **SSH + remote editing** — You lose VS Code, your extensions, copilot, your muscle memory. Editing in `vim` over SSH is a skill barrier unrelated to the course material.
|
|
283
|
+
- **Manual file copy** — `scp` files back and forth before every autotest. Easy to forget, easy to test stale code.
|
|
284
|
+
- **Slow iteration** — Each cycle (edit → copy → test) takes 30-60 seconds. Over a 10-week term, this adds up to hours of wasted time.
|
|
285
|
+
- **No local tooling** — Can't use local debuggers, linters, or formatters on code that must run on CSE.
|
|
286
|
+
|
|
287
|
+
### What cselab enables
|
|
288
|
+
|
|
289
|
+
- **Stay in your editor.** Write code in VS Code, Cursor, or any local editor with full language support, extensions, and AI assistance.
|
|
290
|
+
- **One-command testing.** `cselab run "1521 autotest"` replaces the entire SSH-copy-run cycle.
|
|
291
|
+
- **Sub-second iteration.** After the first run, syncing a single file change takes ~0.1s. Edit, save, test — near-instant feedback.
|
|
292
|
+
- **Watch mode.** `cselab watch "1521 autotest"` makes it fully automatic — save file, see test results.
|
|
293
|
+
- **Focus on learning.** Remove the tooling friction so students can focus on the actual course content: C, data structures, algorithms — not SSH workflows.
|
|
294
|
+
|
|
295
|
+
## Comparison with Other Approaches
|
|
296
|
+
|
|
297
|
+
Every UNSW CSE student needs to run `autotest` and `give` on the CSE server. Here's how the available options stack up:
|
|
298
|
+
|
|
299
|
+
| | VLAB | SSH FS | Remote-SSH | cserun | **cselab** |
|
|
300
|
+
|---|:---:|:---:|:---:|:---:|:---:|
|
|
301
|
+
| **Use local editor** (VS Code, Cursor, Vim) | No | Partial | Yes | Yes | **Yes** |
|
|
302
|
+
| **Run autotest/give** | Yes | Needs separate terminal | Yes | Yes | **Yes** |
|
|
303
|
+
| **Server load** | High | Low | **Very High** | Low | **Near Zero** |
|
|
304
|
+
| **Reliability** | Disconnects after 2h idle | Good | Process reapers kill it | 45% (libssh2 failures) | **100%** |
|
|
305
|
+
| **Watch mode** (auto-test on save) | No | No | No | No | **Yes** |
|
|
306
|
+
| **Install difficulty** | None (browser) | Medium (FUSE) | Medium (VS Code ext) | Hard (Rust toolchain) | **Easy** (`pip install`) |
|
|
307
|
+
| **AI editor support** (Cursor, Windsurf) | No | No | No | No | **Yes** |
|
|
308
|
+
| **Offline editing** | No | No | No | No | **Yes** |
|
|
309
|
+
| **Pull files from server** | N/A | Automatic | Automatic | No | **Yes** |
|
|
310
|
+
| **Interactive SSH** | Yes (full desktop) | No | Yes | No | **Yes** |
|
|
311
|
+
|
|
312
|
+
> **Key insight:** VS Code Remote-SSH gives the best editing experience, but CSE [explicitly discourages it](https://taggi.cse.unsw.edu.au/FAQ/VS_Code_Remote-SSH/) because it spawns Node.js processes that consume ~200-500MB RAM per student. CSE runs reaper scripts to kill these processes, and students risk account restrictions.
|
|
313
|
+
>
|
|
314
|
+
> cselab gives you the same local editing workflow with **zero server-side footprint**.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Comparison with cserun
|
|
319
|
+
|
|
320
|
+
This project was inspired by [cserun](https://github.com/xxxbrian/cserun) by [@xxxbrian](https://github.com/xxxbrian), which pioneered the idea of running CSE commands from a local machine. cserun demonstrated the concept and solved a real pain point for UNSW students.
|
|
321
|
+
|
|
322
|
+
We chose to build a new project rather than contribute to cserun because the improvements we wanted required fundamental architectural changes — a different language, different SSH transport, and different sync mechanism. These aren't incremental fixes but a different technical foundation.
|
|
323
|
+
|
|
324
|
+
### Architectural differences
|
|
325
|
+
|
|
326
|
+
| | cselab | cserun |
|
|
327
|
+
|---|---|---|
|
|
328
|
+
| **Language** | Python | Rust |
|
|
329
|
+
| **SSH library** | Native OpenSSH (via subprocess) | libssh2 (C binding via `ssh2` crate) |
|
|
330
|
+
| **Connection** | SSH ControlMaster (persistent, reused) | Fresh TCP+SSH per invocation |
|
|
331
|
+
| **File sync** | `rsync` (delta compression, incremental) | SFTP (full file upload, one-by-one) |
|
|
332
|
+
| **Interactive I/O** | Full PTY via `ssh -tt` | Non-blocking poll loop, no stdin |
|
|
333
|
+
| **Dependencies** | Python 3.10+ (pre-installed on macOS) | Rust toolchain + C compiler (for libssh2) |
|
|
334
|
+
|
|
335
|
+
### Performance (real measurements, 50 files x 10KB)
|
|
336
|
+
|
|
337
|
+
| Metric | cselab | cserun | Improvement |
|
|
338
|
+
|--------|--------|--------|-------------|
|
|
339
|
+
| Command latency (warm) | **0.15s** | 0.73s | 4.9x faster |
|
|
340
|
+
| File sync (50 files) | **0.30s** | 2.13s | 7.1x faster |
|
|
341
|
+
| End-to-end (sync + compile + run) | **0.42s** | 2.14s | 5.0x faster |
|
|
342
|
+
| Cold connect | **0.48s** | 0.73s | 1.5x faster |
|
|
343
|
+
|
|
344
|
+
### Reliability (20 rapid sequential invocations)
|
|
345
|
+
|
|
346
|
+
| | cselab | cserun |
|
|
347
|
+
|---|---|---|
|
|
348
|
+
| Success rate | **20/20 (100%)** | 9/20 (45%) |
|
|
349
|
+
| Failure mode | — | `libssh2: Failed getting banner` |
|
|
350
|
+
|
|
351
|
+
The reliability issue stems from libssh2's SSH handshake implementation, which intermittently fails under rapid reconnection. cselab avoids this entirely by maintaining a persistent connection via ControlMaster.
|
|
352
|
+
|
|
353
|
+
### Feature comparison
|
|
354
|
+
|
|
355
|
+
| Feature | cselab | cserun |
|
|
356
|
+
|---------|--------|--------|
|
|
357
|
+
| Run commands | yes | yes |
|
|
358
|
+
| File sync | yes (rsync) | yes (SFTP) |
|
|
359
|
+
| .gitignore support | yes | yes |
|
|
360
|
+
| Skip sync (`--no-sync`) | yes | yes |
|
|
361
|
+
| Environment variables | planned | yes |
|
|
362
|
+
| **Pull files from server** | **yes** | no |
|
|
363
|
+
| **Interactive commands** | **yes** | no |
|
|
364
|
+
| **Watch mode** | **yes** | no |
|
|
365
|
+
| **Interactive SSH session** | **yes** | no |
|
|
366
|
+
| **Connection reuse** | **yes** | no |
|
|
367
|
+
| **Workspace cleanup** | **yes** | no |
|
|
368
|
+
|
|
369
|
+
### Acknowledgment
|
|
370
|
+
|
|
371
|
+
Thank you to [@xxxbrian](https://github.com/xxxbrian) for creating cserun and proving that local-to-CSE command execution is both possible and valuable. cselab builds on that vision with a different technical approach.
|
|
372
|
+
|
|
373
|
+
## AI Platform Integration
|
|
374
|
+
|
|
375
|
+
cselab ships with skill files for popular AI coding assistants — let AI help you run CSE commands:
|
|
376
|
+
|
|
377
|
+
| Platform | File | Install |
|
|
378
|
+
|----------|------|---------|
|
|
379
|
+
| **Claude Code** | `skills/cselab.md` | `cp skills/cselab.md ~/.claude/commands/` |
|
|
380
|
+
| **Codex CLI** | `skills/AGENTS.md` | `cp skills/AGENTS.md ./AGENTS.md` |
|
|
381
|
+
| **Gemini CLI** | `skills/GEMINI.md` | `cp skills/GEMINI.md ./GEMINI.md` |
|
|
382
|
+
| **Claude.ai** | `skills/cselab.md` | Upload to Project Knowledge |
|
|
383
|
+
| **Cursor** | `skills/cselab.md` | `cp skills/cselab.md .cursor/rules/` |
|
|
384
|
+
| **Windsurf** | `skills/cselab.md` | `cp skills/cselab.md .windsurfrules/` |
|
|
385
|
+
|
|
386
|
+
See [docs/deployment.md](docs/deployment.md) for detailed setup instructions.
|
|
387
|
+
|
|
388
|
+
## For CSE Staff / Administrators
|
|
389
|
+
|
|
390
|
+
If you manage CSE infrastructure or coordinate a course, here's why cselab benefits the server environment.
|
|
391
|
+
|
|
392
|
+
### The Problem: Remote-SSH is Straining Login Servers
|
|
393
|
+
|
|
394
|
+
Students increasingly use VS Code Remote-SSH for local editing convenience. But each Remote-SSH session spawns a persistent Node.js server on the login machines, causing:
|
|
395
|
+
|
|
396
|
+
- **200-500MB RAM per student** from VS Code Server + file watchers + language indexing
|
|
397
|
+
- Persistent connections that last entire coding sessions (hours)
|
|
398
|
+
- CSE has had to deploy **reaper scripts**, dedicate **vscode.cse/vscode2.cse** servers, and impose **SSH rate limits** (20/min firewall ban)
|
|
399
|
+
|
|
400
|
+
Students use Remote-SSH because the alternatives (VLAB, SSH FS) don't provide a satisfactory local editing experience. They need a better option.
|
|
401
|
+
|
|
402
|
+
### How cselab Differs
|
|
403
|
+
|
|
404
|
+
```
|
|
405
|
+
Server resource comparison (100 concurrent students):
|
|
406
|
+
|
|
407
|
+
VS Code Remote-SSH: Node.js resident process + file watchers + indexing
|
|
408
|
+
~200-500MB RAM/student → 20-50GB total, persistent
|
|
409
|
+
|
|
410
|
+
SSH FS (SSHFS): SFTP connection held open
|
|
411
|
+
~50MB/student → ~5GB total, persistent
|
|
412
|
+
|
|
413
|
+
cselab: rsync (0.3s) + SSH exec (<10s) + disconnect
|
|
414
|
+
~0MB idle → near 0GB total, burst only
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
cselab uses **rsync** for file sync (0.3s delta transfer) and **short-lived SSH** for command execution. There are no background processes, no persistent connections, and no Node.js. After each command completes, the server resources are fully released.
|
|
418
|
+
|
|
419
|
+
### Benefits for CSE
|
|
420
|
+
|
|
421
|
+
1. **Zero server load at idle** -- no Node.js, no persistent connections
|
|
422
|
+
2. **Fewer SSH connections** -- SSH ControlMaster multiplexes over one socket, won't trigger rate limits
|
|
423
|
+
3. **Open source (MIT)** -- fully auditable, no server-side components
|
|
424
|
+
4. **Reduces support tickets** -- students stop asking about SSH disconnects and VLAB lag
|
|
425
|
+
5. **Compatible with all courses** -- autotest, give, classrun all work unchanged
|
|
426
|
+
|
|
427
|
+
### Recommendation
|
|
428
|
+
|
|
429
|
+
If you'd like to evaluate cselab, the source is at [github.com/Genius-Cai/cselab](https://github.com/Genius-Cai/cselab). It requires only standard `ssh` and `rsync` on the student's machine and makes no modifications to the server environment.
|
|
430
|
+
|
|
431
|
+
We'd welcome the opportunity to have cselab reviewed for inclusion in the [CSE Home Computing Guide](https://taggi.cse.unsw.edu.au/FAQ/Home_computing/).
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Project Structure
|
|
436
|
+
|
|
437
|
+
```
|
|
438
|
+
cselab/
|
|
439
|
+
├── src/cselab/
|
|
440
|
+
│ ├── cli.py # CLI entry point
|
|
441
|
+
│ ├── config.py # Config management
|
|
442
|
+
│ └── connection.py # SSH/rsync transport
|
|
443
|
+
├── skills/
|
|
444
|
+
│ ├── cselab.md # Claude Code skill
|
|
445
|
+
│ ├── AGENTS.md # Codex CLI instructions
|
|
446
|
+
│ └── GEMINI.md # Gemini CLI context
|
|
447
|
+
├── docs/
|
|
448
|
+
│ └── deployment.md # Multi-platform deployment guide
|
|
449
|
+
├── examples/
|
|
450
|
+
│ ├── autotest.sh # Run autotest
|
|
451
|
+
│ ├── submit.sh # Submit via give
|
|
452
|
+
│ └── watch-test.sh # Watch mode demo
|
|
453
|
+
├── install.sh # One-line installer
|
|
454
|
+
├── README.md # English docs
|
|
455
|
+
├── README_CN.md # 中文文档
|
|
456
|
+
└── LICENSE # MIT
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
## Author
|
|
460
|
+
|
|
461
|
+
**Steven Cai** ([@Genius-Cai](https://github.com/Genius-Cai))
|
|
462
|
+
|
|
463
|
+
UNSW Sydney — Bachelor of Commerce / Computer Science
|
|
464
|
+
|
|
465
|
+
## License
|
|
466
|
+
|
|
467
|
+
[MIT](LICENSE)
|