diff --git a/README.md b/README.md
deleted file mode 100644
index e3ca84c..0000000
--- a/README.md
+++ /dev/null
@@ -1,128 +0,0 @@
-# Manage your passwords!
-
-MPW is a little software which stores your passwords in an GPG encrypted file.
-MPW can synchronize your password with SSH or FTP.
-
-# Installation
-
-This program work with ruby >= 2.0
-
-* install ruby and rubygems on your computer
-* install xclip
-* gem install mpw
-
-# How to use
-
-* Show help
-```
-mpw --help
-```
-
-* Setup a new config file
-```
-mpw --setup
-mpw --setup --config /path/conf/file.cfg
-```
-
-* Create and setup a new wallet
-```
-mpw --setup-wallet --wallet new_wallet_name
-mpw --setup-wallet --wallet new_wallet_name --config /path/conf/file.cfg 
-```
-
-* Add a GPG key in wallet
-```
-mpw --add --key root@localhost.local
-mpw --add --key root@localhost.local --config /path/conf/file.cfg 
-mpw --add --key root@localhost.local --wallet wallet_name
-mpw --add --key root@localhost.local --config /path/conf/file.cfg --wallet wallet_name
-```
-
-* Add a new  GPG key in wallet
-```
-mpw --add --key root@localhost.local --file /path/gpg/file.pub
-mpw --add --key root@localhost.local --file /path/gpg/file.pub --config /path/conf/file.cfg 
-mpw --add --key root@localhost.local --file /path/gpg/file.pub --wallet wallet_name
-mpw --add --key root@localhost.local --file /path/gpg/file.pub --config /path/conf/file.cfg --wallet wallet_name
-```
-
-* Delete a GPG key in wallet
-```
-mpw --delete --key root@localhost.local
-mpw --delete --key root@localhost.local --wallet wallet_name
-mpw --delete --key root@localhost.local --wallet wallet_name --config /path/conf/file.cfg 
-```
-
-* Add a new item in wallet
-```
-mpw --add 
-mpw --add --config /path/conf/file.cfg
-mpw --add --wallet wallet_name
-mpw --add --config /path/conf/file.cfg --wallet wallet_name
-```
-
-* Update an item
-```
-mpw --update --id uniq_id
-mpw --update --id uniq_id --config /path/conf/file.cfg
-mpw --update --id uniq_id --wallet wallet_name
-mpw --update --id uniq_id --config /path/conf/file.cfg --wallet wallet_name
-```
-
-* Delete an item
-```
-mpw --delete --id uniq_id
-mpw --delete --id uniq_id --config /path/conf/file.cfg
-mpw --delete --id uniq_id --wallet wallet_name
-mpw --delete --id uniq_id --config /path/conf/file.cfg --wallet wallet_name
-```
-
-* Show an item
-```
-mpw --show 'string to search'
-mpw --show 'string to search' --config /path/conf/file.cfg
-mpw --show 'string to search' --wallet wallet_name
-mpw --show 'string to search' --config /path/conf/file.cfg --wallet wallet_name
-mpw --show 'string to search' --group group_name
-mpw --show 'string to search' --group group_name --config /path/conf/file.cfg
-mpw --show 'string to search' --group group_name --wallet wallet_name
-mpw --show 'string to search' --group group_name --config /path/conf/file.cfg --wallet wallet_name
-```
-
-* Export data in YAML file
-```
-mpw --export --file /path/file/to/export.yml
-mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg
-mpw --export --file /path/file/to/export.yml --wallet wallet_name
-mpw --export --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name
-```
-
-* Import data from YAML file
-```
-mpw --import --file /path/file/to/export.yml
-mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg
-mpw --import --file /path/file/to/export.yml --wallet wallet_name
-mpw --import --file /path/file/to/export.yml --config /path/conf/file.cfg --wallet wallet_name
-```
-
-Format file to import:
-```
-1:
-  name: Website perso
-  group: Perso
-  host: localhost.local
-  protocol: ftp
-  user: test
-  password: letoortue
-  port: 21
-  comment: Mysuper website
-2:
-  name: Linuxfr
-  group: Pro
-  host: Linuxfr.org
-  protocol: https
-  user: test
-  password: coucou 
-  port: 
-  comment: 
-```
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..a62c1e2
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,53 @@
+MPW: Manage your passwords!
+*******************************************************
+
+mpw is a little software which stores your passwords in `GnuPG <http://www.gnupg.org/>` encrypted files.
+
+Features
+========
+
+* generate OTP code
+* synchronize your passwords with SSH or FTP.
+* copy your login, password or otp in clipboard
+
+Install
+=======
+
+On debian or ubuntu::
+
+	apt install ruby ruby-dev xclip
+	gem install mpw
+
+
+How to use
+==========
+
+A simple mpw usage::
+
+	mpw config --init user@host.com
+	mpw add
+	mpw copy
+	mpw add
+	mpw list
+
+Output::
+
+	Bank
+	 ==============================================================================
+	  ID | Host          | User      | Protocol | Port | OTP | Comment                
+	 ==============================================================================
+	  1  | bank.com      | 1234456   | https    |      |  X  |                        
+
+	Linux
+	 ==============================================================================
+	  ID | Host          | User      | Protocol | Port | OTP | Comment                
+	 ==============================================================================
+	  2  | linuxfr.org   | example   | https    |      |     | Da Linux French Site
+
+
+Licence |License|
+=================
+
+Full license here: `LICENSE <https://github.com/nishiki/manage-password/blob/master/LICENSE>`
+
+.. |License| image:: https://img.shields.io/badge/license-GPL--2.0-blue.svg
diff --git a/VERSION b/VERSION
index e4604e3..c0de572 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.2.1
+4.0.0-beta
diff --git a/bin/mpw b/bin/mpw
index f5e717b..2d32700 100755
--- a/bin/mpw
+++ b/bin/mpw
@@ -18,13 +18,9 @@
 
 $: << File.expand_path('../../lib', __FILE__)
 
-require 'optparse'
 require 'locale'
 require 'set'
 require 'i18n'
-require 'mpw/mpw'
-require 'mpw/config'
-require 'mpw/cli'
 
 # --------------------------------------------------------- #
 # Set local
@@ -45,190 +41,9 @@ I18n.locale         = lang.to_sym
 # Options
 # --------------------------------------------------------- #
 
-options_password    = {}
-options             = {}
-options[:force]     = false
-options[:otp]       = false
-options[:sync]      = true
-options[:clipboard] = true
-options[:group]     = nil
-options[:config]    = nil
-options[:wallet]    = nil
+bin_dir = File.dirname(__FILE__)
+command = "#{bin_dir}/mpw-#{ARGV[0]}"
 
-OptionParser.new do |opts|
-	opts.banner = "#{I18n.t('option.usage')}: mpw [options]"
-
-	opts.on('-a', '--add', I18n.t('option.add')) do
-		options[:add] = true
-	end
-
-	opts.on('-A', '--show-all', I18n.t('option.show_all')) do
-		options[:type] = nil
-		options[:show] = ''
-	end
-
-	opts.on('-c', '--config CONFIG', I18n.t('option.config')) do |config|
-		options[:config] = config
-	end
-
-	opts.on('-C', '--no-clipboard', I18n.t('option.clipboard')) do
-		options[:clipboard] = false
-	end
-
-	opts.on('-d', '--delete', I18n.t('option.remove')) do
-		options[:delete] = true
-	end
-
-	opts.on('-e', '--export', I18n.t('option.export')) do
-		options[:export] = true
-	end
-
-	opts.on('-f', '--file FILE', I18n.t('option.file')) do |file|
-		options[:file] = file
-	end
-
-	opts.on('-F', '--force', I18n.t('option.force')) do
-		options[:force] = true
-	end
-
-	opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group|
-		options[:group] = group
-	end
-
-	opts.on('-G', '--generate-password [LENGTH]', I18n.t('option.generate_password')) do |length|
-		options_password[:length] = length
-	end
-
-	opts.on('-h', '--help', I18n.t('option.help')) do
-		puts opts
-		exit 0
-	end
-
-	opts.on('-i', '--id ID', I18n.t('option.id')) do |id|
-		options[:id] = id
-	end
-
-	opts.on('-I', '--import', I18n.t('option.import')) do
-		options[:import] = true
-	end
-
-	opts.on('-k', '--key KEY', I18n.t('option.key')) do |key|
-		options[:key] = key
-	end
-
-	opts.on('-n', '--numeric', I18n.t('option.numeric')) do
-		options_password[:numeric] = true
-	end
-
-	opts.on('-N', '--no-sync', I18n.t('option.no_sync')) do
-		options[:sync] = false
-	end
-
-	opts.on('-O', '--otp', I18n.t('option.otp')) do
-		options[:otp] = true
-	end
-
-	opts.on('-s', '--show [SEARCH]', I18n.t('option.show')) do |search|
-		search.nil? ? (options[:show]  = '')  : (options[:show] = search)
-	end
-
-	opts.on('-S', '--setup', I18n.t('option.setup')) do
-		options[:setup] = true
-	end
-
-	opts.on('-u', '--update', I18n.t('option.update')) do
-		options[:update] = true
-	end
-
-	opts.on('-w', '--wallet WALLET', I18n.t('option.wallet')) do |wallet|
-		options[:wallet] = wallet
-	end
-
-	opts.on('-W', '--setup-wallet', I18n.t('option.setup_wallet')) do
-		options[:setup_wallet] = true
-	end
-
-	opts.on('-x', '--special-chars', I18n.t('option.special_chars')) do
-		options_password[:special] = true
-	end
-
-	opts.on('-y', '--alpha', I18n.t('option.alpha')) do
-		options_password[:alpha] = true
-	end
-end.parse!
-
-# --------------------------------------------------------- #
-# Main
-# --------------------------------------------------------- #
-
-# Generate password
-if not options_password.empty?
-	puts MPW::MPW::password(options_password)
-	exit 0
-end
-
-begin
-	config = MPW::Config.new(options[:config])
-	cli    = MPW::Cli.new(config, options[:clipboard], options[:sync], options[:otp])
-		
-	# Setup a new config 
-	if not options[:setup].nil?
-		cli.setup(lang)
-		exit 0
-	end
-
-	cli.setup(lang)   if not config.is_valid?
-	cli.setup_gpg_key if not config.check_gpg_key?
-	
-	cli.get_wallet(options[:wallet])
-	cli.decrypt
-	
-	# Display the item's informations
-	if not options[:show].nil?
-		opts = {search:    options[:show],
-		        group:     options[:group],
-		       }
-	
-		cli.display(opts)
-	
-	# Remove an item
-	elsif not options[:delete].nil? and not options[:id].nil?
-		cli.delete(options[:id], options[:force])
-	
-	# Update an item
-	elsif not options[:update].nil? and not options[:id].nil?
-		cli.update(options[:id])
-	
-	# Add a new item
-	elsif not options[:add].nil? and options[:key].nil?
-		cli.add
-	
-	# Add a new public key in wallet
-	elsif not options[:add].nil? and not options[:key].nil?
-		cli.add_key(options[:key], options[:file])
-	
-	# Delete a public key in wallet
-	elsif not options[:delete].nil? and not options[:key].nil?
-		cli.delete_key(options[:key])
-	
-	# Export
-	elsif not options[:export].nil? and not options[:file].nil?
-		cli.export(options[:file])
-	
-	# Add a new item
-	elsif not options[:import].nil? and not options[:file].nil?
-		cli.import(options[:file])
-	
-	# Setup wallet config
-	elsif not options[:setup_wallet].nil?
-		cli.setup_wallet_config
-	
-	end
-	
-	cli = nil
-	
-	exit 0
-
-rescue SystemExit, Interrupt
-	exit 3
+if Dir.glob("#{bin_dir}/mpw-*").include?("#{command}")
+	Kernel.load(command)
 end
