Skip to content

Commit e87c7ff

Browse files
committed
fix: set HOME to app dataDir parent, write ~/.nullclaw/config.json on startup, grant mic permission
1 parent 1b6a84d commit e87c7ff

3 files changed

Lines changed: 38 additions & 6 deletions

File tree

app/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ android {
3535
viewBinding = true
3636
}
3737

38+
packaging {
39+
jniLibs {
40+
useLegacyPackaging = true
41+
}
42+
}
43+
3844
// Package the nullclaw binary from assets
3945
sourceSets {
4046
getByName("main") {

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
android:allowBackup="false"
1414
android:label="ClawWatch"
1515
android:icon="@mipmap/ic_launcher"
16+
android:extractNativeLibs="true"
1617
android:theme="@style/Theme.AppCompat.NoActionBar">
1718

1819
<activity

app/src/main/java/com/thinkoff/clawwatch/ClawRunner.kt

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,44 @@ class ClawRunner(private val context: Context) {
2525
}
2626

2727
private val filesDir get() = context.filesDir
28-
// Android W^X: execute from nativeLibraryDir (always executable), config in filesDir
28+
// HOME = parent of filesDir so ~/.nullclaw/config.json lands at dataDir/.nullclaw/config.json
29+
private val homeDir get() = context.filesDir.parentFile!!
2930
private val binaryFile get() = File(context.applicationInfo.nativeLibraryDir, "libnullclaw.so")
3031
private val configFile get() = File(filesDir, CONFIG_NAME)
32+
private val nullclawConfigFile get() = File(homeDir, ".nullclaw/config.json")
3133

32-
/** Copy config from assets on first run only. Binary lives in nativeLibraryDir. */
34+
/** Write NullClaw home config with API key and model, copy app config from assets. */
3335
suspend fun ensureInstalled() = withContext(Dispatchers.IO) {
34-
// Binary is in nativeLibraryDir (always executable — no W^X issue)
3536
Log.i(TAG, "NullClaw binary at ${binaryFile.absolutePath} (exists: ${binaryFile.exists()})")
36-
// Only copy config if it doesn't exist — preserve any on-device changes
37+
// Only copy app config if it doesn't exist
3738
if (!configFile.exists()) {
3839
context.assets.open(CONFIG_NAME).use { it.copyTo(configFile.outputStream()) }
3940
}
40-
Log.i(TAG, "NullClaw ready")
41+
// Always write ~/.nullclaw/config.json with API key + model so NullClaw is configured
42+
writeNullclawHomeConfig()
43+
Log.i(TAG, "NullClaw ready, home=${homeDir.absolutePath}")
44+
}
45+
46+
/** Write ~/.nullclaw/config.json so NullClaw knows the model + provider. */
47+
private fun writeNullclawHomeConfig() {
48+
val apiKey = getApiKey() ?: return
49+
nullclawConfigFile.parentFile?.mkdirs()
50+
nullclawConfigFile.writeText("""
51+
{
52+
"agents": {
53+
"defaults": {
54+
"model": {
55+
"primary": "claude-opus-4-6"
56+
}
57+
}
58+
},
59+
"providers": {
60+
"anthropic": {
61+
"api_key": "$apiKey"
62+
}
63+
}
64+
}
65+
""".trimIndent())
4166
}
4267

4368
fun saveApiKey(key: String) {
@@ -73,7 +98,7 @@ class ClawRunner(private val context: Context) {
7398
.apply {
7499
environment().apply {
75100
put("ANTHROPIC_API_KEY", apiKey)
76-
put("HOME", filesDir.absolutePath)
101+
put("HOME", homeDir.absolutePath)
77102
put("PATH", "/system/bin:/system/xbin")
78103
}
79104
}

0 commit comments

Comments
 (0)