diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb
index 0a19016..ef66d30 100755
--- a/lib/rubygems/command_manager.rb
+++ b/lib/rubygems/command_manager.rb
@@ -70,6 +70,7 @@ class Gem::CommandManager
     register_command :unpack
     register_command :update
     register_command :which
+    register_command :nix
   end
 
   ##

diff --git a/lib/rubygems/commands/nix_command.rb b/lib/rubygems/commands/nix_command.rb
new file mode 100644
index 0000000..24f3479
--- /dev/null
+++ b/lib/rubygems/commands/nix_command.rb
@@ -0,0 +1,229 @@
+require 'net/http'
+require 'rubygems/command'
+require 'rubygems/doc_manager'
+require 'rubygems/install_update_options'
+require 'rubygems/dependency_installer'
+require 'rubygems/local_remote_options'
+require 'rubygems/validator'
+require 'rubygems/exceptions'
+require 'rubygems/version_option'
+require 'rubygems/version'
+require 'open3'
+
+
+def nixname(gem)
+  s = "#{gem}" == gem ? gem : gem.full_name
+  s.gsub(/[.-]/,'_')
+end
+
+def nixdescription(spec)
+  desc_from_spec = spec.description
+  desc = desc_from_spec.sub(/[.].*/,'') # only keep first sentence
+  desc = desc.length > 120 \
+    ? "description = \"#{ desc[0..120] }\"; # cut to 120 chars" \
+    : "description = \"#{ desc }\";"
+  desc = desc.sub(/";$/,"[...]\";") if desc != desc_from_spec
+  desc.gsub("\n"," ") # no \ns in description
+end
+
+##
+# tool creating nix expression to install gems (from ruby forge etc)
+#
+# this is work in progress
+
+class Gem::Commands::NixCommand < Gem::Command
+
+  include Gem::VersionOption
+  include Gem::LocalRemoteOptions
+  include Gem::InstallUpdateOptions
+
+  def initialize
+    defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
+    })
+    super 'nix', 'create a nix file containing expressions of the gems', defaults
+  end
+
+  def description # :nodoc:
+    <<-EOF
+      create a nix file containing expressions of the gems
+      There are many gems. So it's best to only specify some target gems and
+      take them into acocunt with their deps
+      TODO more details
+    EOF
+  end
+
+  def usage # :nodoc:
+    "#{program_name} GEMNAME [GEMNAME ...] [options] -- --build-flags"
+  end
+
+  def arguments # :nodoc:
+    "GEMNAME       name of gem to be added to the expressions file"
+  end
+
+  def defaults_str # :nodoc:
+    # what to put in here ? TODO (probably nothing is ok)
+    ""
+  end
+
+  def execute
+
+    begin
+      @prerelease = false;
+
+      args = options[:args];
+
+      @gems_with_deps = {}
+      @seen = {}
+
+      # args to dep informations
+      args.map { |arg|
+        if arg =~ /(.+)-?(.*)?/ then
+          gem_name = $1
+          version =  $2.empty? ?  Gem::Requirement.default : Gem::Version.new($2)
+        else
+          raise Gem::CommandLineError, "could'nt parse arg. expected: name or name-version"
+        end
+
+        puts "adding #{gem_name}\n"
+
+        adddep(Gem::Dependency.new gem_name, version)
+      }
+
+      print " total: #{@gems_with_deps.length}\n"
+
+
+      out = "
+         # WARNING: automatically generated CODE
+         # This section has been generated by gem nix #{args.join(" ")}
+         # the gem nix command has been added by a nix patch to ruby gems
+      "
+      # define aliases
+      aliases = {}
+      @gems_with_deps.each{ |key, (spec, src, deps)|
+        aliases[spec.name] = spec \
+          if aliases[spec.name].nil? || aliases[spec.name].version < spec.version
+
+           src_url = "http://gems.rubyforge.org/gems/#{spec.full_name}.gem"
+
+         # [> get true mirror url reading redirect contents
+         #  h = Net::HTTP.new('gems.rubyforge.org', 80)
+         #  resp, data = h.get("/gems/#{spec.full_name}.gem", nil)
+         #  if resp.code == "200" then
+         #    src_url = "http://gems.rubyforge.org/gems/#{spec.full_name}.gem"
+         #  else if resp.code == "302" then
+         #      src_url = resp['location']
+         #      print "redirection: http://gems.rubyforge.org/gems/#{spec.full_name}.gem -> #{src_url}\n"
+         #    else
+         #      raise Gem::DependencyError.new("unkown http return code #{resp} #{data}")
+         #    end
+         #  end
+
+         #raise Gem::DependencyError("src_url is nil, 302 redirection failed?") if src_url.nil?
+
+         out = "
+         #{out}
+  #{nixname spec} = rubyDerivation {
+     name = \"ruby-#{spec.full_name}\"; # full_name
+     nameNoVersion = \"#{nixname spec.name}\";
+     propagatedBuildInputs = [ #{deps.map {|n| n.nil? ? "" : (nixname n) }.join(" ")} ];
+     src = fetchurl {
+       url = \"#{src_url}\";
+       sha256 = \"#{nixhashof src_url}\";
+     };
+     meta = {
+       homepage = \"#{spec.homepage}\";
+       license = [#{spec.licenses.map{|l| "\"#{l}\""}.join(" ") }]; # one of ?
+       #{nixdescription spec}
+       longDescription = \"#{ spec.description }\";
+     };
+  };\n"
+      }
+
+      out = "#{out}\n# aliases\n"
+      aliases.each { |key, spec |
+        out = "#{out}#{nixname key}=#{nixname spec};\n"
+      }
+
+      print out
+      exit_code = 0
+
+    rescue => e
+      puts e.inspect
+      puts e.backtrace
+    end
+
+
+  end
+
+  # helper funtions ================
+  
+  def adddep(dep)
+    gem = find_gem_with_source(dep)
+    raise Gem::CommandLineError, "couldn't find #{dep}" if gem.nil?
+    full_name = gem[0].full_name
+
+    return if @seen[full_name]
+    @seen[full_name] = true # there maybe circular dependencies. thus mark this gem seen as early as possible
+
+    # development deps can't be found. Some are old. Thus only add rutime dependencies
+    deps = gem[0].dependencies.find_all { |d| d.type == :runtime }
+
+    print " total deps of #{full_name}: #{deps.length}\n"
+
+    dep_specs = []
+    # recurse while collecting deps
+    deps.each {|dep_var| dep_specs.push(adddep(dep_var)) }
+    
+
+    @gems_with_deps[full_name] = [
+      gem[0], # spec
+      gem[1], # src
+      dep_specs # deps
+    ]
+    gem[0] # only return spec, no source for dep list
+  end
+
+
+  # copied from dependency_installer, stripped
+  def find_gem_with_source(dep)
+    gems_and_sources = []
+
+    # no local 
+
+      requirements = dep.version_requirements.requirements.map do |req, ver|
+        req
+      end
+
+      all = true
+      found = Gem::SpecFetcher.fetcher.fetch dep, all, true, @prerelease
+      found.reverse[0]
+  end
+
+
+  def nixhashof(src)
+    cashfile="#{ENV['HOME']}/.nix-ruby-gems-cache"
+    cash = {}
+    if FileTest.exists?(cashfile)
+      File.open(cashfile,'r') do |f| Marshal.load(f) end
+    end
+
+    if cash[src].nil? then
+      tmp="/tmp/ruby-gems-nix-tmp-file"
+      system("nix-prefetch-url #{src.gsub(/([:= `$;])/,'\\\\\1')} > #{tmp} 2>/dev/null")
+      if $? == 0
+        file = File.new(tmp)
+        hash = file.readlines().first().split("\n")[0] # remove trailing \n
+        file.close()
+        File.delete(tmp)
+        cash[src] = hash
+      else
+        cash[src] = "no hash"
+      end
+
+      File.open(cashfile, "w+") do |f| Marshal.dump(cash, f) end
+    end
+
+    return cash[src]
+  end
+
+end

diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index d1ef3cb..bf15652 100755
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -545,6 +545,13 @@ Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
 
       say path if Gem.configuration.really_verbose
     end
+
+    if !ENV['NIX_POST_EXTRACT_FILES_HOOK'].nil?
+      print "\nrunning NIX_POST_EXTRACT_FILES_HOOK #{ENV['NIX_POST_EXTRACT_FILES_HOOK']} #{@gem_dir}\n"
+      print `#{ENV['NIX_POST_EXTRACT_FILES_HOOK']} #{@gem_dir}`
+      print "\nrunning NIX_POST_EXTRACT_FILES_HOOK done\n"
+    end
+
   end
 
   ##
