diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml
index fab81f6b09..a8e71bcb95 100644
--- a/common/config/rush/pnpm-lock.yaml
+++ b/common/config/rush/pnpm-lock.yaml
@@ -56,6 +56,7 @@ specifiers:
   '@rush-temp/task-resources': file:./projects/task-resources.tgz
   '@rush-temp/text-editor': file:./projects/text-editor.tgz
   '@rush-temp/theme': file:./projects/theme.tgz
+  '@rush-temp/tool': file:./projects/tool.tgz
   '@rush-temp/ui': file:./projects/ui.tgz
   '@rush-temp/upload': file:./projects/upload.tgz
   '@rush-temp/view': file:./projects/view.tgz
@@ -84,6 +85,7 @@ specifiers:
   '@typescript-eslint/eslint-plugin': '4'
   '@typescript-eslint/parser': ^4.0.0
   autoprefixer: ^10.2.6
+  commander: ^8.1.0
   cors: ^2.8.5
   cross-env: ^7.0.3
   css-loader: ^5.2.1
@@ -176,6 +178,7 @@ dependencies:
   '@rush-temp/task-resources': file:projects/task-resources.tgz_c38cf1a7a413db8918b0b4754c21e4c5
   '@rush-temp/text-editor': file:projects/text-editor.tgz_c38cf1a7a413db8918b0b4754c21e4c5
   '@rush-temp/theme': file:projects/theme.tgz_c38cf1a7a413db8918b0b4754c21e4c5
+  '@rush-temp/tool': file:projects/tool.tgz_6c259fadfeb3a4b20890aefe87070b8b
   '@rush-temp/ui': file:projects/ui.tgz_c38cf1a7a413db8918b0b4754c21e4c5
   '@rush-temp/upload': file:projects/upload.tgz_6c259fadfeb3a4b20890aefe87070b8b
   '@rush-temp/view': file:projects/view.tgz_6c259fadfeb3a4b20890aefe87070b8b
@@ -204,6 +207,7 @@ dependencies:
   '@typescript-eslint/eslint-plugin': 4.28.5_a8e83fcad666e1ba86be4b2e27a20aea
   '@typescript-eslint/parser': 4.28.5_eslint@7.32.0+typescript@4.3.5
   autoprefixer: 10.3.1_postcss@8.3.6
+  commander: 8.1.0
   cors: 2.8.5
   cross-env: 7.0.3
   css-loader: 5.2.7_webpack@5.48.0
@@ -2798,6 +2802,11 @@ packages:
     engines: {node: '>= 10'}
     dev: false
 
+  /commander/8.1.0:
+    resolution: {integrity: sha512-mf45ldcuHSYShkplHHGKWb4TrmwQadxOn7v4WuhDJy0ZVoY5JFajaRDKD0PNe5qXzBX0rhovjTnP6Kz9LETcuA==}
+    engines: {node: '>= 12'}
+    dev: false
+
   /component-emitter/1.3.0:
     resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==}
     dev: false
@@ -10108,6 +10117,30 @@ packages:
       - typescript
     dev: false
 
