Commit 4af2491c authored by Michael Murtaugh's avatar Michael Murtaugh
Browse files

initial social shell notes made in 2014 with Anne Laforet

(The machine stops)
* We (Anne + I) need to propose an alternative network.
** File collection of different kinds of materials
** Shared Keywording system
** Recipes reusable
* Can the architecture allow speculative / experimental
Speculative / Parody / Space
Our project provides documentation service
In the end, we want a working documentation...
Ideally, we want a document written
Systeem as writing spac
1984 Surveillance => 2014 Render service
We propose a "service" oriented system with all the problematics of Web 2.0
* Central,
* Truth, Authenticity...
* We watch, we make reports,
* We share the surveillance
* We invite users to hack the system
* Do we hide power relations, made explicit
(Specialist, Technical decisions, )
Hackable system
* Hot spot software ?
Surveillance systems
* Usage facebook
<!> Collect my HRO story
<!> Learn about setting up hot spot
CF: Eleanor Greenhalgh
* Milgram Experiment
* Kate Rich interview FSS
* Find the tone : We need to actually offer a service
Imaginative Cartography of the Shell
The Shell as a Fiction
Avoid Single Image Pipeline
Efficiency vs. Multiplicity
In both cases: sharing, serendipity, ... good things... but in what context and to what consequence
Frictionless Sharing:
* Hierarchical (Designed by designers, programmed by programmers, used by users, paid by advertisers)
* Automatic
* Consent out of context (one-time / pre-use consent through EULA / TOS)
* Shortest path, optimum solutions
Promiscuous Pipeline:
* Mixed roles (user becomes developer...)
* Hands on control
* Editability through interrogable
* Variability, multiplicity
Variability / Multiplicity:
like make can produce many versions / formats of output, an ideal promiscuous makefile would support a vast variety of possibilities
what's the smallest unit of "raw" material...
How can the raw "units" be recombined / bound in new documents / frames / compilations
Image + Caption
Q + A
Commit Message
18 April 2014, Variable
Parameters of time / space
instead of login.
(IP address, Authentication via password/email / OAUTH)
Imagine a network tagging time,
All activity is stored as a kind of relative map of nodes
Playful: Make connections between people... introduce people to each other?
Return to the idea of sensing each others presence when working.
How do you give glimpses of others at work / encourage collaboration / spirit of working together in a digital enrivonment without devolving into full surveillance (watching every detail, etc).
How to avoid the situation that providing a full report of logged activities, even when intended to warn, in fact comes very close to existing practices of "data nudism" -- ie providing self-surveillance as a service.
Stronger position is to propose alternative ways of working and active writing spaces (as opposed to passive logging) for people to explore collaboration and shift tracking to something explicit.
* Making the logs visible
Example: Typing a space in the terminal to prevent a message entering the history
[?] Core question: do we take a position of parody
KEY to actually propose a viable alternative
Scenario: People arrive for summer school, are handed a network pod...
immediately contrasts to tradition hotspot are apparent...
Etherpad + Anonymous contribution, time based //
(Nameless !== Anonymous)
Nameless, linking
Social File System //
alt git / distribute
Different set of handles for organizing & correlating data.
Proposing relations based on:
* Algorithmic (images with similar amounts of red)
Recombination Modules
* Apple's Time Machine (based on the individual hard drive)
** non-collaboriative
* Internet archive wayback
** Based on the identity of the URL, )
** Limited by the parameters of the spider (ignoring some types of media, privileges a client-side view of the data)
** Follows nobot = noarchive
* Git
** Hash based identity (files are their content, not their name)
** Name + email
* Torrents
** Magnet link identity -- Distributed
Where the Social Network proposes relations based:
** Rejection of traditional authentication
** Algorithmic connections
* Share Canvas
Across different collaboration / file management tools:
* Identity (of people, of files, of digital content)
* Time
* Core stuctures for organizing / indexing
* Interface
Network / Access / Tactics of engagement (with existing...)
* Proxy, means of accessing existing systems (example of using github with other kinds of identity)
* Scroogle: Example of using a single account
* Publicizing one's login information
* Question of publishing
* Setting in stone vs. Ad hoc relations
* Web ring, adding a link /// PYRING!
M commits an image
A commits a text
The commiters are sitting next to each other at the time & there's less than 5 seconds in time.
* SVG layers work
git + etherpad = shared canvas
a distributed space for files and ad hoc relationship
* Location
* Time
Multidimension space
* Relative timelines (not calendar / absolute)
* How to avoid the "sync-kill" (example of cinema)
* Shared index of files...
* Pre Summer School
* Summer School
* Post Summer School
Three temporalities of writing
* Prospective / Planning
* Real time / Happening Now
* Retrospective / Editing
Location, similary can be relevant / and can be not.
Ideally an interface for editing where one can "check in / check out" -- choose to detach.
* Timelines
* Spaces
* Tags
* yourworldoftext
* second life
* gray editor (julien maire)
* social/situated/cyberspace
Object as a clock / The chess clock
Example for prototyping futures:
* Using timelines to place / relate elements such as
* IRC as a protocol allows for distribution -- how does this work?
<!DOCTYPE html>
<meta charset="utf-8" />
<script src="/lib/jquery-1.10.2.min.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
<script type="text/javascript" src="script.js"></script>
$<input id="cmd" type="text" value="" />
<!-- <button id="start">start</button>
<button id="stop">stop</button>
<button id="manbutton">man</button>
<button id="cookbookbutton">cookbook</button>
--> </div>
<div class="bash" id="shell" style="width: 640px; float: left"></div>
<div id="man" class="bash" style="display: none;"></div>
This diff is collapsed.
$(document).ready(function () {
system as cookbook writing environment
hooks into repository manager for shared cookbook writing the (social)
+ hooks for realtime (chat?!)
Common problems:
Finally have got a working command, just want to save it
it's just awkward enough that you don't do it
(the effort of cut/paste, swapping to editor, naming and placing the file)
Instead: one-click "bookmarking", added to personal history list
Terminal is binary-averse (image, audio, visual material is "alienated" to external display)
HTML is "collage"-able means of mixing media
!! Pipeline editor / debugger with media-specific previews
* Bookmark (this command)
* Add to Recipe/Script
* Smart Tab completions
* Link to cookbook (examples)
separate stderr / stdout
script panes (editable!?)
man pages as postscript / pdf / savable?!
annotations in man pages <!>
mime type sniffing of output & appropriate browser-based display ( image / audio / video / text+html )
Missing features
* live programs / keyboard control (mplayer, top, etc...)
.on("keypress", function (evt) {
if (evt.keyCode == 13) {
} else if (evt.keyCode == 9) {
// tab
return false;
} else if (evt.charCode == 32) {
} else if (evt.keyCode == 8) {
// Backspace
} else if (evt.keyCode == 38) {
// UP
} else if (evt.keyCode == 40) {
} else if (evt.keyCode == 37) {
} else if (evt.keyCode == 39) {
} else if (evt.charCode == 92) {
// PIPE !
function _sock (wsuri, opts) {
// to do add support for stderr, stdin & buffer data to ensure line-based processing callbacks for the two
// also set a flag for CR ?!
// might want to ensure closed before reopening a new one ?!
var that = {
sock: new WebSocket(wsuri)
curline = '';
that.close = function () {
that.sock.onopen = function(e) {
console.log("connected to " + wsuri);
if ( {, e)
that.sock.onmessage = function (e) {
var lines =[\n\r])/),
len = lines.length;
if (len == 1) { // extend current line...
curline += lines[0];
} else {
for (i=0; i<len; i+=2) {
if (lines[i] == "") { continue; }
curline += lines[i];, curline+lines[i+1]);
curline = "";
that.sock.onclose = function(e) {
console.log("connection closed (" + e.code + ")");
if (opts.close) {, e) };
return that;
var sock = null,
wsuri = "ws://localhost:9000",
curline = '';
var shell = $("#shell").get(0);
function go () {
sock = _sock(wsuri, {
open: function (e) { this.sock.send($("#cmd").val()); },
stdin: function (text) {
// console.log("message received: " +;
var cr = text.match(/\r$/);
if (!cr || !lastline) {
lastline = $("<div></div>").appendTo(shell);
close: function () {
function man() {
var cmd = $("#cmd").val().split(/\s/)[0],
src = '';
console.log("cmd", cmd, "*");
sock = _sock(wsuri, {
open: function (e) { this.sock.send("man -Thtml "+cmd); },
/* TODO: Hyperlink See Alsos !!! */
stdin: function (text) {
src += text;
// console.log("man");
close: function () {
console.log("man closed");
$("#stop").click(function () {
if (sock) {
sock = null;
#!/usr/bin/env python
import argparse, socket, os
import twisted
from time import sleep
from twisted.internet import reactor, protocol
from autobahn.twisted.websocket import WebSocketServerFactory, WebSocketServerProtocol, listenWS
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.web.static import File
from twisted.web.twcgi import CGIDirectory
class AAWebSocketProtocol(WebSocketServerProtocol):
def __init__(self):
# WebSocketServerProtocol.__init__(self) # apparently there isn't one
self.process = None
def onMessage(self, msg, binary):
if (self.process == None):
self.process = AAProcessProtocol(self)
parts = msg.strip().split()
reactor.spawnProcess(self.process, parts[0], parts, {})
# self.sendMessage("Starting {0}...\n", False)
def onClose (self, wasclean, code, reason):
# web socket has closed, kill the process
print "web socket onClose", wasclean, code, reason
if (self.process != None):
self.process = None
def ended (self, code):
# process has ended (normally), close ourself
if (self.process != None):
# close outself
class AAProcessProtocol(protocol.ProcessProtocol):
def __init__(self, ws):
# self.output = "" = ws
def connectionMade(self):
print "connectionMade"
self.transport.closeStdin() # no input to mplayer
def outReceived(self, data):
# print "outReceived, with %d bytes!" % len(data)
# self.output += data, False)
def errReceived(self, data):
print "errReceived, with %d bytes!" % len(data)
print "<ERR>", data,
def inConnectionLost(self):
print "inConnectionLost, stdin is closed! (we probably did it)"
def outConnectionLost(self):
print "outConnectionLost! The child closed their stdout!"
# evt here code to (trigger) a processing of the output
def errConnectionLost(self):
print "errConnectionLost! The child closed their stderr."
def processExited(self, reason):
print "processExited, status %d" % (reason.value.exitCode,)
def processEnded(self, reason):
print "processEnded, status %d" % (reason.value.exitCode,)
def kill (self):
# Here's the trace of a kill (when triggered by websocket.onClose)
# web socket onClose True None None
# errConnectionLost! The child closed their stderr.
# outConnectionLost! The child closed their stdout!
# processExited, status 1
# processEnded, status 1
# self.transport supports methods: write, closeStdin, closeStdout, closeStderr, loseConnection (close all 3)
# kill seems to cause errors while loseConnection closes things gracefully
# self.transport.signalProcess("KILL")
def main (args):
parser = argparse.ArgumentParser(description='Happy to serve you')
parser.add_argument('--port', type=int, default=8000, help='http port number')
parser.add_argument('--wsport', type=int, default=9000, help='websocket port number')
parser.add_argument('-t', '--notryports', default=True, action="store_false", help='if a port is busy, automatically try other ones')
parser.add_argument('--share', default=False, action="store_true", help='Run as server accessible via your local network')
args = parser.parse_args(args)
tryports = args.notryports
port = args.port
ipaddr = None
if args.share:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ipaddr = s.getsockname()[0]
interface = ipaddr # None would listen to all
interface = "localhost"
resource = File(".") # Resource()
# resource.putChild("f", File(cwd))
# resource.putChild("lib", File(activearchives.getDataPath("htdocs")))
# resource.putChild("cgi-bin", CGIDirectory(activearchives.getDataPath("cgi-bin")))
# resource.putChild("", File(activearchives.getDataPath("root/index.html")))
# resource.putChild("", File("."))
factory = Site(resource)
# WebSocket
wsfactory = WebSocketServerFactory("ws://localhost:{0}".format(args.wsport))
wsfactory.protocol = AAWebSocketProtocol
while True:
if ipaddr:
server_address = (ipaddr, port)
servername = ipaddr
server_address = ("", port)
servername = "localhost"
reactor.listenTCP(port, factory, interface=interface)
print "(Twisted) Archiving starts now --> http://{0}:{1}".format(servername, port)
except twisted.internet.error.CannotListenError:
if tryports:
if port < 2000:
port = 2000
port += 1
print """
Error: port ({0}) is already in use
You can pick another port number
(for example 9999) with:
sosh --port 9999
if __name__ == "__main__":
import sys
source venv/bin/activate
body, input {
margin: 10px;
font-family: monospace;
font-size: 16px;
background: #000;
color: white;
.bash {
font-family: monospace;
font-size: 12px;
height: 24em;
overflow: auto;
resize: both;
border: 1px dotted black;
#shell {
white-space: pre-wrap;
#cmd {
border: 1px solid black;
width: 640px;
.loading {
background: #AAA;
input#cmd {
border: none;
#man {
background: white;
padding: 10px;
color: black;
width: 400px;
float: left;
#man a {
color: purple;
text-decoration: none;
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment