How to handle system-uri-response in the main.js process

Continuing the discussion from Problem using nodejs tutorial code in other electron apps:
I am adapting the nodejs tutorial example as a CLI app with no GUI, so no browser window.

I can successfully send the auth request which brings the SAFE Browser to the front, and I auth the app. But I’m not sure how to handle the system-uri-response from within main.js (in the tutorial it happens in controller.js)

I naively tried the following code in my main.js but the handler is never called, even though I auth the app in SAFE Browser. I expect this is a simple issue but I could do with some help!

My app calls safenetwork.sendAuthRequest() which brings SAFE Browser to the front as expected, and I auth the app. But I never see the console.log('RECEIVED system-uri-response!!!!') output in the app.on('system-uri-response'..) handler.

app.on('system-uri-response', async (event, resAuthUri) => {
  console.log('RECEIVED system-uri-response!!!!')
  await safenetwork.uponAuthResponse(resAuthUri)
  const items = await safenetwork.getItems()
  let scope = angular.element(document.getElementById("planner")).scope();
  scope.$apply(() => {
    scope.ctrl.trips = items;

    .arguments('<param1> <param2>')
    .description('Boilerplate for a SAFE command line interface (CLI) App')
    .option('-n, --name <name>', 'explain -name here')
    .option('-f, --fps <fps>', 'explain -fps here')
    .action((source, destination) => {
      console.log('Attempting to authorise on SAFE Network...'))
      generator(source, destination,, program.fps).then(
            (success) => console.log(,
            (error) => console.log(

if (!process.argv.slice(2).length) {

Ideas? The rest of the code is essentially the same as the main.js from the nodejs tutorial - except that I’ve disabled showing the app’s browser window, which is why I can’t use the ipc.on('system-uri-response'...) code present in the tutorial, in controller.js

EDIT: Ahh! I wonder if I don’t have the correct path for the executable in my auth request. I’ll look into that, meanwhile, should that work with npm start or only with a packaged executable?

1 Like

What you are looking for is app.makeSingleInstance.

This is the piece that handles your application being executed by the system, once you approve authorisation.
Stick a log just under line 86 line 36 and you’ll see it ping.

After that, the URI response is sent, line 39, from the main process to the renderer process in controller.js via the system-uri-response IPC channel.

1 Like

Are we on the same page here? I’m making a CLI app so wasn’t planning to have a browser window at all - for now I’ve just commented out the window related code in main.js

I had it working with a window, and was able to handle the ipc.on('system-uri-response'...) but now I’m trying to do without the window and handle it in main.js with app.on('system-uri-response'...)

Only 81 lines in main.js?

Is there any particular reason you’re using Electron if you’re ditching the GUI?

To make it as easy to build as possible. We have apps which do this using electron. If we had something else (which works) that I can modify easily I’d consider using that.

And by build you mean distributing to multiple platforms like Windows and OSX?

I’m starting to understand your challenge here. Do you have the code from your OP on a repository at the moment?

I’ll settle for linux executable, but if it can target windows and mac that would be great.

I haven’t created a github repo yet but the code is essentially the nodejs tutorial, and then me trying to get the system-uri-response in the app rather than the window so I can strip the latter out. I also added a command (npm) so it handles parameters but don’t think that’s relevant. I’ll post the main.js to you by PM in case you want to see.

EDIT: I’m thinking maybe I should just hide the window for now and jump to a better CLI framework later. It just seems like this should be easily soluble by somebody who knows electron. :pray:

@happybeing, I assume you still have the following in your main.js:

If so, that’s the entry point of the response, and that code is trying to send the restAuthUri received to your renderer process/es, I presume you should replace the body of that function with your own logic.

Edit: and this other place is where you would also need to place your logic, this is for when you have your app running already so it doesn’t launch a new instance:


Never assume anything with me. :wink:

I hadn’t realised the app was sending system-uri-response so I think you have hit the nail on the head. Thanks very much. Will have a go with that.

UPDATE: not sorted yet but I’m going to start again with hunter’s safe-app-base and try my best to keep the auth working. Thanks for the hints. This still might be what I needed to know.


This topic gave me the idea to authorise without using Electron, as I initially thought it’s a distraction.

I’ll just leave this minimal viable example here, in case anyone might deem it useful:

const safeApp = require('@maidsafe/safe-node-app');

const info = {
    id: 'example', name: 'example', vendor: 'example',
    customExecPath: [process.execPath, __filename],

async function authorise() {
    const app = await safeApp.initializeApp(info);
    const uri = await app.auth.genAuthUri({});
    await app.auth.openUri(uri.uri);

(async () => {
    if (process.argv.length == 2) {
        await authorise();

    const app = await safeApp.fromAuthURI(info, process.argv[2]);

    // Authenticated and ready to rumble

Was a useful learning experience; haven’t tested it thoroughly yet. I understand now why Electron comes in handy as it manages the process and instance for you.

1 Like

I think I have this working now (with electron), but what’s still missing is the packaging to executable.

If there’s a way to package your stuff for linux, and ideally win/mac then this would be great.

1 Like

I’ve tried with It seems to be a little hard as the safe-node-app dynamically links to a library, which it expects to be at a certain path relative to the package scripts. When packaging everything into a single executable it won’t find the library.

It could be fixed by making it look for the libraries in the same directory as the executable.

So, your best bet would still be Electron! Using hunterlester/safe-app-base shouldn’t it be as simple as npm run package?

1 Like

I hit this too (for /**/safe-clip/node_modules/@maidsafe/safe-node-app/src/native/mock/ and I think I also get it with Hunter’s thing but I’ll need to go back to that to check.

I am trying to get it included by pkg by specifying it as an asset, but a few people seem to have failed to get that to work with other missing resources, so I’m not sure it works. I haven’t got it working yet.

The problem lies with the fact pkg changes the path the script thinks it’s executing at. (In Windows) It thinks it’s in C:\snapshot\project, so will look for the DLL there.

1 Like

I need to update the readme.
It’s setup so that you don’t have to package it for development.
You can run yarn start and it’ll receive the URI response back from the browser, once authorisation is approved.

npm run package will do though.

Testing just now, I was getting the same error as you about not being able to find module @maidsafe/safe-node-app.
yarn was pruning my resources.
I updated the repo just now to run use npm and it’s fine.

Were you able to solve the issue and still use yarn?

[EDIT]: I’ll require const safeApp2 = require('@maidsafe/safe-node-app') in the main process to see if I can get it to error just now.


fascinating to watch you guys working through this :slight_smile:


This is working now. Sorry @hunterlester I must have got confused somewhere so I shall carry on. See:

Thanks for your help!

If you have any ideas for how to solve the problem with pkg that would be good, so we can build CLI apps without electron. It looks like its almost there.


I’ll take some time to see how pkg works.

In my repo I’m simply using electron-packager


I started by following this and it works fine until I add const safeApp = require('@maidsafe/safe-node-app') and other stuff from your safe-app-base

1 Like