diff --git a/bin/mpw-add b/bin/mpw-add
new file mode 100644
index 0000000..5322cc1
--- /dev/null
+++ b/bin/mpw-add
@@ -0,0 +1,61 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/config'
+require 'mpw/cli'
+
+# --------------------------------------------------------- #
+# Options
+# --------------------------------------------------------- #
+
+options        = {}
+options[:sync] = true
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw add [options]"
+
+	opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
+		options[:config] = config
+	end
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
+		options[:sync] = false
+	end
+
+	opts.on('-r', '--random', I18n.t('option.random_password')) do
+		options[:password] = true
+	end
+
+	opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
+		options[:wallet] = wallet
+	end
+end.parse!
+
+config = MPW::Config.new(options[:config])
+cli    = MPW::Cli.new(config, options[:sync])
+
+cli.load_config
+cli.get_wallet(options[:wallet])
+cli.decrypt
+cli.add(options[:password])
diff --git a/bin/mpw-config b/bin/mpw-config
new file mode 100644
index 0000000..120da5b
--- /dev/null
+++ b/bin/mpw-config
@@ -0,0 +1,75 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/config'
+require 'mpw/cli'
+
+# --------------------------------------------------------- #
+# Options
+# --------------------------------------------------------- #
+
+options = {}
+values  = {}
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw config [options]"
+
+	opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
+		options[:config] = config
+	end
+
+	opts.on('-g', '--gpg-exe PATH', I18n.t('option.gpg_exe')) do |gpg_exe|
+		values[:gpg_exe] = gpg_exe
+	end
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('-i', '--init GPG_KEY', I18n.t('option.init')) do |gpg_key|
+		options[:init]   = true
+		values[:gpg_key] = gpg_key
+	end
+
+	opts.on('-k', '--key GPG_KEY', I18n.t('option.gpg_key')) do |gpg_key|
+		values[:gpg_key] = gpg_key
+	end
+
+	opts.on('-l', '--lang LANG', I18n.t('option.lang')) do |lang|
+		values[:lang] = lang
+	end
+
+	opts.on('-w', '--wallet-dir PATH', I18n.t('option.wallet_dir')) do |wallet_dir|
+		values[:wallet_dir] = wallet_dir
+	end
+end.parse!
+
+config = MPW::Config.new(options[:config])
+cli    = MPW::Cli.new(config, nil)
+
+if not options[:init].nil?
+	cli.setup(values)
+	cli.load_config
+	cli.get_wallet
+	cli.setup_gpg_key(options[:init])
+	cli.setup_wallet_config
+else
+	cli.set_config(values)
+end
diff --git a/bin/mpw-copy b/bin/mpw-copy
new file mode 100644
index 0000000..0a14ed7
--- /dev/null
+++ b/bin/mpw-copy
@@ -0,0 +1,71 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/config'
+require 'mpw/cli'
+
+# --------------------------------------------------------- #
+# Options
+# --------------------------------------------------------- #
+
+options             = {}
+options[:sync]      = true
+options[:clipboard] = true
+values              = {}
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw copy [options]"
+
+	opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
+		options[:config] = config
+	end
+
+	opts.on('-d', '--disable-clipboard', I18n.t('option.clipboard')) do
+		options[:clipboard] = false
+	end
+
+	opts.on('-g', '--group NAME', I18n.t('option.group')) do |group|
+		values[:group] = group
+	end
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
+		options[:sync] = false
+	end
+
+	opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
+		values[:pattern] = pattern
+	end
+
+	opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
+		options[:wallet] = wallet
+	end
+end.parse!
+
+config = MPW::Config.new(options[:config])
+cli    = MPW::Cli.new(config, options[:sync])
+
+cli.load_config
+cli.get_wallet(options[:wallet])
+cli.decrypt
+cli.copy(options[:clipboard], values)
diff --git a/bin/mpw-delete b/bin/mpw-delete
new file mode 100644
index 0000000..2d79e6a
--- /dev/null
+++ b/bin/mpw-delete
@@ -0,0 +1,66 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/config'
+require 'mpw/cli'
+
+# --------------------------------------------------------- #
+# Options
+# --------------------------------------------------------- #
+
+options        = {}
+options[:sync] = true
+values         = {}
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw delete [options]"
+
+	opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
+		options[:config] = config
+	end
+
+	opts.on('-g', '--group NAME', I18n.t('option.group')) do |group|
+		values[:group] = group
+	end
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
+		options[:sync] = false
+	end
+
+	opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
+		values[:pattern] = pattern
+	end
+
+	opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
+		options[:wallet] = wallet
+	end
+end.parse!
+
+config = MPW::Config.new(options[:config])
+cli    = MPW::Cli.new(config, options[:sync])
+
+cli.load_config
+cli.get_wallet(options[:wallet])
+cli.decrypt
+cli.delete(values)
diff --git a/bin/mpw-export b/bin/mpw-export
new file mode 100644
index 0000000..f891873
--- /dev/null
+++ b/bin/mpw-export
@@ -0,0 +1,70 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/config'
+require 'mpw/cli'
+
+# --------------------------------------------------------- #
+# Options
+# --------------------------------------------------------- #
+
+options        = {}
+options[:sync] = true
+values         = {}
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]"
+
+	opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
+		options[:config] = config
+	end
+
+	opts.on('-f', '--file PATH', I18n.t('option.file_export')) do |file|
+		options[:file] = file
+	end
+
+	opts.on('-g', '--group GROUP', I18n.t('option.group')) do |group|
+		values[:group] = group
+	end
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
+		options[:sync] = false
+	end
+
+	opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
+		values[:pattern] = pattern
+	end
+
+	opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
+		options[:wallet] = wallet
+	end
+end.parse!
+
+config = MPW::Config.new(options[:config])
+cli    = MPW::Cli.new(config, options[:sync])
+
+cli.load_config
+cli.get_wallet(options[:wallet])
+cli.decrypt
+cli.export(options[:file], values)
diff --git a/bin/mpw-genpwd b/bin/mpw-genpwd
new file mode 100644
index 0000000..8af4290
--- /dev/null
+++ b/bin/mpw-genpwd
@@ -0,0 +1,50 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/mpw'
+
+options = {}
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw passwd [options]"
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('-l', '--length NUMBER', I18n.t('option.length')) do |length|
+		options[:length] = length.to_i
+	end
+
+	opts.on('-n', '--numeric', I18n.t('option.numeric')) do
+		options[:numeric] = true
+	end
+
+	opts.on('-s', '--special-chars', I18n.t('option.special_chars')) do
+		options[:special] = true
+	end
+
+	opts.on('-a', '--alpha', I18n.t('option.alpha')) do
+		options[:alpha] = true
+	end
+end.parse!
+
+puts MPW::MPW::password(options)
+exit 0
diff --git a/bin/mpw-import b/bin/mpw-import
new file mode 100644
index 0000000..c740252
--- /dev/null
+++ b/bin/mpw-import
@@ -0,0 +1,61 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/config'
+require 'mpw/cli'
+
+# --------------------------------------------------------- #
+# Options
+# --------------------------------------------------------- #
+
+options        = {}
+options[:sync] = true
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw import [options]"
+
+	opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
+		options[:config] = config
+	end
+
+	opts.on('-f', '--file PATH', I18n.t('option.file_import')) do |file|
+		options[:file] = file
+	end
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
+		options[:sync] = false
+	end
+
+	opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
+		options[:wallet] = wallet
+	end
+end.parse!
+
+config = MPW::Config.new(options[:config])
+cli    = MPW::Cli.new(config, options[:sync])
+
+cli.load_config
+cli.get_wallet(options[:wallet])
+cli.decrypt
+cli.import(options[:file])
diff --git a/bin/mpw-list b/bin/mpw-list
new file mode 100644
index 0000000..9d18b0d
--- /dev/null
+++ b/bin/mpw-list
@@ -0,0 +1,66 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/config'
+require 'mpw/cli'
+
+# --------------------------------------------------------- #
+# Options
+# --------------------------------------------------------- #
+
+options        = {}
+options[:sync] = true
+values         = {}
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw list [options]"
+
+	opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
+		options[:config] = config
+	end
+
+	opts.on('-g', '--group NAME', I18n.t('option.group')) do |group|
+		values[:group] = group
+	end
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
+		values[:pattern] = pattern
+	end
+
+	opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
+		options[:sync] = false
+	end
+
+	opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
+		options[:wallet] = wallet
+	end
+end.parse!
+
+config = MPW::Config.new(options[:config])
+cli    = MPW::Cli.new(config, options[:sync])
+
+cli.load_config
+cli.get_wallet(options[:wallet])
+cli.decrypt
+cli.list(values)
diff --git a/bin/mpw-update b/bin/mpw-update
new file mode 100644
index 0000000..301b876
--- /dev/null
+++ b/bin/mpw-update
@@ -0,0 +1,66 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/config'
+require 'mpw/cli'
+
+# --------------------------------------------------------- #
+# Options
+# --------------------------------------------------------- #
+
+options        = {}
+options[:sync] = true
+values         = {}
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw update [options]"
+
+	opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
+		options[:config] = config
+	end
+
+	opts.on('-g', '--group NAME', I18n.t('option.group')) do |group|
+		values[:group] = group
+	end
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
+		options[:sync] = false
+	end
+
+	opts.on('-p', '--pattern PATTERN', I18n.t('option.pattern')) do |pattern|
+		values[:pattern] = pattern
+	end
+
+	opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
+		options[:wallet] = wallet
+	end
+end.parse!
+
+config = MPW::Config.new(options[:config])
+cli    = MPW::Cli.new(config, options[:sync])
+
+cli.load_config
+cli.get_wallet(options[:wallet])
+cli.decrypt
+cli.update(values)
diff --git a/bin/mpw-wallet b/bin/mpw-wallet
new file mode 100644
index 0000000..b81e6b2
--- /dev/null
+++ b/bin/mpw-wallet
@@ -0,0 +1,91 @@
+#!/usr/bin/ruby
+# MPW is a software to crypt and manage your passwords
+# Copyright (C) 2016  Adrien Waksberg <mpw@yae.im>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+require 'optparse'
+require 'mpw/config'
+require 'mpw/cli'
+
+# --------------------------------------------------------- #
+# Options
+# --------------------------------------------------------- #
+
+options        = {}
+options[:sync] = {}
+values         = {}
+
+OptionParser.new do |opts|
+	opts.banner = "#{I18n.t('option.usage')}: mpw wallet [options]"
+
+	opts.on('-c', '--config PATH', I18n.t('option.config')) do |config|
+		options[:config] = config
+	end
+
+	opts.on('-h', '--help', I18n.t('option.help')) do
+		puts opts
+		exit 0
+	end
+
+	opts.on('--host NAME', I18n.t('option.host')) do |host|
+		values[:host] = host
+	end
+
+	opts.on('-l', '--list', I18n.t('option.list')) do |list|
+		options[:list] = true
+	end
+
+	opts.on('-n', '--no-sync', I18n.t('option.no_sync')) do
+		options[:sync] = false
+	end
+
+	opts.on('--password', I18n.t('option.password')) do
+		values[:password] = true
+	end
+
+	opts.on('--path PATH', I18n.t('option.path')) do |path|
+		values[:path] = path
+	end
+
+	opts.on('--port NUMBER', I18n.t('option.port')) do |port|
+		values[:port] = port
+	end
+
+	opts.on('--protocol NAME', I18n.t('option.protocol')) do |protocol|
+		values[:protocol] = protocol
+	end
+
+	opts.on('--user NAME', I18n.t('option.user')) do |user|
+		values[:user] = user
+	end
+
+	opts.on('-w', '--wallet NAME', I18n.t('option.wallet')) do |wallet|
+		options[:wallet] = wallet
+	end
+end.parse!
+
+config = MPW::Config.new(options[:config])
+cli    = MPW::Cli.new(config, options[:sync])
+
+cli.load_config
+
+if not options[:list].nil?
+	cli.list_wallet
+else
+	cli.get_wallet(options[:wallet])
+	cli.decrypt
+	cli.setup_wallet_config(values)
+end
diff --git a/i18n/en.yml b/i18n/en.yml
index c704849..9a964d2 100644
--- a/i18n/en.yml
+++ b/i18n/en.yml
@@ -3,15 +3,13 @@ en:
   error:
     config:
       write: "Can't write the config file!"
