How to clone wp-admin and make a new dashboard controlled by your code?

In fact, the WP API (also named WP REST API or WP JSON API aims for that (aside from other goals). You can find the project in the repo and on GitHub.

The “API” mainly provides data access and (CRUD actions) via GET and POST request running to the /wp-json/ request/URi. You can fetch posts, post collections, users, media, comments and meta data for pretty much everything. The thing you don’t get is stuff like the importer and other “Tools”, Dashboard widgets, theme stuff or plugin activation, etc. Also plugins would have to add their own responses if the plugin is present or you will have to write adapters on your own.

The plugin aims to be part of WP Core with one of the next versions. Currently it’s not at the point where that happens, but development continues.

While it’s still a long journey to build a replacement for ~/wp-admin, you can simply register a custom endpoint and try to build your own (JavaScript) application there. In the interwebs you will find many pre-made admin interface frameworks (mostly built on top of stuff like Twitters Bootstrap, Foundation, etc.) that should allow you to build a very rough prototype with most admin stuff covered in one or two days (depending on your knowledge):

// Adds the \WP_Rewrite endpoint
add_action( 'init', function()
{
    add_rewrite_endpoint( 'custom-route', EP_NONE );
} );

// Adds your identifier for queries
add_filter( 'query_vars', function( $vars )
{
    $vars[] = 'custom-admin-identifier';
    return $vars;
} );

Make sure to visit the admin > options > permalinks page to flush your rewrite rules after that – or register an activation or deactivation callback that wraps flush_rewrite_rules().

Then you should be able to visit https://example.com/custom-route where you can do whatever pleases you. If you want to load custom templates there, jump in on template_redirect and load them:

add_filter( 'template_redirect', function( $template )
{
    # another option would to check:
    # array_key_exists( 'custom-admin-identifier', $GLOBALS['wp_query']->query_vars )

    if ( get_query_var( 'custom-admin-identifier' ) )
        return plugin_dir_path( __FILE__ ).'templates/index.php';

    return $template;
} );

which would load templates/index.php from your plugin and serve it.