Adding tasks to obsidian via a network share
Home Assistant General
Overview
This guide walks through setting up Home Assistant to create Obsidian task notes via voice command using the built-in Assist voice assistant. When you say “Add task [title] about [body]”, a markdown file is written directly into your Obsidian vault, which is kept ion another server via a SMB share.
What you will need
- Home Assistant (VM or install) with the SSH & Web Terminal add-on
- A network share from your Syncthing LXC already mounted in Home Assistant
- The Obsidian Tasks or Tasknotes plugin configured to use frontmatter properties
- Assist enabled in Home Assistant
Architecture
The flow works as follows:
- You speak a command via Assist
- A conversation trigger fires an automation, passing the title and body as slots
- The automation calls an HA script
- The script runs a shell command which executes a bash script on the HA host
- The bash script writes a formatted markdown file to the network share
- Syncthing picks up the new file and syncs it to your Obsidian vault
Step 1 — Mount the Syncthing folder as a network share in Home Assistant
If you have not already done this, add the Syncthing LXC folder as a network share (SMB or NFS) and mount it in Home Assistant via Settings ? System ? Storage ? Add network storage. Give it a recognisable name such as obsidian-tasks.
Once mounted, confirm the path it appears at. Open the HA terminal (SSH add-on) and run:
df -h # or mount | grep -i cifs mount | grep -i nfs
Note the mount path — it will typically be something like /media/obsidian-tasks. You will need this in the steps below.
Step 2 — Update configuration.yaml
Home Assistant requires external paths to be explicitly allowlisted before scripts can write to them. Add the following to your configuration.yaml, replacing the path with your actual mount point:
homeassistant:
allowlist_external_dirs:
- /media/obsidian-tasks
shell_command:
write_obsidian_task: bash /config/scripts/create_task.sh '{{ title }}' '{{ body }}' '{{ subfolder }}'
Restart Home Assistant after saving this file.
Step 3 — Create the bash script
This script does the actual work of generating the markdown file with the correct frontmatter for the Tasknotes plugin.
In the HA terminal, create the scripts folder and the file:
mkdir -p /config/scripts nano /config/scripts/create_task.sh
Paste the following content, replacing /media/obsidian-tasks with your actual share path:
#!/bin/bash
TITLE="$1"
BODY="$2"
SUBFOLDER="${3:-Tasks}"
DEST="/media/obsidian-tasks/${SUBFOLDER}"
mkdir -p "$DEST"
# Sanitise the title for use as a filename
FILENAME="$(echo "$TITLE" | tr ' ' '-' | tr -cd '[:alnum:]-_').md"
# Date/time values
CREATED="$(date +"%Y-%m-%dT%H:%M")"
DATE_MODIFIED="$(date +"%Y-%m-%dT%H:%M:%S.000")$(date +"%z" | sed 's/\(..\)$/:\1/')"
SCHEDULED="$(date +"%Y-%m-%d")"
DUE="$(date -d "@$(($(date +%s) + 259200))" +"%Y-%m-%d")"
{
printf -- "---\n"
printf "created: %s\n" "$CREATED"
printf "tags:\n"
printf " - task\n"
printf "dateModified: %s\n" "$DATE_MODIFIED"
printf "title: %s\n" "$TITLE"
printf "status: open\n"
printf "priority: normal\n"
printf "due: %s\n" "$DUE"
printf "scheduled: %s\n" "$SCHEDULED"
printf -- "---\n"
printf "\n"
printf "%s\n" "$BODY"
} > "${DEST}/${FILENAME}"
echo "Created: ${DEST}/${FILENAME}"
Save the file (Ctrl+X, then Y, then Enter), then make it executable:
chmod +x /config/scripts/create_task.sh
Notes on the date fields
- created — timestamp when the file is written
- dateModified — same timestamp, formatted with timezone offset and milliseconds to match the Tasknotes plugin format
- scheduled — set to today
- due — set to 3 days from today (259200 seconds). The arithmetic method is used instead of
date -d "+3 days"because the HA container uses BusyBox date which does not support that flag
Test the script manually
Before wiring it into Home Assistant, confirm it works from the terminal:
bash /config/scripts/create_task.sh "Test Task" "This is the body text" "Tasks"
Check your Obsidian vault to confirm the file appears with the correct frontmatter.
Step 4 — Create the Home Assistant script
This script is the callable action that automations and voice commands will trigger. Add it via Settings ? Automations & Scenes ? Scripts ? Add Script ? Edit in YAML, or add it directly to scripts.yaml:
alias: Create Obsidian Task
description: Write a markdown task into the Obsidian vault via Syncthing
icon: mdi:note-plus-outline
fields:
title:
description: Task title (becomes the filename)
required: true
example: "Fix bathroom tap"
selector:
text:
body:
description: Task body / details
required: false
default: ""
example: "Dripping since Monday, check washer first"
selector:
text:
multiline: true
subfolder:
description: Subfolder within the vault
required: false
default: "HomeAssistant"
example: "HomeAssistant, Family, Projects"
selector:
text:
sequence:
- action: shell_command.write_obsidian_task
data:
title: "{{ title }}"
body: "{{ body }}"
subfolder: "{{ subfolder }}"
response_variable: result
- if: "{{ result['returncode'] != 0 }}"
then:
- action: persistent_notification.create
data:
title: "Obsidian task failed"
message: "{{ result['stderr'] }}"
If the shell command fails for any reason, a persistent notification will appear in your HA dashboard with the error detail.
You can test this script directly via Developer Tools ? Actions, searching for script.create_obsidian_task and filling in the fields.
Step 5 — Create the voice automation
This automation listens for spoken commands via Assist and triggers the script. Add it via Settings ? Automations & Scenes ? Automations ? Add Automation ? Edit in YAML:
alias: Voice - Create Obsidian Task
description: Creates an Obsidian task via Assist voice command
triggers:
- trigger: conversation
command:
- "add task {title} about {body}"
- "create task {title} about {body}"
- "new task {title} about {body}"
actions:
- action: script.create_obsidian_task
data:
title: "{{ trigger.slots.title }}"
body: "{{ trigger.slots.body }}"
subfolder: "HomeAssistant"
- stop: "Task created"
response_variable:
speech: "Task {{ trigger.slots.title }} has been created"
The {title} and {body} placeholders in the trigger commands act as named slots automatically — no separate custom sentence file is needed. The stop action at the end sends a spoken confirmation back through whichever Assist pipeline triggered the command.
Step 6 — Test the voice command
Before testing with a physical voice device, use the Assist chat interface in Home Assistant:
- Click the Assist icon in the HA toolbar (the chat bubble)
- Type:
add task Fix the boiler about needs a new pressure valve - Confirm you receive the spoken/text confirmation response
- Check your Obsidian vault to confirm the file has been created with the correct frontmatter
If using a physical satellite device (such as a Wyoming-protocol voice device), the confirmation will be spoken back through that device.
Troubleshooting
returncode 127 — script not found
The bash script does not exist at /config/scripts/create_task.sh or is not executable. Re-run the chmod +x command and verify the file exists with ls -la /config/scripts/.
returncode 1 — permission denied writing to share
The HA process does not have write permission to the network share mount point. Check the share permissions on the Syncthing LXC side and ensure the user account used for the SMB/NFS mount has write access.
File created but frontmatter fields missing in Tasknotes
Check that the frontmatter field names in the script (status, priority, due, scheduled, dateModified) exactly match the field names configured in your Tasknotes plugin settings. These are configurable and may differ from the defaults shown here.
Voice command not recognised
Ensure the automation is enabled and that Assist is using a pipeline with speech-to-text configured. Test by typing the command in the Assist chat interface first to confirm the trigger is matching before involving speech recognition.
Due date is blank
The HA container uses BusyBox date which does not support date -d "+3 days". Confirm the script is using the arithmetic method shown above (date -d "@$(($(date +%s) + 259200))").
Customisation
Changing the default due date offset
To change the due date from 3 days to a different number, replace 259200 in the script with the number of seconds you want. Common values:
- 1 day —
86400 - 3 days —
259200 - 7 days —
604800 - 14 days —
1209600
Adding more voice trigger phrases
Add additional entries under the command list in the automation trigger. The slot names {title} and {body} must remain consistent:
command:
- "add task {title} about {body}"
- "create task {title} about {body}"
- "new task {title} about {body}"
- "remind me to {title} because {body}"
Routing to different subfolders by voice
To support dynamic subfolder selection by voice, extend the trigger and pass the slot through:
command:
- "add {subfolder} task {title} about {body}"
actions:
- action: script.create_obsidian_task
data:
title: "{{ trigger.slots.title }}"
body: "{{ trigger.slots.body }}"
subfolder: "{{ trigger.slots.subfolder }}"
You would then say: “Add HomeAssistant task Fix the boiler about needs a new pressure valve”