-      check: "Checkconfig failed!"
+      load: "Checkconfig failed!"
       key_bad_format: "The key string isn't in good format!"
       no_key_public: "You haven't the public key of %{key}!"
       genkey_gpg:
         exception: "Can't create the GPG key!"
         name: "You must define a name for your GPG key!"
         password: "You must define a password for your GPG key!"
-    delete:
-      id_no_exist: "Can't delete the item %{id}, it doesn't exist!"
     export: "Can't export, unable to write in %{file}!"
     gpg_file: 
       decrypt: "Can't decrypt file!"
@@ -41,41 +39,51 @@ en:
     config: "Specify the configuration file to use"
     clipboard: "Disable the clipboard feature"
     export: "Export a wallet in an yaml file"
-    file: "Specify a file, to use with the options [--import | --export | --add]"
+    file_export: "Specify the file where export data"
+    file_import: "Specify the file to import"
     force: "No ask to confirm when you delete an item"
     generate_password: "Generate a random password (default 8 characters)"
+    gpg_exe: "Set the gpg binary path to use"
+    gpg_key: "Specify a GPG key (ex: user@example.com)"
     group: "Search the items with specified group"
     help: "Show this help message"
-    id: "Specify an id, to use with the options [--delete | --update]"
+    host: "Specify the server for the synchronization"
+    init: "Initialize mpw"
     import: "Import item since a yaml file"
-    key: "Specify the key name, to use with the options [--add | --delete | --update]"
+    key: "Specify the key name"
+    lang: "Set the software language"
+    list: "List the wallets"
     no_sync: "Disable synchronization with the server"
     numeric: "Use number to generate a password"
+    password: "Change the password for the synchronization"
+    path: "Specify the remote path"
+    pattern: "Given search pattern"
+    port: "Specify the connection port"
+    protocol: "Specify the protocol for the connection"
     setup: "Create a new configuration file" 
     setup_wallet: "Create a new configuration file for a wallet"
     special_chars: "Use special char to generate a password"
     show: "Search and show the items"
     show_all: "List all items"
-    remove: "Delete an item"
-    update: "Update an item"
     usage: "Usage"
+    user: "Specify the user for the connection"
     wallet: "Specify a wallet to use"
+    wallet_dir: "Set the wallets folder"
 
   form:
     select: "Select the item: "
     add_key:
       valid: "Key has been added!"
     add_item:
-      title: "Add a new item"
-      name: "Enter the name: "
-      group: "Enter the group (optional): "
-      server: "Enter the hostname or ip: "
-      protocol: "Enter the protocol of the connection (ssh, http, other): "
-      login: "Enter the login connection: "
-      password: "Enter the the password: "
-      port: "Enter the connection port (optional): "
-      comment: "Enter a comment (optional): "
-      otp_key: "Enter the otp secret (base32 secret key): "
+      name: "The item's name (mandatory"
+      group: "The group's name"
+      host: "The hostname or ip"
+      protocol: "The protocol of the connection (ssh, http, ...)"
+      login: "The login of connection"
+      password: "The password"
+      port: "The connection port"
+      comment: "A comment"
+      otp_key: "The OTP secret"
       valid: "Item has been added!"
     clipboard:
       choice: "What do you want to copy ? [q = quit, p = password, l = login]: "
@@ -88,12 +96,12 @@ en:
          login: "Press <l> to copy the login"
          password: "Press <p> to copy the password"
          otp_code: "Press <o> to copy the otp code"
+         quit: "Press <q> to quit"
     delete_key:
       valid: "Key has been deleted!"
     delete_item:
-      ask: "Are you sure you want to remove the item %{id} ?"
-      valid: "The item %{id} has been removed!"
-      not_valid: "The item %{id} hasn't been removed, because it doesn't exist!"
+      ask: "Are you sure you want to remove the item ?"
+      valid: "The item has been removed!"
     import:
       ask: "Are you sure you want to import this file %{file} ?"
       valid: "The import is succesfull!"
@@ -127,16 +135,15 @@ en:
       wait: "Please waiting during the GPG key generate, this process can take few minutes."
       valid: "Your GPG key has been created ;-)"
     update_item:
-      title: "Update an item"
-      name: "Enter the name [%{name}]: "
-      group: "Enter the group [%{group}]: "
-      server: "Enter the hostname or ip [%{server}]: "
-      protocol: "Enter the protocol of the connection [%{protocol}]: "
-      login: "Enter the login connection [%{login}]: "
-      password: "Enter the the password: "
-      port: "Enter the connection port [%{port}]: "
-      comment: "Enter a comment [%{comment}]: "
-      otp_key: "Enter the otp secret (base32 secret key): "
+      name: "The item's name (mandatory"
+      group: "The group's name"
+      host: "The hostname or ip"
+      protocol: "The protocol of the connection (ssh, http, ...)"
+      login: "The login of connection"
+      password: "The password (leave empty if you don't want change)"
+      port: "The connection port"
+      comment: "A comment"
+      otp_key: "The OTP secret (leave empty if you don't want change"
       valid: "Item has been updated!" 
     export:
       valid: "The export in %{file} is succesfull!"
