Workspaces
Automated Context Switching
If you’re doing a lot, you’re probably doing a lot of context-switching.
We’re all balancing multiple projects at work, passion projects, personal finance, education etc. Being effective requires effective context switching.
Compartmentalize, remove distractions & focus.
I like to keep my work setup as minimal & clean as possible — minimising the number of tabs and applications open. If my workspace is cluttered, so are my thoughts.
Naturally, a workspace seldom stays minimal.
My simple way to automate context switching with
yaml
files.
A great context-switching workflow should have a few characteristics:
- Quick startup: minimise startup time.
- Minimize cognitive load: outsource memory where possible & trust your system.
- Able to shut down & switch tasks: Stop leaving every application open for the next day.
I need a way to effectively compartmentalise, focus deeply and easily spin up or shut down a project.
Workspaces
My solution is extremely simple — but proving so powerful it’s worth sharing. YAML
!
Let’s call each independent task (a work project, personal finance, education, or any distinct, independent task) a workspace.
- Setup
YAML
config
files that store all the metadata for a workspace. - Use
Bash
or equivalent shell scripts to launch aconfig
file.
That’s it.
Implementation
Step 1. Setting up workspace config files
Anything can be done from the terminal so any application can be added.
Here is my template yaml config
file:
firefox :
- https://<URL>.com/
chrome :
- https://<URL>.com/
papers :
- <PATH.pdf>
code :
- ~/Desktop/µπ/workspaces
finder :
- <path to folder>
excel :
- <path to excel file>
Step 2. Writing a .sh script to parse the yaml config
To keep the solution extendable, I chose to execute shell commands from a node.js
script.
// modules
const {exec} = require('child_process');
const yaml = require('js-yaml');
const fs = require('fs');
// execute shell, zsh, bash, etc using exec
function execute_shell(shellCommand) {
exec(shellCommand, (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
}
// Generate shell/terminal command to launch applications
function generate_launch_script(launch_type, launch_value) {
let launchTypes = {
'excel' : 'open -a Microsoft\\ Excel',
'chrome' : 'open -a Google\\ Chrome',
'firefox': 'open -a firefox -g',
'papers' : 'open -a Preview.app',
'cursor' : 'cursor -n',
'code' : 'cursor -n',
'finder' : 'open',
'open' : 'open',
}
return launchTypes[launch_type] + ' ' + launch_value;
}
// execute yaml files
function execute_yaml(yaml_file='workspace.yaml') {
try {
const doc = yaml.load(fs.readFileSync(yaml_file, 'utf8'));
for (const key in doc) {
if (doc.hasOwnProperty(key)) {
const value = doc[key];
// loop through each key type
for (const _index in value) {
if (value.hasOwnProperty(_index)) {
const value2 = value[_index];
// generate and exceute the shell command
let _exe_string = generate_launch_script(key, value2);
console.log('>>', _exe_string);
execute_shell(_exe_string);
}
}
}
}
} catch (e) {
console.log(e);
}
}
// ------------------------------------------------------------>>
// RUN -------------------------------------------------------->>
// load yaml file(s)
const args = process.argv.slice(2);
try {
for (const arg of args) {
// console.log('yaml file :', arg);
execute_yaml(arg);
}
} catch (e) {
console.log(e);
}
// RUN -------------------------------------------------------->>
// ------------------------------------------------------------>>
Run the script from the terminal, passing the config
files as arguments.
node index.js <config_1.yaml> <config_2.yaml>
Usage
Keep an up-to-date yaml config
file for each distinct task. The yaml keeps links to all the relevant documentation, papers, code repositories, files & whatever else a project requires.
Isolate tasks, spin up & shut down tasks easily & reduce cognitive load.