Thursday, October 17, 2019

The winner is CodeSandbox, Overmind, etc

At last! The holy grail. Or a close approximation.
A while ago I did an assessment of Dev environments in the cloud
Now I’ve settled on one.
My goal was a genuinely frictionless programming environment. One where everything I do happens instantly—or at least quickly.
I want to make a change and see a result.
Just like that.
I also want a sensible methodology for programming. One that organizes code so that I can create it rapidly, maintain it easily, modify it efficiently, test it thoroughly, and deploy it effortlessly.
I’ve got something that’s a candidate.

My programming environment

I’m using:

CodeSandbox

Codesandbox is my development environment. It lets me check stuff out of Github with a Chrome Extension that makes creating a new SandBox a one-click operation.
Once I’ve made my changes, I can commit back to the repository—if it’s mine—or create a new one from the IDE.
CodeSandbox plays nicely with React, Overmind, and Firebase. And with Node Package Manager (NPM), I can grab any library I want with a few keystrokes.
Equally important: if I want to understand how a library works, I can create a SandBox that contains one of the library’s examples. Then I can play with the example it until I’m sure it will do what I want.
When I make a change, CodeSandbox uses Hot Module Reloading (HMR) to only reload what needs to be reloaded. The result is that any change in my code appears in my app more-or-less instantly.
Whatever I commit to Github gets deployed automatically by Netlify.
So my workflow looks like this: checkout, modify, modify, modify, modify, commit, then automatic deploy.
If I want to save an intermediate state, I can fork my SandBox, and if I’m headed in the wrong direction, I can go back to an earlier version.
I can organize SandBoxes in directories, and if I have one that I like, I can turn it into a template.
And CodeSandbox lets me work on the entire app or just one module. Which is kind of awesome.

Building with Overmind

I build an application by creating a data model using Overmind in a SandBox, testing it, then connecting the model to a user interface built with React.
Overmind is my data modeling and state-management tool.
I define a JSON object that represents my application’s state, a set of actions for modifying the state, and a set of effects that interact with the outside world.
Overmind delivers state, actions, and effects anyplace I need it,
I can write scripts invoking actions and effects and verify that the scripted code transforms the state the way I want. I can confirm that by observation (Overmind has a development tool that displays state and a record of actions) or by writing tests that verify.
State contains explicit values and values derived from other parts of the state. Overmind magically updates the derived values when the values on which they depend are updated. Just like a spreadsheet.
Later, when I hook Overmind to React, Overmind will magically tell React to rerender any part of the UI when the state on which the UI depends changes.

UI components

Once the state works the way I want it to, I use a CodeSandbox feature that lets me work on one UI module at a time.
I write a UI module and tell it which state variables to render, and Overmind and React re-render components when values change.
As I’m writing my code and change the code for UI component, it gets rerendered in well under a second.
Then I hook user interactions in the UI to the actions and effects I created. User does something, action or effect fires, the state gets updated, UI gets rerendered, just like that.
As I finish my lower-order components, I combine them into larger components. As far as CodeSandbox is concerned, a component is a component is a component. So as I tweak a higher-level component, everything within it that needs rerendering just does.
If I discover a problem in action, I can change the action and try it again.
Since the state is just a plain old Javascript object, I can save it and restore it any time I want.
When I’m done, I commit, and deploy happens automatically as I go on.

What’s next?

Next, I’m going to make a series of videos to show all this stuff

Sunday, June 9, 2019

Dev environments in the cloud

I’ve been experimenting with cloud development environments.
Here are the ones I’ve been using and what I’ve learned about them.
TL;DR
Cloud development environments are so capable now that it hardly makes sense to install a development environment on my computer. At least for that kind of development.
CodeSandBox.io is going to be my primary environment for a while. It’s got what I need. I may also use Scrimba.

JSFiddle.net

This is the old school JavaScript sandbox. This is the one that things off it all and the first one that I used. Today it seems well behind the times. I have also used some others, like JS Bin, Fiddle Salad, and repl.it

Plunkr

I used it when I was messing around with Angular and facebook. I’ve still got a couple of Plunks in my library.

CodePen.io

I used it for a bunch of client-side experiments. The great thing about it was instant response and excellent editing experience.

Glitch.com

Glitch was the first environment that I used that handled both client side and server side. So It was a complete node development environment, and I did some exportation into Google’s APIs with it. Its user interface is a little funky and weird. I don’t think it compares well to the alternatives below.