diff --git a/i18n/fr.yml b/i18n/fr.yml
index 41cac4d..d2cae5b 100644
--- a/i18n/fr.yml
+++ b/i18n/fr.yml
@@ -3,15 +3,13 @@ fr:
   error:
     config:
       write: "Impossible d'écrire le fichier de configuration!"
-      check: "Le fichier de configuration est invalide!"
+      load: "Le fichier de configuration est invalide!"
       key_bad_format: "La clé GPG est invalide!"
       no_key_public: "Vous ne possédez pas la clé publique de %{key}!"
       genkey_gpg:
         exception: "La création de la clé GPG n'a pas pu aboutir!"
         name: "Vous devez définir un nom pour votre clé GPG!"
         password: "Vous devez définir un mot de passe pour votre clé GPG!"
-    delete:
-      id_no_exist: "Impossible de supprimer l'élément %{id}, car il n'existe pas!"
     export: "Impossible d'exporter les données dans le fichier %{file}!"
     gpg_file: 
       decrypt: "Impossible de déchiffrer le fichier GPG!"
@@ -41,41 +39,51 @@ fr:
     config: "Spécifie le fichier de configuration à utiliser"
     clipboard: "Désactive la fonction presse papier"
     export: "Exporte un portefeuille dans un fichier yaml"
-    file: "Spécifie un fichier, à utiliser avec les options [--import | --export | --add]"
+    file_export: "Spécifie le fichier où exporter les données"
+    file_import: "Spécifie le fichier à importer"
     force: "Ne demande pas de confirmation pour la suppression d'un élément"
     generate_password: "Génére un mot de passe aléatoire (défaut 8 caractères)"
+    gpg_exe: "Spécifie le chemin du binaire gpg à utiliser"
+    gpg_key: "Spécifie une clé GPG (ex: user@example.com)"
     group: "Recherche les éléments appartenant au groupe spécifié"
     help: "Affiche ce message d'aide"
-    id: "Spécifie un identifiant, à utiliser avec les options [--delete | --update]"
+    host: "Spécifie le serveur pour la synchronisation"
     import: "Importe des éléments depuis un fichier yaml"
-    key: "Spécifie le nom d'une clé, à utiliser avec les options [--add | --delete | --update]"
+    init: "Initialise mpw"
+    key: "Spécifie le nom d'une clé"
+    lang: "Spécifie la langue du logiciel (ex: fr)"
+    list: "Liste les portefeuilles"
     no_sync: "Désactive la synchronisation avec le serveur"
     numeric: "Utilise des chiffre dans la génération d'un mot de passe"
+    password: "Changer le mot de passe de connexion"
+    path: "Spécifie le chemin distant"
+    pattern: "Motif de donnée à chercher"
+    port: "Spécifie le port de connexion"
+    protocol: "Spécifie le protocol utilisé pour la connexion"
     setup: "Création d'un nouveau fichier de configuration"
     setup_wallet: "Création d'un nouveau fichier de configuration pour un portefeuille"
     special_chars: "Utilise des charactères speciaux dans la génération d'un mot de passe"
     show: "Recherche et affiche les éléments"
     show_all: "Liste tous les éléments"
-    remove: "Supprime un élément"
-    update: "Met à jour un élément"
     usage: "Utilisation"
+    user: "Spécifie l'identifiant de connection"
     wallet: "Spécifie le portefeuille à utiliser"
+    wallet_dir: "Spécifie le répertoire des portefeuilles"
 
   form:
     select: "Sélectionner l'élément: "
     add_key:
       valid: "La clé a bien été ajoutée!"
     add_item:
-      title: "Ajout d'un nouvel élément"
-      name: "Entrez le nom: "
-      group: "Entrez le groupe (optionnel): "
-      server: "Entrez le nom de domaine ou l'ip: "
-      protocol: "Entrez le protocole de connexion (ssh, http, other): "
-      login: "Entrez l'identifiant de connexion: "
-      password: "Entrez le mot de passe: "
-      port: "Entrez le port de connexion (optionnel): "
-      comment: "Entrez un commentaire (optionnel): "
-      otp_key: "Entrez le secret OTP: "
+      name: "Le nom de l'élément (obligatoire)"
+      group: "Le nom du groupe"
+      host: "Le nom de domaine ou l'ip"
+      protocol: "Le protocole de connexion (ssh, http, ...)"
+      login: "L'identifiant de connexion"
+      password: "Le mot de passe"
+      port: "Le port de connexion"
+      comment: "Un commentaire"
+      otp_key: "Le secret OTP"
       valid: "L'élément a bien été ajouté!"
     clipboard:
       choice: "Que voulez-vous copier ? : "
@@ -88,12 +96,12 @@ fr:
          login: "Pressez <l> pour copier l'identifiant"
          password: "Pressez <p> pour copier le mot de passe"
          otp_code: "Pressez <o> pour copier le code OTP"
+         quit: "Pressez <q> pour quitter"
     delete_key:
       valid: "La clé a bien été supprimée!"
     delete_item:
-      ask: "Êtes vous sûre de vouloir supprimer l'élément %{id} ?"
-      valid: "L'élément %{id} a bien été supprimé!"
-      not_valid: "L'élément %{id} n'a pu être supprimé, car il n'existe pas!"
+      ask: "Êtes vous sûre de vouloir supprimer l'élément ?"
+      valid: "L'élément a bien été supprimé!"
     import:
       ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?"
       valid: "L'import est un succès!"
@@ -127,16 +135,15 @@ fr:
       wait: "Veuillez patienter durant la génération de votre clé GPG, ce processus peut prendre quelques minutes."
       valid: "Votre clé GPG a bien été créée ;-)"
     update_item:
-      title: "Mis à jour d'un élément"
-      name: "Entrez le nom [%{name}]: "
-      group: "Entrez le groupe [%{group}]: "
-      server: "Entrez le nom de domaine ou l'ip du serveur [%{server}]: "
-      protocol: "Entrez le protocole de connexion [%{protocol}]: "
-      login: "Entrez votre identifiant de connexion [%{login}]: "
-      password: "Entrez le mot de passe: "
-      port: "Entrez un port de connexion [%{port}]: "
-      comment: "Entrez un commentaire [%{comment}]: "
-      otp_key: "Entrez le secret OTP: "
+      name: "Le nom de l'élément (obligatoire)"
+      group: "Le nom du groupe"
+      host: "Le nom de domaine ou l'ip"
+      protocol: "Le protocole de connexion (ssh, http, ...)"
+      login: "L'identifiant de connexion"
+      password: "Le mot de passe (laissez vide si vous ne voulez pas le changer)"
+      port: "Le port de connexion"
+      comment: "Un commentaire"
+      otp_key: "Le secret OTP (laissez vide si vous ne voulez pas le changer)"
       valid: "L'élément a bien été mis à jour!" 
     export:
       valid: "L'export dans %{file} est un succès!"
diff --git a/lib/mpw/cli.rb b/lib/mpw/cli.rb
index 392e7bd..722b16d 100644
--- a/lib/mpw/cli.rb
+++ b/lib/mpw/cli.rb
@@ -17,10 +17,12 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 require 'readline'
+require 'locale'
 require 'i18n'
 require 'colorize'
 require 'highline/import'
 require 'clipboard'
+require 'tmpdir'
 require 'mpw/item'
 require 'mpw/mpw'
 
@@ -30,33 +32,35 @@ class Cli
 	# Constructor
 	# @args: config -> the config
 	#        sync -> boolean for sync or not
-	#        clipboard -> enable clopboard
-	#        otp -> enable otp
-	def initialize(config, clipboard=true, sync=true, otp=false)
+	def initialize(config, sync=true)
 		@config    = config
-		@clipboard = clipboard
 		@sync      = sync
-		@otp       = otp
+	end
+
+	# Change a parameter int the config after init
+	# @args: options -> param to change
+	def set_config(options)
+		gpg_key    = options[:gpg_key]    || @config.key
+		lang       = options[:lang]       || @config.lang
+		wallet_dir = options[:wallet_dir] || @config.wallet_dir
+		gpg_exe    = options[:gpg_exe]    || @config.gpg_exe
+
+		@config.setup(gpg_key, lang, wallet_dir, gpg_exe)
+	rescue Exception => e
+		puts "#{I18n.t('display.error')} #15: #{e}".red
+		exit 2
 	end
 
 	# Create a new config file
-	# @args: lang -> the software language
-	def setup(lang)
-		puts I18n.t('form.setup_config.title')
-		puts '--------------------'
-		language   = ask(I18n.t('form.setup_config.lang', lang: lang)).to_s
-		key        = ask(I18n.t('form.setup_config.gpg_key')).to_s
-		wallet_dir = ask(I18n.t('form.setup_config.wallet_dir', home: "#{@config.config_dir}")).to_s
-		gpg_exe    = ask(I18n.t('form.setup_config.gpg_exe')).to_s
+	# @args: options -> set param
+	def setup(options)
+		lang = options[:lang] || Locale::Tag.parse(ENV['LANG']).to_simple.to_s[0..1]
 
-		if language.nil? or language.empty?
-			language = lang
-		end
-		I18n.locale = language.to_sym
+		I18n.locale = lang.to_sym
 
-		@config.setup(key, lang, wallet_dir, gpg_exe)
+		@config.setup(options[:gpg_key], lang, options[:wallet_dir], options[:gpg_exe])
 
-		raise I18n.t('error.config.check') if not @config.is_valid?
+		load_config
 
 		puts "#{I18n.t('form.setup_config.valid')}".green
 	rescue Exception => e
