diff --git a/core/ajax/appconfig.php b/core/ajax/appconfig.php
new file mode 100644
index 0000000000000000000000000000000000000000..50984ac32b92d4da6eaf6af711413a97a36200a7
--- /dev/null
+++ b/core/ajax/appconfig.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+require_once ("../../lib/base.php");
+OC_JSON::checkLoggedIn();
+$action=isset($_POST['action'])?$_POST['action']:$_GET['action'];
+$result=false;
+switch($action){
+	case 'getValue':
+		$result=OC_Appconfig::getValue($_GET['app'],$_GET['key'],$_GET['default']);
+		break;
+	case 'setValue':
+		$result=OC_Appconfig::setValue($_POST['app'],$_POST['key'],$_POST['value']);
+		break;
+	case 'getApps':
+		$result=OC_Appconfig::getApps();
+		break;
+	case 'getKeys':
+		$result=OC_Appconfig::getKeys($_GET['app']);
+		break;
+	case 'hasKey':
+		$result=OC_Appconfig::hasKey($_GET['app'],$_GET['key']);
+		break;
+	case 'deleteKey':
+		$result=OC_Appconfig::deleteKey($_POST['app'],$_POST['key']);
+		break;
+	case 'deleteApp':
+		$result=OC_Appconfig::deleteApp($_POST['app']);
+		break;
+}
+OC_JSON::success(array('data'=>$result));
diff --git a/core/js/config.js b/core/js/config.js
new file mode 100644
index 0000000000000000000000000000000000000000..500fe072a64976eebb02b66561027993163c613f
--- /dev/null
+++ b/core/js/config.js
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OC.AppConfig={
+	url:OC.filePath('core','ajax','appconfig.php'),
+	getCall:function(action,data,callback){
+		data.action=action;
+		$.getJSON(OC.AppConfig.url,data,function(result){
+			if(result.status='success'){
+				if(callback){
+					callback(result.data);
+				}
+			}
+		});
+	},
+	postCall:function(action,data,callback){
+		data.action=action;
+		$.post(OC.AppConfig.url,data,function(result){
+			if(result.status='success'){
+				if(callback){
+					callback(result.data);
+				}
+			}
+		},'json');
+	},
+	getValue:function(app,key,defaultValue,callback){
+		if(typeof defaultValue=='function'){
+			callback=defaultValue;
+			defaultValue=null;
+		}
+		OC.AppConfig.getCall('getValue',{app:app,key:key,default:defaultValue},callback);
+	},
+	setValue:function(app,key,value){
+		OC.AppConfig.postCall('setValue',{app:app,key:key,value:value});
+	},
+	getApps:function(callback){
+		OC.AppConfig.getCall('getApps',{},callback);
+	},
+	getKeys:function(app,callback){
+		OC.AppConfig.getCall('getKeys',{app:app},callback);
+	},
+	hasKey:function(app,key,callback){
+		OC.AppConfig.getCall('hasKey',{app:app,key:key},callback);
+	},
+	deleteKey:function(app,key){
+		OC.AppConfig.postCall('deleteKey',{app:app,key:key});
+	},
+	deleteApp:function(app){
+		OC.AppConfig.postCall('deleteApp',{app:app});
+	},
+}
+//TODO OC.Preferences
diff --git a/lib/base.php b/lib/base.php
index 94e4907fed29f3c830106229db58c4e57061f64f..652b1f11bad43909f6be8b6043985dc93d60e2f7 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -205,6 +205,7 @@ class OC{
 		OC_Util::addScript( "jquery-tipsy" );
 		OC_Util::addScript( "js" );
 		OC_Util::addScript( "eventsource" );
+		OC_Util::addScript( "config" );
 		//OC_Util::addScript( "multiselect" );
 		OC_Util::addScript('search','result');
 		OC_Util::addStyle( "styles" );