Index: tools/langserver/src/json.hpp
===================================================================
--- tools/langserver/src/json.hpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/langserver/src/json.hpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <nlohmann/json.hpp>
+
+namespace json {
+      auto parse(const std::vector<char> & buff) {
+            return nlohmann::json::parse(buff.begin(), buff.end());
+      }
+
+      using obj = nlohmann::json;
+}
Index: tools/langserver/src/log.cpp
===================================================================
--- tools/langserver/src/log.cpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/langserver/src/log.cpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,24 @@
+#include "log.hpp"
+
+#include <iostream>
+#include <fstream>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+int g_argc;
+char** g_argv;
+
+static std::ofstream create() {
+      struct passwd *pw = getpwuid(getuid());
+      const char *homedir = pw->pw_dir;
+
+      std::string target = std::string(homedir) + "/.cfa-ls.log";
+      return std::ofstream{ target };
+}
+
+std::ostream & log() {
+      static std::ofstream log = create();
+      return log;
+}
Index: tools/langserver/src/log.hpp
===================================================================
--- tools/langserver/src/log.hpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/langserver/src/log.hpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <iostream>
+
+extern std::ostream & log();
+extern int g_argc;
+extern char** g_argv;
Index: tools/langserver/src/main.cpp
===================================================================
--- tools/langserver/src/main.cpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/langserver/src/main.cpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,89 @@
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "json.hpp"
+#include "log.hpp"
+
+static void request(std::vector<char> & buf);
+
+namespace server {
+	json::obj init(const json::obj & ) {
+		return {
+			{ "capabilities", json::obj::array() },
+			{ "serverInfo", {
+				{ "name", "Cforall Language Server" },
+				{ "version", "0.1" }
+			}}
+		};
+	}
+}
+
+std::unordered_map<std::string, json::obj (*)( const json::obj & )> actions {
+	{ "initialize", server::init }
+};
+
+int main(int argc, char * argv[]) {
+	g_argc = argc;
+	g_argv = argv;
+
+	log() << "Language Server called with args:" << std::endl;
+	for(int i = 0; i < argc; i++) {
+		log() << "\t- " << argv[i] << std::endl;
+	}
+
+	std::vector<char> buffer;
+	while(true) {
+		request(buffer);
+		if(buffer.size() == 0) break;
+
+		auto top = json::parse(buffer);
+
+		auto action = actions.find( top["method"] );
+		if(action != actions.end()) {
+			log() << "Executing request '" << action->first << "'" << std::endl;
+			json::obj response = {
+				{"id", top["id"] }
+			};
+
+			try{
+				response["result"] = action->second( top["params"] );
+			} catch( const json::obj & error ) {
+				response["result"] = "";
+				response["error"] = error;
+			}
+			log() << "Responding with : " << response.dump(4) << std::endl;
+			std::cout << response.dump() << std::endl;
+		}
+		else {
+			log() << "WARNING no action for method '" << top["method"].dump(4) << "'" << std::endl;
+		}
+	}
+
+	log() << "Language Server closing after end of file" << std::endl;
+
+	return 0;
+}
+
+static void request(std::vector<char> & buffer) {
+	std::string lenstr;
+	std::getline( std::cin, lenstr );
+	if(std::cin.eof()) { buffer.clear(); return; };
+
+	if (lenstr.rfind("Content-Length: ", 0) != 0) {
+		log() << "Expected content length bug got '" << lenstr << "' instead " << std::endl;
+		std::exit(EXIT_FAILURE);
+	}
+
+	size_t idx = sizeof("Content-Length:");
+	size_t end;
+	size_t len = std::stoul(lenstr.substr(idx), &end);
+	if(lenstr.length() != (idx + end + 1)) {
+		log() << "Inconsistent size of integer in content length: " << lenstr.length() << " vs " << (idx + end) << std::endl;
+	}
+
+	log() << "New request of " << len << " bytes" << std::endl;
+	buffer.resize( len + 2 );
+	std::cin.read(buffer.data(), buffer.size());
+	return;
+}
Index: tools/vscode/uwaterloo.cforall-0.1.0/client/main.js
===================================================================
--- tools/vscode/uwaterloo.cforall-0.1.0/client/main.js	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/vscode/uwaterloo.cforall-0.1.0/client/main.js	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,55 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+// The module 'vscode' contains the VS Code extensibility API
+// Import the module and reference it with the alias vscode in your code below
+const path = require("path");
+const vscode = require("vscode");
+
+
+const vscode_lc = require('vscode-languageclient');
+
+let client = {}
+
+// this method is called when your extension is activated
+// your extension is activated the very first time the command is executed
+function activate(context) {
+	vscode.window.showInformationMessage('Cforall Extension Starting');
+
+	// The debug options for the server
+	// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
+	let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
+
+	// If the extension is launched in debug mode then the debug server options are used
+	// Otherwise the run options are used
+	let serverOptions = {
+		run: { command: 'cfa-ls', transport: vscode_lc.TransportKind.ipc },
+		debug: {
+			command: 'cfa-ls',
+			transport: vscode_lc.TransportKind.ipc,
+			options: debugOptions
+		}
+	};
+
+	// Options to control the language client
+	let clientOptions = {
+		// Register the server for plain text documents
+		documentSelector: [{ scheme: 'file', language: 'cforall' }]
+	};
+
+	// Create the language client and start the client.
+	client = new vscode_lc.LanguageClient(
+		'CforallServer',
+		'Cforall Language Server',
+		serverOptions,
+		clientOptions
+	);
+
+	// Start the client. This will also launch the server
+	client.start();
+
+}
+exports.activate = activate;
+
+// this method is called when your extension is deactivated
+function deactivate() { }
+exports.deactivate = deactivate;
Index: tools/vscode/uwaterloo.cforall-0.1.0/package.json
===================================================================
--- tools/vscode/uwaterloo.cforall-0.1.0/package.json	(revision 0f3d8448d8eb105df4d36abcceea99d8bb8e872f)
+++ tools/vscode/uwaterloo.cforall-0.1.0/package.json	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -15,4 +15,8 @@
 		"Other"
 	],
+	"activationEvents": [
+		"onLanguage:cforall"
+	],
+	"main": "./client/main.js",
 	"contributes": {
 		"languages": [
@@ -40,4 +44,22 @@
 			}
 		]
+	},
+	"configuration": {
+		"type": "object",
+		"title": "Example configuration",
+		"properties": {
+			"languageServerExample.maxNumberOfProblems": {
+				"scope": "resource",
+				"type": "number",
+				"default": 100,
+				"description": "Controls the maximum number of problems produced by the server."
+			}
+		}
+	},
+	"dependencies": {
+		"vscode-languageclient": "^4.1.4"
+	},
+	"devDependencies": {
+		"vscode-languageclient": "^4.1.4"
 	}
 }
Index: tools/vscode/uwaterloo.cforall-0.1.0/server/out/server
===================================================================
--- tools/vscode/uwaterloo.cforall-0.1.0/server/out/server	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/vscode/uwaterloo.cforall-0.1.0/server/out/server	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,1 @@
+../../../ls