Google Cloud Console

Google gives you your own Linux Docker container, freshly provisioned each time you use it. That’s a problem because it takes a lot longer to spin up than some of the other environments. You can also define your own customized VM, so you have a degree of flexibility that you don’t get elsewhere.
Also, there’s an elegant tool for building your own tutorials.
The editor is pretty crappy, and it keeps disconnecting, so not so much.

Gitpod.io

Lets you clone any Github repository, branch or commit into a VM that it provides for you. It even has a browser extension that puts a GitPod button on your Github pages. Click and get a gitpod. But it takes a while to spin up your VM. There’s got to be a better way because everyone the others do it better.
Unlike Google Cloud console’s VMs, these persist. But each Gitpod is independent of the rest.

CodeSandBox.io

CodeSandbox is really fast. You can embed CodeSandbox apps in your web pages (or blog posts) I’ll post at length, later.

StackBlitz.com

StackBlitz is the runner up. Maybe more to come later.

Bit.dev

An excellent environment for finding and tuning up pre-made React components.

Saturday, April 28, 2018

StackBlitz: online playground



Stackblitz is an online development environment--like jsfiddle.net, codepen.io, and codesandbox.io.

The big plus for StackBlitz is the ability to use VS Code as your editor.

Another nice feature (shared by several others) is the ability to embed your project.

Kind of like this. You can edit the code in the embed and the screen will update.

VS Code Editor

Visual Studio Code aka VSCode or just code once you’ve installed it is the best editor around. 
If you like VIM, it’s got a VIM mode. So there. If you like other key bindings, you’ve got them.
It’s got a ton of plugins, more on which later.
And it’s free. That’s the right price.
And you can use it as your online editor for client applications using stackblitz.com More on that later.

About glitch

Glitch is my web playground of choice for building full stack node-served web apps. 

You can use glitch project to run a node server and use it to serve your own content.

Glitch is integrated with GitHub so you can move projects easily between the two.

And you can clone your GitHub repository to your development machine and work locally or in the cloud, depending on what's best.

I'm eldrgeek on GitHub and glitch.

You can find my growing list of Glitch projects here.








OneTab--tab cleaner-upper

The top  tabs in  my OneTab
OneTab is a Chrome plugin that solves a problem that I have: too many open tabs, which leads to both slow performance and distraction.
I get too many open tasks because I tend to leave a trail of open tabs behind me as I research, or task switch. I tell myself that I’ll get around to handling them. But eventually I’ve got a unmanageable clutter. When I get too many tabs, I can use OneTab to close the tabs but not lose track of them.
OneTab keeps a local data structure that it renders as a web page. When I click on the plugin, it adds a new section and in it puts a links to each of the open tabs in my current Chrome window. Then it closes those tabs. If I have a tab that I don’t want closed, I can just drag it out of current window.
My OneTab on this machine has too many files to count. Every other machine that I use has its own OneTab with its own many unhandled tabs.
Now it’s time to clean up some tabs.

Sunday, July 2, 2017

Blueprint: awesome React UI library

Blueprint is a fabulous library, built for React. It has everything that I know that I've wanted for building a UI, and it has lots of stuff that I didn't realize that I wanted--but I do now!

And did I say that it's built for React? Oh, yeah.

Things like Navbars, and Menus and Toasts. Never heard of a Toast? Check this out.

You can play a bit on this here CodeSandbox project. Or click below.



Monday, April 3, 2017

Requirements for a minimal viable TODO

# Minimal Viable TODO

The TODO list is an editable document in MarkDown.

1. The system uses a CodeMirror instance. Each line is an item.

2. It persists data to local storage AND to the server's .data directory.

3. It uses Markdown as a representation

4. Markdown heading lines (starting with one or more #) are section markers. So # Next is the next group. # Projects is the project group. Projects start with ##. Subprojects with ###

5. When I leave a line the system turns the line from Markdown to HTML Entering a line reverses the process.

7. When I leave a line, any line with a # or @ annotation is moved to the matching section. Top or bottom of section to be decided later.

8. The annotation #done overrides all other # annotations, and moves the item to the end of the relevant section. #done lines are rendered with a .task_done style, which is a strikethrough.

9. Ctrl-up/Down are used to move lines up and down

10. Ctrl-K selects the current word (if nothing is selected) or uses the current selection, and wraps it in [] and pastes the current clipboard contents wrapped in (). This is the markdown link syntax.

11. Add a RESTFUL API that will let me read the list or push it to a remote site.

12. Push the system to `glitch` which will give me a project that I can work on, online.

# Ideas for next phase

Use the CodeMirror `marktext` API and code folding API to hide/show regions of the document.

By default, regions are unfolded when the cursor enters them; are folded when the cursor moves out.

Convert atomic edits to Redux Actions.

VS Code multi-process debugging

VS Code is cool!
I set up a project here on Github to demonstrate debugging two processes— a parent process and a child.
The parent launch configuration looks like this:
 {
            "type": "node",
            "request": "launch",
            "name": "Parent",
            "program": "${workspaceRoot}/parent.js",
            "args": [],
            "cwd": "${workspaceRoot}"
            // ,"port": 5858
            ,"protocol": "auto"

        }
Note that the port:5858 line is commented out. If it’s included, everything works, but later, when we launch both parent and child together, there are problems.
Parent code:
console.log("Parent running")
const cp = require('child_process');

const child = cp.fork(`${__dirname}/child.js`,{
 //force the debug port to the one in the launch config
 execArgv: ["--debug=5859"]
 ,silent: true
//  ,stdio: 'ipc'
}
);

//Child data does not go to console with VS Code
//So do this.
child.stdout.on("data", (m) => console.log(m.toString()));

const sender = () => {
    child.send({ hello: 'world' });
}

child.on('message', (m) => {
  console.log('PARENT got message:', m);
  sender()
});
The parent has to pass debug=5859 to the child, and the Child launch configuration has to have that port set:

  {
        "name": "Child",
        "type": "node",
        "request": "attach",
        "port": 5859,
        "address": "localhost",
        "restart": false,
        "sourceMaps": false,
        "outFiles": [],
        "localRoot": "${workspaceRoot}",
        "remoteRoot": null,
        "protocol": "legacy"
    }
The child looks like this:
console.log("Child started\nu");
console.log(process.argv)

sender = () => {
    process.send({ foo: 'bar' });
}

process.on('message', (m) => {
  console.log('CHILD got message:', m);
  sender()

});
//start by sending a message
sender();
The README.md file explains how to use the project

VS Code Child Process Debug

This is a VS code project that lets you open a debugger on a parent process and a child at the same time.
It shows several ways to connect:
  1. Connecting to one process at a time in debugger
  2. Connecting to both together in debugger
  3. Connecting to a parent started in a console

Connecting to one process at a time in debugger

  1. Switch to the debug view
  2. Set a breakpoint in parent.js in the line that reads:
    console.log('PARENT got message:', m);
  3. Set a breakpoint in child.js in the line that reads:
    console.log('CHILD got message:', m);
  4. Select Program as the launch configuration
  5. Start the debugger by clicking on the green arrow key or F5. A debug widget

    will appear and the debugger will stop in parent.js and display the file in an editor pane. You’ll get output in the console that looks like this:
Debugging with inspector protocol because Node v6.10.0 was detected.
node --inspect=SOME PORT --debug-brk parent.js 
Debugger listening on port 5858.
Warning: This is an experimental feature and could change at any time.
Debugger attached.
Parent running
Child started
[ '/home/mwolf/tools/node-v6.10.0-linux-x64/bin/node',
  '/home/mwolf/tools/junk/child.js' ]
*******************
Like this one
  1. Choose Child in the launch configuration, and press the green arrow key to attach to the child.
Note: in this case F5 will not attach to the child, but cause the already running parent to continue and stop at the breakpoint again.
  1. The debug widget will now have a a drop-down list and let you switch between the parent (launch) process or to the child. You can also disconnect from one or the other
  2. If you press the green arrow in the debugger widget, or F5, the program will run to the next breakpoint—which by design is in the other process, display the code and stop there. Pressing F5 again moves it back.
  3. If you have two tab sets open and move one file to each set, then you’ll see it toggle back and forth as you hit successive breakpoints.

Connecting to both together

  1. Select the Program/Child launch configuration.
  2. Press F5 of click on the green arrow.
  3. The debugger will stop in parent.js and both

Disconnecting and reconnecting

If you disconnect from the parent, then the child disconnects as well. But if you disconnect from the child, you can reconnect using the child launch configuration

Sunday, March 19, 2017

Toward an awesome development workflow

I've spent a lot of time over the past few years designing and building tools that approached my vision of an ideal application development workflow. Web tools were the future: CSSHTMLJavascript, NodeJs for the back end. Plus others. I learned a lot. Then I decided that what I was doing wasn't working. So I took a break.

After a bit, I started reading about new high-productiviy technologies that had appeared and begun to mature since I'd started my project. The more I learned, the more impressed I became, and the more excited I got about building something even better than what I had originally envisioned.

I decided that I needed to spend time mastering some of the core technologies for web app building. I knew the basics of JS, but ES6 had come along. And JSX. And Typescript and Babel, the next generation compiler. All these tools added up to something better than what I'd been using (Coffee Script).

Then I found React and Redux, which put HTML back into Javascript and solves a bunch of problems. Then CSS Modules which put CSS in Javascript and solved a bunch of problems. Then Webpack which packaged things up on the fly and made building for the web a lot simpler. And hot module reloading. And React and Redux dev tools. And then a buddy pointed me to glitch.com -- a better coding playground in the cloud than the ones I had been using. And VS Code, a better editor and working environment on the desktop (Linux, Windows, Mac) than what I'd been using (Sublime Text and Atom.) I was off and running.

And along the way, I've found people online with similar visions for application building. Some had already contributed to big pieces I've listed. Others were crafting smaller bits that helped make a workflow really flow. My job now is filling in the gaps in my education, integrating their stuff, making my contribution, and spreading the word.

I want to build the world's most awesome development environment for web applications. I'm not going to fill this blog with my discussions of what I am doing and what I've learned. Instead, I'm going to be posting on another blog that I have: Awesome Development, starting with a copy of this post. 

If you're interested, I'll see you there.

Originally published here

Tuesday, January 3, 2017

Time travelling development--for JS apps

TL;DR To how things should really work, watch this talk by Dan Abramov who created Redux, and the debugger concept.

Long version:
Make a change in your code. See it updated instantly. That's what I want because modern development is an iterative process, with fast iterations.

We've got something like that in JS playgrounds like JSFiddle, CodePen, and so on. But there's still a couple of things that are wrong. Make a change and the app runs again, from the top.  It's pretty quick, and for small bits of code, there may be almost no lag. But as your app scales, the time grows.

You can write a test driver, so that once the app loads, it tests itself, but that's another whole lot of code that you have to write. And even then, reloading takes time, and most of the changes that you make are teeny tiny ones. Even a second or two for a reload is too long.

You can do this in your Dev environment, as well as

And you don't want to test your whole app every time you make a change. Most changes are not going to break the app. They're just little tweaks. What you'd like to do is this: put the app in a certain state. Make your code change. Do some fiddling with the interface. See if it works right. If it doesn't then:

  • Revert to the earlier change
  • Rerun the interface twiddles
  • Repeat until it's perfect
  • Make this the new base, state
  • Repeat forever
And if you run into problems you'd like to go back to your base state with the ability to back up through the twiddles and debug anywhere. Now someone has pretty much done that using mainstream tools.

The key is making your code functional. Take state out of the functions. It's a variation on MVC programming. And it points out a flaw in MVC.

The usual MVC routine is this: you've got a data structure, which is your model. You've got code that takes the Model and renders a View. The view contains UI Control components. When a user manipulates the Controls, the model changes -- either by two-way binding, or by calling functions that are part of the Model, or by directly manipulating the Model data structure. But sometimes the View has its own controlling data structures. So there's a Data Model, and a View Model to pay attention to.

Instead, design code using Model, View, Controller, and Actions. The rules are:

All state is in the Model. Base data state and View state are in different parts of the one and only Model.

Models are POJOs, so they can be serialized and parsed back to their former state.

Actions are Plain Old Javascript Objects (POJOS) emitted by Controllers. 

A part of a Model is updated by calling a model updating function with an Action. There is no other way to update a Model. Model updating functions are called Reducers.

Reducers functions have the following signature: (Oldstate, action) -> newState, the signature used for functions called by Array.reduce They take the prior state as an input parameter and produce a new state. Because of their signature, reducers can be called with an array of Actions, using Array.map. So calling:
arrayOfActions.reduce(reducer, initialState)
Will return the final state, after applying all of the actions. 

Reducers don't update the Model; they replace the old state with a new state, in which the changes have been made according to the Actions. So state objects are immutable.

As a consequence:
  • We can save and restore the application state at any time
  • We can take any state, and apply a set of actions to it, giving the state after the actions
This lets us create a debugger that will do what we want it to do.

The technologies that make this easy to do are React and Redux. React is a framework for view rendering. In ordinary practice, View components can be stateless or stateful. Redux is a framework for managing states for React-based applications so that View components can be stateless.

To see how this works, watch this talk by Dan Abromov who created Redux, and the debugger concept.

Also read the docs for React and Redux, which I am in the process of doing.

Sunday, January 1, 2017

Browser synchronization, event capture

BrowserSync is an Open Source project that keeps multiple browser instances in sync.

I've downloaded it and tested it. It has some problems, but it mainly works as advertised. And it can do a bunch of thing that an awesome environment would need to do.

First: the main idea. BrowerSync captures events from each browser that's displaying data from a site that it serves, and forwards those events to other browsers looking at the same site. Even better, the BrowserSync server can proxy another server, including one serving pages by https.

Here's a review of some competing technologies by Addy Osmani, and his review of BrowserSync or browser-sync (github) and site.

I started by installing browser-sync

npm install -g browser-sync

I started by testing it with a polymer/firebase project. I cd's into the directory and ran:

$firebase serve 

That gave:

Starting Firebase development server...

Project Directory: /home/mwolf/tools/prog-with-papa
Public Directory: dist

Server listening at: http://localhost:5000


In another console, I run browser-sync in proxy mode:

browser-sync start -p  http://localhost:5000

That gives:

[BS] Proxying: http://localhost:5000
[BS] Access URLs:
------------------------------------
      Local: http://localhost:3000
   External: http://192.168.1.2:3000
------------------------------------
         UI: http://localhost:3001
UI External: http://192.168.1.2:3001
------------------------------------

And pops open a window on http://localhost:3000

I opened an incognito window and went to the same URL. Sure enough, clicking on menu selections in one made the same changes happen in the other. One of the pages had a text box. Entering text in one entered it in the other. But scrolling the form did not sync! I also tested it using my phone and the external port. Worked fine.

Next test. I proxy a site on the web.

browser-sync start -p  http://slatestarcodex.com/

Next test. I proxy a site on the web. Works fine, including navigation within the site and scrolling. So maybe the scrolling problem has something to do with Polymer?

Then I proxy the site using https. I get:

[BS] Proxying: https://slatestarcodex.com
[BS] Access URLs:
-------------------------------------
      Local: https://localhost:3000
   External: https://192.168.1.2:3000
-------------------------------------
         UI: http://localhost:3001
UI External: http://192.168.1.2:3001

Again, it works as hoped for.

Will it work for google?

browser-sync start -p  https://www.google.com

Opens a browser, but tells me that there's a security problem: the site doesn't have a correct SSL certificate. I approve it as an exception, and it works!

I try with facebook. Facebook lets me get public content, but its security protocols won't let me log in. I assume that the same thing will happen with any site withy good security.

So BrowserSync does some of the things that I want it to do. Others, like bypassing security, are probably impossible by any means.

Couple this with Chrome Plugins, and I may be able to do some of the hacking that I want to do.

At the heart of browser-sync is its ability to capture events and forward them. On the road to discovery, I found the following resources:

HTMLGoodies Advanced Javascript event handling

Ghostlab

Comparison of Ghostlab and BrowserSync

EventTarget.addEventListener at MDN, defines the basic procedure for handling events. By overriding EventTarget.prototype.addEventListener you can capture events for all targets, and do funky things with them.

An article about event capture on css-tricks.com by one of the authors of GhostLab. The article includes links to several CodePen examples for capture.


The workbench paradigm

IDEs and other power software tools suffer a tension between power and complexity. A photo editing tool has a dozen menus; each might have a dozen selections, and many of those might have submenus. If you remove all the menus and selection, you remove the tool's power. If you keep them, then finding out how to do the thing you want to do next means searching for the right command.

Some tools get you around this by letting you type a string that fuzzy-matches to the function that you are looking for. That's better, but still requires quite a bit of fiddling to get the function that you want.

Instead, consider a shop project as a governing paradigm. A skilled craftsman has a workshop full of tools and materials, but for any one task, needs only a few. Before commencing work the craftsman grabs the needed tools and materials, lays them out on the workbench in easy reach, and then sets to work. When possible, a workman prefers materials as close to finished size as possible. He'd prefer already-turned drawer pulls to blocks of raw wood he can turn into pulls.

So, consider building a GUI. The usual method is to go to a palette of components, pick one, place it, then assign properties to it. Then pick the next one, and so on. Instead, pick only the components that you'll need; choose the items in the palette that you want to be visible, and hide the rest; when you've adapted one to size, add it to the palette.

Consider building something with a bunch of icons using Polymer's iron-icons. If we were doing it with a GUI builder, we might pick iron-icon from a palette of iron elemements (there are 35 of them) place it, pull up a property sheet to set its properties, and continue.

One property is the icon image name from an iron-iconset. So we'd choose the icon images that we want. Then on to pick the next icon. If we're a little smart, then instead of picking another icon from the palette we'd duplicate the first one. But we're still left with the task of choosing another image.

Instead, we'd do better to go to a collection of pre-made iron-icons, each with a different image, and use them as our components.

The Polymer library lets us define a collection, and add iron-icon to the collection. But we can only add the raw iron-icon element's definition. And it has another element that contains a set of icon images. But it doesn't have a nice way to subset the images, or to attach a chosen image to an icon instance other than cut and paste with the text editor.


Saturday, December 31, 2016

Spreadsheet programming

People who don't call themselves programmers can build sophisticated programs using spreadsheet programs. How come? And what implications does it have for building better programming tools?

1. Normal programming deals with control flow. Spreadsheets deal with data flow. That means that sequencing issues disappear. In a procedural language, you have to call a function at the right place in the program: after all its inputs have been set and before its outputs are needed. In a spreadsheet, this happens automatically.
2. Spreadsheets give fast feedback. Some development environments, like JSFiddle, JSBin, CodePen, Plunker, and other javascript playgrounds do this. So do various interpretive languages. But as programs grow, feedback slows. Spreadsheets, on the other hand, give fast feedback to small changes with low impact, slower feedback to changes that have global impact.
3. Spreadsheets know when you're finished with a change. As soon as you move out of a cell, the spreadsheet recalculates (assuming no errors). Playgrounds need to decide whether you're finished editing or not. If they guess wrong, there's a noticeable penalty.
4. Spreadsheets let you organize information multi-dimensionally. Normal programming languages are entirely linear. Spreadsheets give you two dimensions, at least. Within a sheet's two dimensions you can chunk information arbitrarily.
5. Spreadsheets make it easy to visualize information. You can grab key parameters and put them all in one area.
6. Spreadsheets help you see dependencies.
7. Spreadsheet cells are pure functions. There are no side effects.

Of course, there are disadvantages. You can only put so much logic in a cell before you need to resort to a scripting language. And then you have the usual problems of dealing with procedural languages. And you can only transfer a single value--a number or a string. No structures allowed. And the spreadsheet grid limits presentation options. And binding is one-way.

But imagine a spreadsheet-like model that removed some of these limitations. A 2D area might be subdivided into a "model" section and a "view" section. Values in the model would be bound to areas in the view so that, by default, changing the model would change the view, and vice-versa.

Widgets in the view might have property sets that were, themselves, represented by subordinate spreadsheets, and every value in the property set could contain a simple formula.

As the system scales the number of cells grows, unmanageably so we need a way to restrict our view to only those elements of interest at a given moment. 

This starts to look a bit like a standard GUI-building environment, with widgets with property sheets. There are important differences, though. One is: 

Monday, December 29, 2014

Chrome Remote Operation--work in process

Now that I'm making a debugger abstraction it's time to think about eating my own dogfood by connecting my IDE to a Chrome debugger instance running an application--or even another instance of the debugger.

Even better, it looks like the the chrome-remote-debugger API will not only let me debug a remote instance of Chrome, it will let me control and monitor everything that happens.

The node module is here.

To run more than one debugger on an instance requires crmux, here.

And a partially implemented console that I might be able to read to understand what to do is here.

So far I've been able to do this:

1. Run my debugger with an external debug port:

google-chrome --remote-debugging-port=9222&
9222 is the standard debugging port.

2. Run crmux in a separate window

crmux

This multiplexes the debugger on 9222 to be available on 9223

3. Now I can use the chrome-remote-api REPL

./node_modules/chrome-remote-interface/bin/repl.js -p 9223
Proof that it works: if crmux is not running, it gives an error.

4. Now I can open a page at

     http://localhost:9223

This gives me a list of debuggable pages. If I choose the one that I want I get this URL:

http://localhost:9223/devtools/devtools.html?ws=localhost:9222/devtools/page/7F642E19-7F9A-40AB-BE87-B344B6307246

Note the ws=localhost:9222. This is the original port and can interfere with things. So I must manually change to ....?ws=localhost:9223...

Proof that this works: I can kill crmux and things no longer work.

5. If I now run

crconsole -p 9223

I get a prompt. (It fails if crmux is not running)

And if I type the command

.tabs

I get something like this:

localhost> .tabs
[0] http://localhost:9223/devtools/devtools.html?ws=localhost:9223/devtools/page/7F642E19-7F9A-40AB-BE87-B344B6307246
[1] http://localhost:3333/IDE
[2] chrome-extension://jnihajbhpnppcggbcgedagnkighmdlei/_generated_background_page.html
[3] chrome-extension://ighdmehidhipcmcojjgiloacoafjmpfk/_generated_background_page.html
[4] chrome-extension://diebikgmpmeppiilkaijjbdgciafajmg/background.html
localhost> 

OK. Those are the right tabs.

But no matter what order I use, I haven't been able to get both the Chrome debugger and crconsole ot play nicely together.

But: I was able to run an instance of crdebug and an instance of the chrome-remote-interface REPL together, and evaluate the following this in the REPL

chrome> Runtime.evaluate({expression: 'foo = 20'}, console.log)
Output is:
chrome> false { result: { type: 'number', value: 20, description: '20' },  wasThrown: false }
And the result, 'foo=20' appears in the other console. So I have two different consoles talking to the same chrome instance.

The problem comes when I run one chrome debugger instance along with a crdebug instance. Depending on which one I start first, the other fails.

If I run devtools first, then crconsole fails:
TypeError: Parameter 'url' must be a string, not undefined    at Url.parse (url.js:107:11)    at Object.urlParse [as parse] (url.js:101:5)    at WebSocket.initAsClient (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crconsole/node_modules/chrome-remote-interface/node_modules/ws/lib/WebSocket.js:475:23)    at new WebSocket (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crconsole/node_modules/chrome-remote-interface/node_modules/ws/lib/WebSocket.js:59:18)    at Chrome.connectToWebSocket (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crconsole/node_modules/chrome-remote-interface/lib/chrome.js:112:15)    at Object.ChromeREPL.setTab (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crconsole/index.js:223:17)    at Object.<anonymous> (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crconsole/index.js:23:12)    at /home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crconsole/index.js:167:7    at IncomingMessage.<anonymous> (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crconsole/node_modules/chrome-remote-interface/lib/chrome.js:104:13)    at IncomingMessage.EventEmitter.emit (events.js:117:20)
The code c

Then crmux fails this way:
/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crmux/crmux.js:103           msgObj.id = idMap.id;                            ^TypeError: Cannot read property 'id' of undefined    at WebSocket.<anonymous> (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crmux/crmux.js:103:29)    at WebSocket.EventEmitter.emit (events.js:98:17)    at Receiver.self._receiver.ontext (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crmux/node_modules/ws/lib/WebSocket.js:682:10)    at Receiver.opcodes.1.finish (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crmux/node_modules/ws/lib/Receiver.js:391:14)    at Receiver.expectHandler (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crmux/node_modules/ws/lib/Receiver.js:378:31)    at Receiver.add (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crmux/node_modules/ws/lib/Receiver.js:87:24)    at Socket.firstHandler (/home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crmux/node_modules/ws/lib/WebSocket.js:663:22)    at Socket.EventEmitter.emit (events.js:95:17)    at Socket.<anonymous> (_stream_readable.js:746:14)    at Socket.EventEmitter.emit (events.js:92:17)
The crmux code can be debugged with:

node-debug --preload 0 /home/awesome/tools/node-v0.10.26-linux-x86/lib/node_modules/crmux/crmux.js

The problem occurs when we can't map an upstream ID to a downstream one. That is going to take a bit before we can deal with it. It probably has to do with the DevTools debugger making sure that the IDs that it gets are correct ones, and that it does not see an ID that it does not understand.

I can probably solve this by opening a debugger on the debugger and debugging it.