diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
index 85b219cc694f9449716c8b37e67496d610aa4a7d..f040f723cb9c39b803c3307026f03c0dc342f0c8 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
@@ -23,6 +23,7 @@ import net.i2p.client.streaming.I2PServerSocket;
 import net.i2p.client.streaming.I2PSocket;
 import net.i2p.client.streaming.I2PSocketEepGet;
 import net.i2p.client.streaming.I2PSocketManager;
+import net.i2p.client.streaming.I2PSocketManager.DisconnectListener;
 import net.i2p.client.streaming.I2PSocketManagerFactory;
 import net.i2p.client.streaming.I2PSocketOptions;
 import net.i2p.data.Base32;
@@ -47,7 +48,7 @@ import org.klomp.snark.dht.KRPC;
  * so we can run multiple instances of single Snarks
  * (but not multiple SnarkManagers, it is still static)
  */
-public class I2PSnarkUtil {
+public class I2PSnarkUtil implements DisconnectListener {
     private final I2PAppContext _context;
     private final Log _log;
     private final String _baseName;
@@ -75,6 +76,7 @@ public class I2PSnarkUtil {
     private List<String> _openTrackers;
     private DHT _dht;
     private long _startedTime;
+    private final DisconnectListener _discon;
 
     private static final int EEPGET_CONNECT_TIMEOUT = 45*1000;
     private static final int EEPGET_CONNECT_TIMEOUT_SHORT = 5*1000;
@@ -91,17 +93,18 @@ public class I2PSnarkUtil {
 
 
     public I2PSnarkUtil(I2PAppContext ctx) {
-        this(ctx, "i2psnark");
+        this(ctx, "i2psnark", null);
     }
 
     /**
      *  @param baseName generally "i2psnark"
      *  @since Jetty 7
      */
-    public I2PSnarkUtil(I2PAppContext ctx, String baseName) {
+    public I2PSnarkUtil(I2PAppContext ctx, String baseName, DisconnectListener discon) {
         _context = ctx;
         _log = _context.logManager().getLog(Snark.class);
         _baseName = baseName;
+        _discon = discon;
         _opts = new HashMap<String, String>();
         //setProxy("127.0.0.1", 4444);
         setI2CPConfig("127.0.0.1", I2PClient.DEFAULT_LISTEN_PORT, null);
@@ -324,8 +327,11 @@ public class I2PSnarkUtil {
             if (opts.getProperty(I2PClient.PROP_GZIP) == null)
                 opts.setProperty(I2PClient.PROP_GZIP, "false");
             _manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
-            if (_manager != null)
+            if (_manager != null) {
                 _startedTime = _context.clock().now();
+                if (_discon != null)
+                    _manager.addDisconnectListener(this);
+            }
             _connecting = false;
         }
         if (_shouldUseDHT && _manager != null && _dht == null)
@@ -333,6 +339,19 @@ public class I2PSnarkUtil {
         return (_manager != null);
     }
     
+    /**
+     * DisconnectListener interface
+     * @since 0.9.53
+     */
+    public void sessionDisconnected() {
+        synchronized(this) {
+            _manager = null;
+            _connecting = false;
+        }
+        if (_discon != null)
+            _discon.sessionDisconnected();
+    }
+
     /**
      * @return null if disabled or not started
      * @since 0.8.4
diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java
index 1098d1fbec5c7988f7f34a6617b9122a5d28367b..50f2b2f57b138938a5e57c49ed1d760088cc735b 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java
@@ -1259,7 +1259,7 @@ public class Snark
    */
   private void fatalRouter(String s, Throwable t) throws RouterException {
     _log.error(s, t);
-    stopTorrent();
+    stopTorrent(true);
     if (completeListener != null)
         completeListener.fatal(this, s);
     throw new RouterException(s, t);
diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
index 1767a800714bbffa17fda6cf948910cb743e666a..3d96d44e0197ae13d0e431d3814a7a562a3f9421 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
@@ -31,6 +31,7 @@ import net.i2p.app.ClientAppManager;
 import net.i2p.app.ClientAppState;
 import net.i2p.app.NotificationService;
 import net.i2p.client.I2PClient;
+import net.i2p.client.streaming.I2PSocketManager.DisconnectListener;
 import net.i2p.crypto.SHA1Hash;
 import net.i2p.crypto.SigType;
 import net.i2p.data.Base64;
@@ -58,7 +59,7 @@ import org.klomp.snark.dht.KRPC;
 /**
  * Manage multiple snarks
  */
-public class SnarkManager implements CompleteListener, ClientApp {
+public class SnarkManager implements CompleteListener, ClientApp, DisconnectListener {
     
     /**
      *  Map of (canonical) filename of the .torrent file to Snark instance.
@@ -131,7 +132,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
     public static final String PROP_FILES_PUBLIC = "i2psnark.filesPublic";
     public static final String PROP_OLD_AUTO_START = "i2snark.autoStart";   // oops
     public static final String PROP_AUTO_START = "i2psnark.autoStart";      // convert in migration to new config file
-    public static final String DEFAULT_AUTO_START = "false";
+    private final boolean DEFAULT_AUTO_START;
     //public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
     //public static final String DEFAULT_LINK_PREFIX = "file:///";
     public static final String PROP_STARTUP_DELAY = "i2psnark.startupDelay";
@@ -269,7 +270,8 @@ public class SnarkManager implements CompleteListener, ClientApp {
         _contextName = ctxName;
         _log = _context.logManager().getLog(SnarkManager.class);
         _messages = new UIMessages(MAX_MESSAGES);
-        _util = new I2PSnarkUtil(_context, ctxName);
+        _util = new I2PSnarkUtil(_context, ctxName, this);
+        DEFAULT_AUTO_START = !ctx.isRouterContext();
         String cfile = ctxName + CONFIG_FILE_SUFFIX;
         File configFile = new File(cfile);
         if (!configFile.isAbsolute())
@@ -344,6 +346,18 @@ public class SnarkManager implements CompleteListener, ClientApp {
         }
     }
     
+    /**
+     * DisconnectListener interface
+     * @since 0.9.53
+     */
+    public void sessionDisconnected() {
+        if (!_context.isRouterContext()) {
+            addMessage(_t("Unable to connect to I2P"));
+            stopAllTorrents(true);
+            _stopping = false;
+        }
+    }
+    
     /*
      *  Called by the webapp at Jetty shutdown.
      *  Stops all torrents. Does not close the tunnel, so the announces have a chance.
@@ -465,7 +479,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
     }
 
     public boolean shouldAutoStart() {
-        return Boolean.parseBoolean(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START));
+        return Boolean.parseBoolean(_config.getProperty(PROP_AUTO_START, Boolean.toString(DEFAULT_AUTO_START)));
     }
     
     /**
@@ -816,7 +830,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
         if (!_config.containsKey(PROP_DIR))
             _config.setProperty(PROP_DIR, _contextName);
         if (!_config.containsKey(PROP_AUTO_START))
-            _config.setProperty(PROP_AUTO_START, DEFAULT_AUTO_START);
+            _config.setProperty(PROP_AUTO_START, Boolean.toString(DEFAULT_AUTO_START));
         if (!_config.containsKey(PROP_REFRESH_DELAY))
             _config.setProperty(PROP_REFRESH_DELAY, Integer.toString(DEFAULT_REFRESH_DELAY_SECS));
         if (!_config.containsKey(PROP_STARTUP_DELAY))
@@ -921,13 +935,22 @@ public class SnarkManager implements CompleteListener, ClientApp {
     }
 
 
-    /** call from DirMonitor since loadConfig() is called before router I2CP is up */
-    private void getBWLimit() {
-        if (!_config.containsKey(PROP_UPBW_MAX)) {
+    /**
+     * Call from DirMonitor since loadConfig() is called before router I2CP is up.
+     * We also use this as a test that the router is there for standalone.
+     *
+     * @return true if we got a response from the router
+     */
+    private boolean getBWLimit() {
+        boolean shouldSet = !_config.containsKey(PROP_UPBW_MAX);
+        if (shouldSet || !_context.isRouterContext()) {
             int[] limits = BWLimits.getBWLimits(_util.getI2CPHost(), _util.getI2CPPort());
-            if (limits != null && limits[1] > 0)
+            if (limits == null)
+                return false;
+            if (shouldSet && limits[1] > 0)
                 _util.setMaxUpBW(limits[1]);
         }
+        return true;
     }
 
     private void updateConfig() {
@@ -1578,7 +1601,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
         }
         if (dataDir == null)
             dataDir = getDataDir();
-        Snark torrent = null;
+        Snark torrent;
         synchronized (_snarks) {
             torrent = _snarks.get(filename);
         }
@@ -2497,6 +2520,13 @@ public class SnarkManager implements CompleteListener, ClientApp {
         addMessage(_t("Torrent removed: \"{0}\"", torrent.getBaseName()));
     }
     
+    /**
+     *  This calls monitorTorrents() once a minute.
+     *  It also gets the bandwidth limits and loads magnets on first run.
+     *  For standalone, it also handles checking that the external router is there,
+     *  and restarting torrents once the router appears.
+     *
+     */
     private class DirMonitor implements Runnable {
         public void run() {
             // don't bother delaying if auto start is false
@@ -2511,17 +2541,65 @@ public class SnarkManager implements CompleteListener, ClientApp {
 
             // here because we need to delay until I2CP is up
             // although the user will see the default until then
-            getBWLimit();
+            boolean routerOK = false;
             boolean doMagnets = true;
             while (_running) {
                 File dir = getDataDir();
                 if (_log.shouldLog(Log.DEBUG))
                     _log.debug("Directory Monitor loop over " + dir.getAbsolutePath());
+                if (routerOK &&
+                    (_context.isRouterContext() || _util.connected() || _util.isConnecting())) {
+                    autostart = shouldAutoStart();
+                } else {
+                    // Test if the router is there
+                    // For standalone, this will probe the router every 60 seconds if not connected
+                    boolean oldOK = routerOK;
+                    routerOK = getBWLimit();
+                    if (routerOK) {
+                        autostart = shouldAutoStart();
+                        if (autostart && !oldOK && !doMagnets && !_snarks.isEmpty()) {
+                            // Start previously added torrents
+                            for (Snark snark : _snarks.values()) {
+                                Properties config = getConfig(snark);
+                                String prop = config.getProperty(PROP_META_RUNNING);
+                                if (prop == null || Boolean.parseBoolean(prop)) {
+                                    if (!_util.connected()) {
+                                        addMessage(_t("Connecting to I2P"));
+                                        // getBWLimit() was successful so this should work
+                                        boolean ok = _util.connect();
+                                        if (!ok) {
+                                            if (_context.isRouterContext())
+                                                addMessage(_t("Unable to connect to I2P"));
+                                            else
+                                                addMessage(_t("Error connecting to I2P - check your I2CP settings!") + ' ' + _util.getI2CPHost() + ':' + _util.getI2CPPort());
+                                            routerOK = false;
+                                            autostart = false;
+                                            break;
+                                        }
+                                    }
+                                    addMessageNoEscape(_t("Starting up torrent {0}", linkify(snark)));
+                                    try {
+                                        snark.startTorrent();
+                                    } catch (Snark.RouterException re) {
+                                        // Snark.fatal() will log and call fatal() here for user message before throwing
+                                        break;
+                                    } catch (RuntimeException re) {
+                                        // Snark.fatal() will log and call fatal() here for user message before throwing
+                                    }
+                                }
+                            }
+                            if (routerOK)
+                                addMessage(_t("Up bandwidth limit is {0} KBps", _util.getMaxUpBW()));
+                        }
+                    } else {
+                        autostart = false;
+                    }
+                }
                 boolean ok;
                 try {
                     // Don't let this interfere with .torrent files being added or deleted
                     synchronized (_snarks) {
-                        ok = monitorTorrents(dir);
+                        ok = monitorTorrents(dir, autostart);
                     }
                 } catch (RuntimeException e) {
                     _log.error("Error in the DirectoryMonitor", e);
@@ -2535,7 +2613,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
                     } catch (RuntimeException e) {
                         _log.error("Error in the DirectoryMonitor", e);
                     }
-                    if (!_snarks.isEmpty())
+                    if (routerOK && !_snarks.isEmpty())
                         addMessage(_t("Up bandwidth limit is {0} KBps", _util.getMaxUpBW()));
                     // To fix bug where files were left behind,
                     // but also good for when user removes snarks when i2p is not running
@@ -2544,6 +2622,12 @@ public class SnarkManager implements CompleteListener, ClientApp {
                     // time i2psnark starts. See ticket #1658.
                     if (ok)
                         cleanupTorrentStatus();
+                    if (!routerOK) {
+                        if (_context.isRouterContext())
+                            addMessage(_t("Unable to connect to I2P"));
+                        else
+                            addMessage(_t("Error connecting to I2P - check your I2CP settings!") + ' ' + _util.getI2CPHost() + ':' + _util.getI2CPPort());
+                    }
                 }
                 try { Thread.sleep(60*1000); } catch (InterruptedException ie) {}
             }
@@ -2719,9 +2803,10 @@ public class SnarkManager implements CompleteListener, ClientApp {
     /**
      *  caller must synchronize on _snarks
      *
+     *  @param shouldStart should we autostart the torrents
      *  @return success, false if an error adding any torrent.
      */
-    private boolean monitorTorrents(File dir) {
+    private boolean monitorTorrents(File dir, boolean shouldStart) {
         boolean rv = true;
         File files[] = dir.listFiles(new FileSuffixFilter(".torrent"));
         List<String> foundNames = new ArrayList<String>(0);
@@ -2741,7 +2826,6 @@ public class SnarkManager implements CompleteListener, ClientApp {
         //if (_log.shouldLog(Log.DEBUG))
         //    _log.debug("DirMon found: " + DataHelper.toString(foundNames) + " existing: " + DataHelper.toString(existingNames));
         // lets find new ones first...
-        boolean shouldStart = shouldAutoStart();
         for (String name : foundNames) {
             if (existingNames.contains(name)) {
                 // already known.  noop