+  file:projects/tool.tgz_6c259fadfeb3a4b20890aefe87070b8b:
+    resolution: {integrity: sha512-ZofT4DyGFGWG0s/geyBOmQalsgWxw6y563CJnfSX1NPSgQ9rkuWIfe2MyoTS1sOA5PhmNSzcBr//La4ZjR0gyw==, tarball: file:projects/tool.tgz}
+    id: file:projects/tool.tgz
+    name: '@rush-temp/tool'
+    version: 0.0.0
+    dependencies:
+      '@types/heft-jest': 1.0.2
+      '@typescript-eslint/eslint-plugin': 4.28.5_a8e83fcad666e1ba86be4b2e27a20aea
+      commander: 8.1.0
+      eslint: 7.32.0
+      eslint-plugin-import: 2.23.4_eslint@7.32.0
+      eslint-plugin-node: 11.1.0_eslint@7.32.0
+      eslint-plugin-promise: 4.3.1
+      mongodb: 4.1.1
+      ts-node: 10.2.1_typescript@4.3.5
+    transitivePeerDependencies:
+      - '@swc/core'
+      - '@swc/wasm'
+      - '@types/node'
+      - '@typescript-eslint/parser'
+      - supports-color
+      - typescript
+    dev: false
+
   file:projects/ui.tgz_c38cf1a7a413db8918b0b4754c21e4c5:
     resolution: {integrity: sha512-nqw2XVY89MoFfK662WYoko9Cu+aLj4f32RjKFdamRPs6ZZRyECkCV3JxAC+d+AYvGEPTLcfQyX2FAHtw94JISA==, tarball: file:projects/ui.tgz}
     id: file:projects/ui.tgz
diff --git a/dev/tool/.eslintrc.js b/dev/tool/.eslintrc.js
new file mode 100644
index 0000000000..89f8151bd4
--- /dev/null
+++ b/dev/tool/.eslintrc.js
@@ -0,0 +1,6 @@
+module.exports = {
+  extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
+  parserOptions: {
+    project: './tsconfig.json'
+  }
+}
\ No newline at end of file
diff --git a/dev/tool/.npmignore b/dev/tool/.npmignore
new file mode 100644
index 0000000000..e3ec093c38
--- /dev/null
+++ b/dev/tool/.npmignore
@@ -0,0 +1,4 @@
+*
+!/lib/**
+!CHANGELOG.md
+/lib/**/__tests__/
diff --git a/dev/tool/config/rig.json b/dev/tool/config/rig.json
new file mode 100644
index 0000000000..af1257a896
--- /dev/null
+++ b/dev/tool/config/rig.json
@@ -0,0 +1,18 @@
+// The "rig.json" file directs tools to look for their config files in an external package.
+// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
+{
+  "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
+
+  /**
+   * (Required) The name of the rig package to inherit from.
+   * It should be an NPM package name with the "-rig" suffix.
+   */
+  "rigPackageName": "@anticrm/platform-rig"
+
+  /**
+   * (Optional) Selects a config profile from the rig package.  The name must consist of
+   * lowercase alphanumeric words separated by hyphens, for example "sample-profile".
+   * If omitted, then the "default" profile will be used."
+   */
+  // "rigProfile": "your-profile-name"
+}
diff --git a/dev/tool/package.json b/dev/tool/package.json
new file mode 100644
index 0000000000..c626e70ae8
--- /dev/null
+++ b/dev/tool/package.json
@@ -0,0 +1,27 @@
+{
+  "name": "@anticrm/tool",
+  "version": "0.6.0",
+  "main": "lib/index.js",
+  "author": "Anticrm Platform Contributors",
+  "license": "EPL-2.0",
+  "scripts": {
+    "build": "heft build",
+    "lint:fix": "eslint --fix src",
+    "start": "ts-node src/index.ts"
+  },
+  "devDependencies": {
+    "@anticrm/platform-rig":"~0.6.0",
+    "@types/heft-jest":"^1.0.2",
+    "@typescript-eslint/eslint-plugin":"4",
+    "eslint-plugin-import":"2",
+    "eslint-plugin-promise":"4",
+    "eslint-plugin-node":"11",
+    "eslint":"^7.32.0",
+    "ts-node":"^10.2.1"
+  },
+  "dependencies": {
+    "mongodb":"^4.1.1",
+    "commander":"^8.1.0",
+    "@anticrm/account":"~0.6.0"
+  }
+}
diff --git a/dev/tool/src/index.ts b/dev/tool/src/index.ts
new file mode 100644
index 0000000000..b364739c05
--- /dev/null
+++ b/dev/tool/src/index.ts
@@ -0,0 +1,78 @@
+//
+// Copyright © 2020, 2021 Anticrm Platform Contributors.
+// Copyright © 2021 Hardcore Engineering Inc.
+//
+// Licensed under the Eclipse Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License. You may
+// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+import { program } from 'commander'
+import { MongoClient, Db } from 'mongodb'
+import { getAccount, createAccount, assignWorkspace, createWorkspace } from '@anticrm/account'
+
+const mongodbUri = process.env.MONGODB_URI ?? 'mongodb://localhost:27017'
+
+async function withDatabase (uri: string, f: (db: Db) => Promise<any>): Promise<void> {
+  console.log(`connecting to database '${uri}'...`)
+
+  const client = await MongoClient.connect(uri)
+  await f(client.db('account'))
+  await client.close()
+}
+
+program.version('0.0.1')
+
+// create-user john.appleseed@gmail.com --password 123 --workspace workspace --fullname "John Appleseed"
+program
+  .command('create-user <email>')
+  .description('create user and corresponding account in master database')
+  .requiredOption('-p, --password <password>', 'user password')
+  .requiredOption('-f, --fullname <fullname>', 'full user name')
+  .action(async (email, cmd) => {
+    return await withDatabase(mongodbUri, async (db) => {
+      await createAccount(db, email, cmd.password)
+      // await createContact(withTenant(client, cmd.workspace), email, cmd.fullname)
+    })
+  })
+
+program
+  .command('assign-workspace <email> <workspace>')
+  .description('assign workspace')
+  .action(async (email, workspace, cmd) => {
+    return await withDatabase(mongodbUri, async (db) => {
+      console.log(`assigning user ${email as string} to ${workspace as string}...`)
+      await assignWorkspace(db, email, workspace)
+    })
+  })
+
+program
+  .command('show-user <email>')
+  .description('show user')
+  .action(async (email) => {
+    return await withDatabase(mongodbUri, async (db) => {
+      const info = await getAccount(db, email)
+      console.log(info)
+    })
+  })
+
+program
+  .command('create-workspace <name>')
+  .description('create workspace')
+  .requiredOption('-o, --organization <organization>', 'organization name')
+  .action(async (workspace, cmd) => {
+    return await withDatabase(mongodbUri, async (db) => {
+      await createWorkspace(db, workspace, cmd.organization)
+
+      // await initDatabase(withTenant(client, workspace))
+    })
+  })
+
+program.parse(process.argv)
diff --git a/dev/tool/tsconfig.json b/dev/tool/tsconfig.json
new file mode 100644
index 0000000000..aeb0517b13
--- /dev/null
+++ b/dev/tool/tsconfig.json
@@ -0,0 +1,8 @@
+{
+  "extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
+
+  "compilerOptions": {
+    "rootDir": "./src",
+    "outDir": "./lib"
+  }
+}
\ No newline at end of file
diff --git a/rush.json b/rush.json
index c06204a7e3..f8df376852 100644
--- a/rush.json
+++ b/rush.json
@@ -751,5 +751,10 @@
       "projectFolder": "server/account",
       "shouldPublish": true
     },
+    {
+      "packageName": "@anticrm/tool",
+      "projectFolder": "dev/tool",
+      "shouldPublish": false
+    },
   ]
 }