@@ -65,16 +69,10 @@ class Cli
 	end
 	
 	# Setup a new GPG key
-	def setup_gpg_key
-		puts I18n.t('form.setup_gpg_key.title')
-		puts '--------------------'
-		ask      = ask(I18n.t('form.setup_gpg_key.ask')).to_s
-		
-		if not ['Y', 'y', 'O', 'o'].include?(ask)
-			raise I18n.t('form.setup_gpg_key.no_create')
-		end
+	# @args: gpg_key -> the key name
+	def setup_gpg_key(gpg_key)
+		return if @config.check_gpg_key?
 
-		name     = ask(I18n.t('form.setup_gpg_key.name')).to_s
 		password = ask(I18n.t('form.setup_gpg_key.password')) {|q| q.echo = false}
 		confirm  = ask(I18n.t('form.setup_gpg_key.confirm_password')) {|q| q.echo = false}
 
@@ -82,16 +80,11 @@ class Cli
 			raise I18n.t('form.setup_gpg_key.error_password')
 		end
 
-		length   = ask(I18n.t('form.setup_gpg_key.length')).to_s
-		expire   = ask(I18n.t('form.setup_gpg_key.expire')).to_s
-		password = password.to_s
-
-		length = length.nil? or length.empty? ? 2048 : length.to_i
-		expire = expire.nil? or expire.empty? ? 0    : expire.to_i
+		@password = password.to_s 
 
 		puts I18n.t('form.setup_gpg_key.wait')
 		
-		@config.setup_gpg_key(password, name, length, expire)
+		@config.setup_gpg_key(@password, gpg_key)
 
 		puts "#{I18n.t('form.setup_gpg_key.valid')}".green
 	rescue Exception => e
@@ -100,23 +93,17 @@ class Cli
 	end
 
 	# Setup wallet config for sync
-	def setup_wallet_config
-		config         = {}
-		config['sync'] = {}
-
-		puts I18n.t('form.setup_wallet.title')
-		puts '--------------------'
-		config['sync']['type']     = ask(I18n.t('form.setup_wallet.sync_type')).to_s
-
-		if ['ftp', 'ssh'].include?(config['sync']['type'].downcase)
-			config['sync']['host']     = ask(I18n.t('form.setup_wallet.sync_host')).to_s
-			config['sync']['port']     = ask(I18n.t('form.setup_wallet.sync_port')).to_s
-			config['sync']['user']     = ask(I18n.t('form.setup_wallet.sync_user')).to_s
-			config['sync']['password'] = ask(I18n.t('form.setup_wallet.sync_pwd')).to_s
-			config['sync']['path']     = ask(I18n.t('form.setup_wallet.sync_path')).to_s
+	# @args: options -> value to change
+	def setup_wallet_config(options={})
+		if not options[:password].nil?
+			options[:password] = ask(I18n.t('form.setup_wallet.password')) {|q| q.echo = false}
 		end
 
-		@mpw.set_config(config)
+		#wallet_file = wallet.nil? ? "#{@config.wallet_dir}/default.mpw" : "#{@config.wallet_dir}/#{wallet}.mpw"
+
+		@mpw = MPW.new(@config.key, @wallet_file, @password, @config.gpg_exe)
+		@mpw.read_data
+		@mpw.set_config(options)
 		@mpw.write_data
 
 		puts "#{I18n.t('form.setup_wallet.valid')}".green
@@ -125,6 +112,15 @@ class Cli
 		exit 2
 	end
 	
+	# Load config
+	def load_config
+		@config.load_config
+
+	rescue Exception => e
+		puts "#{I18n.t('display.error')} #10: #{e}".red
+		exit 2
+	end
+
 	# Request the GPG password and decrypt the file
 	def decrypt
 		if not defined?(@mpw)
@@ -139,97 +135,119 @@ class Cli
 		exit 2
 	end
 
-	# Display the query's result
-	# @args: search -> the string to search
-	#        protocol -> search from a particular protocol
-	def display(options={})
-		result = @mpw.list(options)
+	# Format items on a table
+	def table(items=[])
+		group        = '.'
+		i            = 1
+		length_total = 10
+		data         = { id:       { length: 3,  color: 'cyan' },
+		                 host:     { length: 9,  color: 'yellow' },
+		                 user:     { length: 7,  color: 'green' },
+		                 protocol: { length: 9,  color: 'white' },
+		                 port:     { length: 5,  color: 'white' },
+		                 otp:      { length: 4,  color: 'white' },
+		                 comment:  { length: 14, color: 'magenta' },
+		               }
 
-		case result.length
-		when 0
-			puts I18n.t('display.nothing')
+		items.each do |item|
+			data.each do |k, v|
+				next if k == :id or k == :otp
 
-		when 1
-			display_item(result.first)
+				v[:length] = item.send(k.to_s).length + 3 if item.send(k.to_s).to_s.length >= v[:length]
+			end
+		end
+		data[:id][:length]  = items.length.to_s.length + 2 if items.length.to_s.length > data[:id][:length]
+		
+		data.each_value { |v| length_total += v[:length] }
+		items.sort!     { |a, b| a.group.to_s.downcase <=> b.group.to_s.downcase }
 
-		else
-			group = nil
-			i     = 1
+		items.each do |item|
+			if group != item.group
+				group = item.group
 
-			result.sort! { |a,b| a.group.downcase <=> b.group.downcase }
-
-			result.each do |item|
-				if group != item.group
-					group = item.group
-
-					if group.empty?
-						puts I18n.t('display.no_group').yellow
-					else
-						puts "\n#{group}".yellow
-					end
+				if group.to_s.empty?
+					puts "\n#{I18n.t('display.no_group')}".red
+				else
+					puts "\n#{group}".red
 				end
 
-				print " |_ ".yellow
-				print "#{i}: ".cyan
-				print item.name
-				print " -> #{item.comment}".magenta if not item.comment.to_s.empty?
+				print ' '
+				length_total.times { print '=' }
+				print "\n "
+				data.each do |k, v|
+					case k
+					when :id
+						print ' ID'
+					when :otp
+						print '| OTP'
+					else
+						print "| #{k.to_s.capitalize}"
+					end
+
+					(v[:length] - k.to_s.length).times { print ' ' }
+				end
+				print "\n "
+				length_total.times { print '=' }
 				print "\n"
-
-				i += 1
 			end
 
+			print "  #{i}".send(data[:id][:color])
+			(data[:id][:length] - i.to_s.length).times { print ' ' }
+			data.each do |k, v|
+				next if k == :id
+
+				if k == :otp
+					print '| '
+					if item.otp;  print ' X  ' else 4.times { print ' ' } end
+
+					next
+				end
+
+				print '| '
+				print "#{item.send(k.to_s)}".send(v[:color])
+				(v[:length] - item.send(k.to_s).to_s.length).times { print ' ' }
+			end
 			print "\n"
-			choice = ask(I18n.t('form.select')).to_i
 
-			if choice >= 1 and choice < i 
-				display_item(result[choice-1])
-			else
-				puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
-			end
+			i += 1
+		end
+
+		print "\n"
+	end
+
+	# Display the query's result
+	# @args: options -> the option to search
+	def list(options={})
+		result = @mpw.list(options)
+
+		if result.length == 0
+			puts I18n.t('display.nothing')
+
+		else
+			table(result)
 		end
 	end
 
-	# Display an item in the default format
-	# @args: item -> an array with the item information
-	def display_item(item)
-		puts '--------------------'.cyan
-		print 'Id: '.cyan
-		puts  item.id
-		print "#{I18n.t('display.name')}: ".cyan
-		puts  item.name
-		print "#{I18n.t('display.group')}: ".cyan
-		puts  item.group
-		print "#{I18n.t('display.server')}: ".cyan
-		puts  item.host
-		print "#{I18n.t('display.protocol')}: ".cyan
-		puts  item.protocol
-		print "#{I18n.t('display.login')}: ".cyan
-		puts  item.user
+	# Get an item when multiple choice
+	# @args: items -> array of items
+	# @rtrn: item
+	def get_item(items)
+		return items[0] if items.length == 1
 
-		if @clipboard
-			print "#{I18n.t('display.password')}: ".cyan
-			puts '***********'
+		items.sort! { |a,b| a.group.to_s.downcase <=> b.group.to_s.downcase }
+		choice = ask(I18n.t('form.select')).to_i
+
+		if choice >= 1 and choice <= items.length
+			return items[choice-1]
 		else
-			print "#{I18n.t('display.password')}: ".cyan
-			puts  @mpw.get_password(item.id)
-
-			if @mpw.get_otp_code(item.id) > 0
-				print "#{I18n.t('display.otp_code')}: ".cyan
-				puts "#{@mpw.get_otp_code(item.id)} (#{@mpw.get_otp_remaining_time}s)"
-			end
+			return nil
 		end
-
-		print "#{I18n.t('display.port')}: ".cyan
-		puts  item.port
-		print "#{I18n.t('display.comment')}: ".cyan
-		puts  item.comment
-
-		clipboard(item) if @clipboard
 	end
 
 	# Copy in clipboard the login and password
 	# @args: item -> the item
-	def clipboard(item)
+	#        clipboard -> enable clipboard
+	def clipboard(item, clipboard=true)
 		pid = nil
 
 		# Security: force quit after 90s
@@ -246,21 +264,33 @@ class Cli
 				break
 
 			when 'l', 'login'
-				Clipboard.copy(item.user)
-				puts I18n.t('form.clipboard.login').green
+				if clipboard
+					Clipboard.copy(item.user)
+					puts I18n.t('form.clipboard.login').green
+				else
+					puts item.user
+				end
 
 			when 'p', 'password'
