Workspace Tooling and Environments
This page documents how the full CSL project is operated as a multi-repo workspace across three real environments:
- Android / Termux
- Omarchy Linux (Arch-based)
- Windows 11 via VS Code + PowerShell, with bash available when needed
The goal is not just command reference. The goal is to explain the operating model of the project.
Workspace shape
The project is not a monorepo. It is a directory of sibling repos:
csl/
├── llc-course
├── llc-companion
├── llc-companion-pdf
├── llc-wiki
├── c-systems-lab-exercises
└── scriptsKey ownership boundaries:
llc-courseowns the web app and the canonicalcontent/exercise treellc-companionowns the local execution helperllc-companion-pdfowns the Typst product and solution-side testsllc-wikiowns durable reference documentationcsl-toolsowns cross-repo operator tooling
The top-level csl/ folder is a local workspace, not the authoritative home
for the automation itself. The durable automation lives in source-csl-tools.
Why workspace tooling exists
Without cross-repo tooling, routine work becomes repetitive and error-prone:
- pull five repos manually
- remember which repo owns which build or export step
- remember which environments can install Node deps directly
- keep a local internal mirror in sync by hand on Termux
csl-tools exists to make those flows explicit and repeatable.
Command model
The current operator-facing commands are:
csl-updatecsl-update --setupcsl-setupcsl-statuscsl-logcsl-buildcsl-push
High-level meaning:
csl-update: refresh repo contentscsl-setup: refresh the local runnable environmentcsl-update --setup: do both in sequence
Environment 1 — Android / Termux
Why this environment is special
On Android, shared storage is convenient but technically hostile to Node-based tooling.
The shared-storage path:
/storage/emulated/0/code/cslis good for:
- file visibility
- editing from Android apps
- keeping the workspace in one familiar place
But it is bad for:
node_modules/.binsymlink creation- execution of native binaries such as
esbuild
That is why the project uses an internal mirror:
$HOME/code/cslStandard Termux workflow
Source of truth:
/storage/emulated/0/code/csl
Runnable/internal workspace:
$HOME/code/csl
Standard commands:
csl-update --setup
csl-int
cd llc-course
npm run devWhat happens:
- shared-storage repos are pulled
- internal mirror is rebuilt from shared storage
- dependency install runs inside the internal mirror
- active development commands run from the internal tree
Important consequence
The internal mirror is disposable. It is not the source of truth.
If something goes wrong in the internal tree, it can be recreated from the shared-storage workspace.
Environment 2 — Omarchy Linux (Arch-based)
Main difference from Termux
On Omarchy/Arch Linux, the filesystem constraints that force the Termux mirror pattern generally do not exist.
That means:
- Node installs can usually run directly in the workspace
- native binaries are not blocked by Android shared-storage rules
- the mirror is usually unnecessary
Recommended Linux workflow
Operate directly in the workspace repos:
csl-update
cd /path/to/csl/llc-course
npm install
npm run devUse csl-update --setup only if you intentionally want the same mirrored model
as Termux. The tooling supports it, but Linux does not require it by default.
Main value of tooling on Linux
The Linux value is less about filesystem workaround and more about:
- cross-repo updates
- cross-repo logs/status
- repeatable build/export flows
Environment 3 — Windows 11 via VS Code + PowerShell
Operating model
Windows is supported through PowerShell wrappers in csl-tools/bin-win/.
PowerShell is the user-facing shell, but bash is still allowed and expected when a project’s real build scripts are bash.
That is the correct compromise:
- PowerShell for Windows-native command ergonomics
- bash where the project already has stable bash automation
Practical implication
Do not force a full PowerShell rewrite of every repo-local script just to make the command surface look uniform. The wrapper layer can be PowerShell while the actual build step still calls bash where appropriate.
Typical Windows flow
csl-update
csl-status
csl-build -DistWhen the underlying step is bash-based, the wrapper delegates to bash.
Where to look for what
Use the right documentation layer:
- Wiki: durable cross-repo technical documentation
csl-toolsREADME: command usage and flags- individual repo READMEs: repo-local setup and architecture
This split is intentional. The wiki explains the system; command READMEs explain the interface.
Source-of-truth map
Cross-repo tooling:
Canonical exercises and web content:
PDF/source-side solution validation:
Exercise/export distribution model:
Current standard operator flows
Refresh everything on Termux
csl-update --setupRefresh repo contents only
csl-updateRebuild only the internal Termux mirror and installs
csl-setupCheck cross-repo state
csl-status
csl-logDesign rule
Cross-repo automation should be versioned in csl-tools, not left as ad hoc
scripts in the unversioned workspace root.
That rule exists to avoid exactly the failure mode the project already hit: useful local automation being lost, diverging, or blocking pulls because it lived in the wrong place.