 			throw error
 		}
 	}
-	
+
+	/// implementation of Decodable
+	public init(from decoder: Decoder) throws {
+		let container = try decoder.container(keyedBy: CodingKeys.self)
+		if let params = try? container.decode(Open.self, forKey: .open) {
+			self = .open(params)
+		} else if let params = try? container.decode(Help.self, forKey: .help) {
+			self = .help(params)
+		} else if let params = try? container.decode(VariableValue.self, forKey: .variableValue) {
+			self = .variableValue(params)
+		} else if let params = try? container.decode(VariableUpdate.self, forKey: .variableUpdate) {
+			self = .variableUpdate(params)
+		} else if let params = try? container.decode(Error.self, forKey: .error) {
+			self = .error(params)
+		} else if let params = try? container.decode(Results.self, forKey: .results) {
+			self = .results(params)
+		} else if let params = try? container.decode(ShowOutput.self, forKey: .showOutput) {
+			self = .showOutput(params)
+		} else if let params = try? container.decode(ExecComplete.self, forKey: .execComplete) {
+			self = .execComplete(params)
+		} else if let params = try? container.decode(EnvCreated.self, forKey: .envCreated) {
+			self = .envCreated(params)
+		} else if let params = try? container.decode(PreviewInited.self, forKey: .previewInited) {
+			self = .previewInited(params)
+		} else if let params = try? container.decode(PreviewUpdated.self, forKey: .previewUpdated) {
+			self = .previewUpdated(params)
+		} else {
+			logger.warning("failed to parse a SessionCommand")
+			throw SessionError.decoding
+		}
+	}
+	
+	/// implementation of Encodable
+	public func encode(to encoder: Encoder) throws {
+		var container = encoder.container(keyedBy: CodingKeys.self)
+		switch self {
+			case .open(let params):
+				try container.encode(params, forKey: .open)
+			case .help(let params):
+				try container.encode(params, forKey: .help)
+			case .variableValue(let params):
+				try container.encode(params, forKey: .variableValue)
+			case .variableUpdate(let params):
+				try container.encode(params, forKey: .variableUpdate)
+			case .error(let params):
+				try container.encode(params, forKey: .error)
+			case .results(let params):
+				try container.encode(params, forKey: .results)
+			case .showOutput(let params):
+				try container.encode(params, forKey: .showOutput)
+			case .execComplete(let params):
+				try container.encode(params, forKey: .execComplete)
+			case .envCreated(let params):
+				try container.encode(params, forKey: .envCreated)
+			case .previewInited(let params):
+				try container.encode(params, forKey: .previewInited)
+			case .previewUpdated(let params):
+				try container.encode(params, forKey: .previewUpdated);
+		}
+	}
+
 	/// response from an open message
 	public struct Open: Codable, Hashable {
 		/// was the connection opened

		}
	}

	public struct ExecComplete: Decodable, Hashable {
		let expectShowOutput: Bool
		let queryId: Int
		let startTime: String?

fileprivate let logger = Logger(label: "rc2.ComputeResponse")

/// responses that can be returned by the comppute engine
public enum ComputeResponse: Equatable, Codable {

	case open(Open)
	case help(Help)