-				Clipboard.copy(@mpw.get_password(item.id))
-				puts I18n.t('form.clipboard.password').yellow
+				if clipboard
+					Clipboard.copy(@mpw.get_password(item.id))
+					puts I18n.t('form.clipboard.password').yellow
 
-				Thread.new do
-					sleep 30
+					Thread.new do
+						sleep 30
 
-					Clipboard.clear
+						Clipboard.clear
+					end
+				else
+					puts @mpw.get_password(item.id)
 				end
 
 			when 'o', 'otp'
-				Clipboard.copy(@mpw.get_otp_code(item.id))
+				if clipboard
+					Clipboard.copy(@mpw.get_otp_code(item.id))
+				else
+					puts @mpw.get_otp_code(item.id)
+				end
 				puts I18n.t('form.clipboard.otp', time: @mpw.get_otp_remaining_time).yellow
 
 			else
@@ -268,6 +298,7 @@ class Cli
 				puts I18n.t('form.clipboard.help.login')
 				puts I18n.t('form.clipboard.help.password')
 				puts I18n.t('form.clipboard.help.otp_code')
+				puts I18n.t('form.clipboard.help.quit')
 				next
 			end
 		end
@@ -277,34 +308,25 @@ class Cli
 		Clipboard.clear
 	end
 
+	# List all wallets
+	def list_wallet
+		wallets = Dir.glob("#{@config.wallet_dir}/*.mpw")
+
+		wallets.each do |wallet|
+			puts File.basename(wallet, '.mpw')
+		end
+	end
+
 	# Display the wallet
 	# @args: wallet -> the wallet name
 	def get_wallet(wallet=nil)
 		if wallet.to_s.empty?
 			wallets = Dir.glob("#{@config.wallet_dir}/*.mpw")
 
-			case wallets.length
-			when 0
-				puts I18n.t('display.nothing')
-			when 1
+			if wallets.length == 1
 				@wallet_file = wallets[0]
 			else
-				i = 1
-				wallets.each do |wallet|
-						print "#{i}: ".cyan
-						puts File.basename(wallet, '.mpw')
-
-						i += 1
-				end
-
-				choice = ask(I18n.t('form.select')).to_i
-
-				if choice >= 1 and choice < i
-					@wallet_file = wallets[choice-1]
-				else
-					puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
-					exit 2
-				end
+				@wallet_file = "#{@config.wallet_dir}/default.mpw"
 			end
 		else
 			@wallet_file = "#{@config.wallet_dir}/#{wallet}.mpw"
@@ -336,111 +358,158 @@ class Cli
 		puts "#{I18n.t('display.error')} #15: #{e}".red
 	end
 
-	# Form to add a new item
-	def add
-		options = {}
+	# Text editor interface
+	# @args: template -> template name
+	#        item -> the item to edit
+	#        password -> disable field password
+	def text_editor(template_name, item=nil, password=false)
+		editor        = ENV['EDITOR'] || 'nano'
+		options       = {}
+		opts          = {}
+		template_file = "#{File.expand_path('../../../templates', __FILE__)}/#{template_name}.erb"
+		template      = ERB.new(IO.read(template_file))
 
-		puts I18n.t('form.add_item.title')
-		puts '--------------------'
-		options[:name]     = ask(I18n.t('form.add_item.name')).to_s
-		options[:group]    = ask(I18n.t('form.add_item.group')).to_s
-		options[:host]     = ask(I18n.t('form.add_item.server')).to_s
-		options[:protocol] = ask(I18n.t('form.add_item.protocol')).to_s
-		options[:user]     = ask(I18n.t('form.add_item.login')).to_s
-		password           = ask(I18n.t('form.add_item.password')).to_s
-		options[:port]     = ask(I18n.t('form.add_item.port')).to_s
-		options[:comment]  = ask(I18n.t('form.add_item.comment')).to_s
+		Dir.mktmpdir do |dir|
+			tmp_file = "#{dir}/#{template_name}.yml"
 
-		if @otp
-			otp_key = ask(I18n.t('form.add_item.otp_key')).to_s
+			File.open(tmp_file, 'w') do |f|
+				f << template.result(binding)
+			end
+
+			system("#{editor} #{tmp_file}")
+
+			opts = YAML::load_file(tmp_file)
 		end
 
-		item = Item.new(options)
+		opts.delete_if { |k,v| v.to_s.empty? }
 
+		opts.each do |k,v|
+			options[k.to_sym] = v
+		end
+
+		return options
+	end
+
+	# Form to add a new item
+	# @args: password -> generate a random password
+	def add(password=false)
+		options = text_editor('add_form', nil, password)	
+		item    = Item.new(options)
+
+		if password
+			options[:password] = MPW::password(length: 24)
+		end
+		
 		@mpw.add(item)
-		@mpw.set_password(item.id, password)
-		@mpw.set_otp_key(item.id, otp_key)
+		@mpw.set_password(item.id, options[:password]) if options.has_key?(:password)
+		@mpw.set_otp_key(item.id, options[:otp_key])   if options.has_key?(:otp_key)
 		@mpw.write_data
 		@mpw.sync(true) if @sync
 
 		puts "#{I18n.t('form.add_item.valid')}".green
+	rescue Exception => e
+		puts "#{I18n.t('display.error')} #13: #{e}".red
 	end
 
 	# Update an item
-	# @args: id -> the item's id
-	def update(id)
-		item = @mpw.search_by_id(id)
+	# @args: options -> the option to search
+	def update(options={})
+		items = @mpw.list(options)
+		
+		if items.length == 0
+			puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
+		else
+			table(items) if items.length > 1
 
-		if not item.nil?
-			options = {}
-
-			puts I18n.t('form.update_item.title')
-			puts '--------------------'
-			options[:name]     = ask(I18n.t('form.update_item.name'    , name:     item.name)).to_s
-			options[:group]    = ask(I18n.t('form.update_item.group'   , group:    item.group)).to_s
-			options[:host]     = ask(I18n.t('form.update_item.server'  , server:   item.host)).to_s
-			options[:protocol] = ask(I18n.t('form.update_item.protocol', protocol: item.protocol)).to_s
-			options[:user]     = ask(I18n.t('form.update_item.login'   , login:    item.user)).to_s
-			password           = ask(I18n.t('form.update_item.password')).to_s
-			options[:port]     = ask(I18n.t('form.update_item.port'    , port:     item.port)).to_s
-			options[:comment]  = ask(I18n.t('form.update_item.comment' , comment:  item.comment)).to_s
-
-			if @otp
-				otp_key = ask(I18n.t('form.update_item.otp_key')).to_s
-			end
-
-			options.delete_if { |k,v| v.empty? }
+			item    = get_item(items)
+			options = text_editor('update_form', item)
 
 			item.update(options)
-			@mpw.set_password(item.id, password) if not password.empty?
-			@mpw.set_otp_key(item.id, otp_key)   if not otp_key.to_s.empty?
+			@mpw.set_password(item.id, options[:password]) if options.has_key?(:password)
+			@mpw.set_otp_key(item.id, options[:otp_key])   if options.has_key?(:otp_key)
 			@mpw.write_data
 			@mpw.sync(true) if @sync
 
 			puts "#{I18n.t('form.update_item.valid')}".green
-		else
-			puts I18n.t('display.nothing')
 		end
 	rescue Exception => e
 		puts "#{I18n.t('display.error')} #14: #{e}".red
 	end
 
 	# Remove an item
-	# @args: id -> the item's id
-	#        force -> no resquest a validation
-	def delete(id, force=false)
-		@clipboard = false
-		item       = @mpw.search_by_id(id)
+	# @args: options -> the option to search
+	def delete(options={})
+		items = @mpw.list(options)
+		
+		if items.length == 0
+			puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
+		else
+			table(items)
 
-		if item.nil?
-			puts I18n.t('form.delete_item.not_valid', id: id)
-			return
-		end
-
-		if not force
-			display_item(item)
-
-			confirm = ask("#{I18n.t('form.delete_item.ask', id: id)} (y/N) ").to_s
+			item    = get_item(items)
+			confirm = ask("#{I18n.t('form.delete_item.ask')} (y/N) ").to_s
+	
 			if not confirm =~ /^(y|yes|YES|Yes|Y)$/
-				return
+				return false
 			end
+	
+			item.delete
+			@mpw.write_data
+			@mpw.sync(true) if @sync
+	
+			puts "#{I18n.t('form.delete_item.valid')}".green
 		end
-
-		item.delete
-		@mpw.write_data
-		@mpw.sync(true) if @sync
-
-		puts "#{I18n.t('form.delete_item.valid', id: id)}".green
 	rescue Exception => e
 		puts "#{I18n.t('display.error')} #16: #{e}".red
 	end
 
+	# Copy a password, otp, login
+	# @args: clipboard -> enable clipboard
+	#        options -> the option to search
+	def copy(clipboard=true, options={})
+		items = @mpw.list(options)
+		
+		if items.length == 0
+			puts "#{I18n.t('display.warning')}: #{I18n.t('warning.select')}".yellow
+		else
+			table(items)
+
+			item = get_item(items)
+			clipboard(item, clipboard)
+		end
+	rescue Exception => e
+		puts "#{I18n.t('display.error')} #14: #{e}".red
+	end
+
 	# Export the items in a CSV file
 	# @args: file -> the destination file
-	def export(file)
-		@mpw.export(file)
+	#        options -> option to search
+	def export(file, options)
+		file  = 'export-mpw.yml' if file.to_s.empty?
+		items = @mpw.list(options)
+		data  = {}
+		i     = 1
 
-		puts "#{I18n.t('export.export.valid', file)}".green
+		items.each do |item|
+			data.merge!(i => { 'host'      => item.host,
+			                   'user'      => item.user,
+			                   'group'     => item.group,
+			                   'password'  => @mpw.get_password(item.id),
+			                   'protocol'  => item.protocol,
+			                   'port'      => item.port,
+			                   'otp_key'   => @mpw.get_otp_key(item.id),
+			                   'comment'   => item.comment,
+			                   'last_edit' => item.last_edit,
+			                   'created'   => item.created,
+			                 }
+			            )
+
+			i += 1
+		end
+
+		File.open(file, 'w') {|f| f << data.to_yaml}
+
+		puts "#{I18n.t('export.valid', file)}".green
 	rescue Exception => e
 		puts "#{I18n.t('display.error')} #17: #{e}".red
 	end
@@ -448,7 +517,26 @@ class Cli
 	# Import items from a YAML file
 	# @args: file -> the import file
 	def import(file)
-		@mpw.import(file)
+		raise I18n.t('import.file_empty')     if file.to_s.empty?
+		raise I18n.t('import.file_not_exist') if not File.exist?(file)
+
+		YAML::load_file(file).each_value do |row|
+
+			item = Item.new(group:    row['group'],
+			                host:     row['host'],
+			                protocol: row['protocol'],
+			                user:     row['user'],
+			                port:     row['port'],
+			                comment:  row['comment'],
+			               )
+
+			next if item.empty?
+
+			@mpw.add(item)
+			@mpw.set_password(item.id, row['password']) if not row['password'].to_s.empty?
+			@mpw.set_otp_key(item.id, row['otp_key'])   if not row['otp_key'].to_s.empty?
+		end
+
 		@mpw.write_data
 
 		puts "#{I18n.t('form.import.valid')}".green
diff --git a/lib/mpw/config.rb b/lib/mpw/config.rb
index 90df409..2c1c496 100644
--- a/lib/mpw/config.rb
+++ b/lib/mpw/config.rb
@@ -57,20 +57,18 @@ class Config
 	#        gpg_exe -> the  path of gpg executable
 	# @rtrn: true if le config file is create
 	def setup(key, lang, wallet_dir, gpg_exe)
-
 		if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
 			raise I18n.t('error.config.key_bad_format')
 		end
 
-		if wallet_dir.empty?
+		if wallet_dir.to_s.empty?
 			wallet_dir = "#{@config_dir}/wallets"
 		end
 
-		config = {'config' => {'key'        => key,
-		                       'lang'       => lang,
-		                       'wallet_dir' => wallet_dir,
-		                       'gpg_exe'    => gpg_exe,
-		                      }
+		config = { 'key'        => key,
+		           'lang'       => lang,
+		           'wallet_dir' => wallet_dir,
+		           'gpg_exe'    => gpg_exe,
 		         }
 
 		FileUtils.mkdir_p(wallet_dir, mode: 0700)
@@ -89,9 +87,9 @@ class Config
 	#        expire -> the time of expire to GPG key
 	# @rtrn: true if the GPG key is create, else false
 	def setup_gpg_key(password, name, length = 4096, expire = 0)
-		if name.nil? or name.empty?
+		if name.to_s.empty?
 			raise "#{I18n.t('error.config.genkey_gpg.name')}"
-		elsif password.nil? or password.empty?
+		elsif password.to_s.empty?
 			raise "#{I18n.t('error.config.genkey_gpg.password')}"
 		end
 
@@ -114,22 +112,20 @@ class Config
 		raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}"
 	end
 
-	# Check the config file
-	# @rtrn: true if the config file is correct
-	def is_valid?
+	# Load the config file
+	def load_config
 		config      = YAML::load_file(@config_file)
-		@key        = config['config']['key']
-		@lang       = config['config']['lang']
-		@wallet_dir = config['config']['wallet_dir']
-		@gpg_exe    = config['config']['gpg_exe']
+		@key        = config['key']
+		@lang       = config['lang']
+		@wallet_dir = config['wallet_dir']
+		@gpg_exe    = config['gpg_exe']
 
 		raise if @key.empty? or @wallet_dir.empty?
 			
 		I18n.locale = @lang.to_sym
 
-		return true
-	rescue
-		return false
+	rescue Exception => e
+		raise "#{I18n.t('error.config.load')}\n#{e}"
 	end
 
 	# Check if private key exist
diff --git a/lib/mpw/item.rb b/lib/mpw/item.rb
index ef1309e..4beb49f 100644
--- a/lib/mpw/item.rb
+++ b/lib/mpw/item.rb
@@ -22,12 +22,12 @@ module MPW
 class Item
 
 	attr_accessor :id
-	attr_accessor :name
 	attr_accessor :group
 	attr_accessor :host
 	attr_accessor :protocol
 	attr_accessor :user
 	attr_accessor :port
+	attr_accessor :otp
 	attr_accessor :comment
 	attr_accessor :last_edit
 	attr_accessor :last_sync
@@ -38,15 +38,15 @@ class Item
 	# @args: options -> a hash of parameter
 	# raise an error if the hash hasn't the key name 
 	def initialize(options={})
-		if not options.has_key?(:name) or options[:name].to_s.empty?
+		if not options.has_key?(:host) or options[:host].to_s.empty?
 			raise I18n.t('error.update.name_empty')
 		end
 
-		if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty?  
-			@id      = generate_id
+		if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty?
+			@id = generate_id
 			@created = Time.now.to_i
 		else
-			@id        = options[:id]
+			@id = options[:id]
 			@created   = options[:created]
 			@last_edit = options[:last_edit]
 			options[:no_update_last_edit] = true
@@ -58,16 +58,16 @@ class Item
 	# Update the item
 	# @args: options -> a hash of parameter
 	def update(options={})
-		if options.has_key?(:name) and options[:name].to_s.empty?
+		if options.has_key?(:host) and options[:host].to_s.empty?
 			raise I18n.t('error.update.name_empty')
 		end
 
-		@name      = options[:name]       if options.has_key?(:name)
 		@group     = options[:group]      if options.has_key?(:group)
 		@host      = options[:host]       if options.has_key?(:host)
 		@protocol  = options[:protocol]   if options.has_key?(:protocol)
 		@user      = options[:user]       if options.has_key?(:user)
 		@port      = options[:port].to_i  if options.has_key?(:port) and not options[:port].to_s.empty?
+		@otp       = options[:otp]        if options.has_key?(:otp)
 		@comment   = options[:comment]    if options.has_key?(:comment)
 		@last_edit = Time.now.to_i        if not options.has_key?(:no_update_last_edit)
 	end
@@ -80,12 +80,12 @@ class Item
 	# Delete all data
 	def delete
 		@id        = nil
-		@name      = nil
 		@group     = nil
 		@host      = nil
 		@protocol  = nil
 		@user      = nil
 		@port      = nil
+		@otp       = nil
 		@comment   = nil
 		@created   = nil
 		@last_edit = nil
@@ -93,7 +93,7 @@ class Item
 	end
 
 	def empty?
-		return @name.to_s.empty?
+		return @id.to_s.empty?
 	end
 
 	def nil?
@@ -104,6 +104,6 @@ class Item
 	private
 	def generate_id
 		return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join
-	end
+	end 
+end
 end
-end	
diff --git a/lib/mpw/mpw.rb b/lib/mpw/mpw.rb
index baa83f5..533077e 100644
--- a/lib/mpw/mpw.rb
+++ b/lib/mpw/mpw.rb
@@ -33,7 +33,7 @@ class MPW
 		@gpg_exe     = gpg_exe
 		@wallet_file = wallet_file
 
-		if @gpg_exe
+		if not @gpg_exe.to_s.empty?
 			GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, @gpg_exe, "#{Dir.home}/.gnupg")
 		end
 	end
@@ -83,12 +83,12 @@ class MPW
 		if not data.nil? and not data.empty?
 			YAML.load(data).each_value do |d|
 				@data.push(Item.new(id:        d['id'],
-				                    name:      d['name'],
 				                    group:     d['group'],
 				                    host:      d['host'],
 				                    protocol:  d['protocol'],
 				                    user:      d['user'],
 				                    port:      d['port'],
+				                    otp:       @otp_keys.has_key?(d['id']),
 				                    comment:   d['comment'],
 				                    last_edit: d['last_edit'],
 				                    created:   d['created'],
@@ -110,16 +110,15 @@ class MPW
 		@data.each do |item|
 			next if item.empty?
 
-			data.merge!(item.id => {'id'        => item.id,
-			                        'name'      => item.name,
-		                            'group'     => item.group,
-			                        'host'      => item.host,
-			                        'protocol'  => item.protocol,
-			                        'user'      => item.user,
-			                        'port'      => item.port,
-			                        'comment'   => item.comment,
-			                        'last_edit' => item.last_edit,
-			                        'created'   => item.created,
+			data.merge!(item.id => { 'id'        => item.id,
+			                         'group'     => item.group,
+			                         'host'      => item.host,
+			                         'protocol'  => item.protocol,
+			                         'user'      => item.user,
+			                         'port'      => item.port,
+			                         'comment'   => item.comment,
+			                         'last_edit' => item.last_edit,
+			                         'created'   => item.created,
 			                       }
 			           )
 		end
@@ -158,7 +157,7 @@ class MPW
 
 		File.rename(tmp_file, @wallet_file)
 	rescue Exception => e
-		File.unlink(tmp_file)
+		File.unlink(tmp_file) if File.exist?(tmp_file)
 
 		raise "#{I18n.t('error.mpw_file.write_data')}\n#{e}"
 	end
@@ -211,16 +210,16 @@ class MPW
 
 	# Set config
 	# args: config -> a hash with config options
-	def set_config(config)
-		@config['sync'] = {} if @config['sync'].nil?
+	def set_config(options={})
+		@config              = {} if @config.nil?
 
-		@config['sync']['type']      = config['sync']['type']
-		@config['sync']['host']      = config['sync']['host']
-		@config['sync']['port']      = config['sync']['port']
-		@config['sync']['user']      = config['sync']['user']
-		@config['sync']['password']  = config['sync']['password']
-		@config['sync']['path']      = config['sync']['path']
-		@config['sync']['last_sync'] = @config['sync']['last_sync'].nil? ? 0 : @config['sync']['last_sync']
+		@config['protocol']  = options[:protocol] if options.has_key?(:protocol)
+		@config['host']      = options[:host]     if options.has_key?(:host)
+		@config['port']      = options[:port]     if options.has_key?(:port)
+		@config['user']      = options[:user]     if options.has_key?(:user)
+		@config['password']  = options[:password] if options.has_key?(:password)
+		@config['path']      = options[:path]     if options.has_key?(:path)
+		@config['last_sync'] = @config['last_sync'].nil? ? 0 : @config['last_sync']
 	end
 
 	# Add a new item
@@ -241,18 +240,17 @@ class MPW
 	def list(options={})
 		result = []
 
-		search   = options[:search].to_s.downcase
-		group    = options[:group].to_s.downcase
+		search = options[:pattern].to_s.downcase
+		group  = options[:group].to_s.downcase
 
 		@data.each do |item|
 			next if item.empty?
-			next if not group.empty?    and not group.eql?(item.group.downcase)
+			next if not group.empty? and not group.eql?(item.group.to_s.downcase)
 			
-			name    = item.name.to_s.downcase
 			host    = item.host.to_s.downcase
 			comment = item.comment.to_s.downcase
 
-			if not name =~ /^.*#{search}.*$/ and not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ 
+			if not host =~ /^.*#{search}.*$/ and not comment =~ /^.*#{search}.*$/ 
 				next
 			end
 
@@ -273,56 +271,9 @@ class MPW
 		return nil
 	end
 
-	# Export to yaml
-	# @args: file -> file where you export the data
-	def export(file)
-		data = {}
-		@data.each do |item|
-			data.merge!(item.id => {'id'        => item.id,
-			                        'name'      => item.name,
-			                        'group'     => item.group,
-			                        'host'      => item.host,
-			                        'protocol'  => item.protocol,
-			                        'user'      => item.user,
-			                        'password'  => get_password(item.id),
-			                        'port'      => item.port,
-			                        'comment'   => item.comment,
-			                        'last_edit' => item.last_edit,
-			                        'created'   => item.created,
-			                       }
-			            )
-		end
-
-		File.open(file, 'w') {|f| f << data.to_yaml}
-	rescue Exception => e 
-		raise "#{I18n.t('error.export', file: file)}\n#{e}"
-	end
-
-	# Import to yaml
-	# @args: file -> path to file import
-	def import(file)
-		YAML::load_file(file).each_value do |row| 
-			item = Item.new(name:     row['name'], 
-			                group:    row['group'],
-			                host:     row['host'],
-			                protocol: row['protocol'],
-			                user:     row['user'],
-			                port:     row['port'],
-			                comment:  row['comment'],
-			               )
-
-			raise 'Item is empty' if item.empty?
-
-			@data.push(item)
-			set_password(item.id, row['password'])
-		end
-	rescue Exception => e 
-		raise "#{I18n.t('error.import', file: file)}\n#{e}"
-	end
-
 	# Get last sync
 	def get_last_sync
-		return @config['sync']['last_sync'].to_i
+		return @config['last_sync'].to_i
 	rescue
 		return 0
 	end
@@ -330,18 +281,18 @@ class MPW
 	# Sync data with remote file
 	# @args: force -> force the sync
 	def sync(force=false)
-		return if @config.empty? or @config['sync']['type'].to_s.empty?
+		return if @config.empty? or @config['protocol'].to_s.empty?
 		return if get_last_sync + 300 > Time.now.to_i and not force
 
 		tmp_file  = "#{@wallet_file}.sync"
 		
-		case @config['sync']['type']
+		case @config['protocol']
 		when 'sftp', 'scp', 'ssh'
 			require "mpw/sync/ssh"
-			sync = SyncSSH.new(@config['sync'])
+			sync = SyncSSH.new(@config)
 		when 'ftp'
 			require 'mpw/sync/ftp'
-			sync = SyncFTP.new(@config['sync'])
+			sync = SyncFTP.new(@config)
 		else
 			raise I18n.t('error.sync.unknown_type')
 		end
@@ -365,8 +316,7 @@ class MPW
 
 					# Update item
 					if item.last_edit < r.last_edit
-						item.update(name:      r.name,
-						            group:     r.group,
+						item.update(group:     r.group,
 						            host:      r.host,
 						            protocol:  r.protocol,
 						            user:      r.user,
@@ -394,7 +344,6 @@ class MPW
 			next if r.last_edit <= get_last_sync
 
 			item = Item.new(id:        r.id,
-			                name:      r.name,
 			                group:     r.group,
 			                host:      r.host,
 			                protocol:  r.protocol,
@@ -415,7 +364,7 @@ class MPW
 			item.set_last_sync
 		end
 
-		@config['sync']['last_sync'] = Time.now.to_i
+		@config['last_sync'] = Time.now.to_i
 
 		write_data
 		sync.update(@wallet_file)
@@ -429,13 +378,27 @@ class MPW
 	# args: id -> the item id
 	#       key -> the new key
 	def set_otp_key(id, key)
-		@otp_keys[id] = encrypt(key)
+		if not key.to_s.empty?
+			@otp_keys[id] = encrypt(key.to_s)
+		end
 	end
 
+	# Get an opt key
+	# args: id -> the item id
+	#       key -> the new key
+	def get_otp_key(id)
+		if @otp_keys.has_key?(id)
+			return decrypt(@otp_keys[id])
+		else
+			return nil
+		end
+	end
+
+
 	# Get an otp code
 	# @args: id -> the item id
 	# @rtrn: an otp code
-	def	get_otp_code(id)
+	def get_otp_code(id)
 		if not @otp_keys.has_key?(id)
 			return 0
 		else
@@ -481,6 +444,8 @@ class MPW
 	# @args: data -> string to decrypt
 	private
 	def decrypt(data)
+		return nil if data.to_s.empty?
+
 		crypto = GPGME::Crypto.new(armor: true)
 		
 		return crypto.decrypt(data, password: @gpg_pass).read.force_encoding('utf-8')
@@ -495,12 +460,12 @@ class MPW
 		recipients = []
 		crypto     = GPGME::Crypto.new(armor: true, always_trust: true)
 
+		recipients.push(@key)
 		@keys.each_key do |key|
+			next if key == @key
 			recipients.push(key)
 		end
 
-		recipients.push(@key) if not recipients.index(@key).nil?
-
 		return crypto.encrypt(data, recipients: recipients).read
 	rescue Exception => e 
 		raise "#{I18n.t('error.gpg_file.encrypt')}\n#{e}"
diff --git a/mpw.gemspec b/mpw.gemspec
index fa4afc7..09fe6d9 100644
--- a/mpw.gemspec
+++ b/mpw.gemspec
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
   spec.add_dependency "locale"
   spec.add_dependency "colorize"
   spec.add_dependency "net-ssh"
-  spec.add_dependency "net-scp"
+  spec.add_dependency "net-sftp"
   spec.add_dependency "clipboard"
   spec.add_dependency "rotp"
 end
diff --git a/templates/add_form.erb b/templates/add_form.erb
new file mode 100644
index 0000000..c2d6d73
--- /dev/null
+++ b/templates/add_form.erb
@@ -0,0 +1,9 @@
+---
+host:           # <%= I18n.t('form.add_item.host') %>
+user:           # <%= I18n.t('form.add_item.login') %>
+group:          # <%= I18n.t('form.add_item.group') %> 
+protocol:       # <%= I18n.t('form.add_item.protocol') %><% if not password %>
+password:       # <%= I18n.t('form.add_item.password') %><% end %>
+port:           # <%= I18n.t('form.add_item.port') %>
+comment:        # <%= I18n.t('form.add_item.comment') %>
+otp_key:        # <%= I18n.t('form.add_item.otp_key') %>
diff --git a/templates/setup_form.erb b/templates/setup_form.erb
new file mode 100644
index 0000000..f7e6d7b
--- /dev/null
+++ b/templates/setup_form.erb
@@ -0,0 +1,9 @@
+---
+# <%= I18n.t('form.setup_config.lang') %>
+language: <%= @config.lang %>
+# <%= I18n.t('form.setup_config.gpg_key') %>
+gpg_key: <%= @config.key %>
+# <%= I18n.t('form.setup_config.wallet_dir') %>
+wallet_dir: <%= @config.config_dir %>
+# <%= I18n.t('form.setup_config.gpg_exe') %>
+gpg_exe: <%= @config.gpg_exe %>
diff --git a/templates/update_form.erb b/templates/update_form.erb
new file mode 100644
index 0000000..f4a380b
--- /dev/null
+++ b/templates/update_form.erb
@@ -0,0 +1,17 @@
+---
+# <%= I18n.t('form.update_item.host') %>
+host: <%= item.host %>
+# <%= I18n.t('form.update_item.login') %>
+user: <%= item.user %>
+# <%= I18n.t('form.update_item.password') %>
+password: 
+# <%= I18n.t('form.update_item.group') %>
+group: <%= item.group %>
+# <%= I18n.t('form.update_item.protocol') %>
+protocol: <%= item.protocol %>
+# <%= I18n.t('form.update_item.port') %>
+port: <%= item.port %>
+# <%= I18n.t('form.update_item.otp_key') %>
+opt_key: 
+# <%= I18n.t('form.update_item.comment') %>
+comment: <%= item.comment %>