There are times when you might want to make a field in a list hidden or un-hidden, after you have provisioned it. Here's a script I put together to solve this issue with CSOM. Crazy that we have to modify the schema using a string replace to achieve this considering there is a Field.Hidden property. For some reason they decided to make that property read only.

Update: 9 April 2018 - I found that sometimes the schema doesn't contain a Hidden attribute so have updated the script to add it in that case. This works with the Title field now, so you can hide it if needed.

#PowerShell

# Hide or show a field in a list
# Author: Tim Wheeler 2018 http://blog.timwheeler.io
# Note: Download appropriate CSOM version from Nuget
param(
    $siteUrl = $("https://somesite"),
    $spOnline = $($false),
    $username = $($null),
    $password = $($null),
    $listName = $("Some List"),
    $pathToCSOM = $($PSScriptRoot + "\..\CSOM\15"),
    $fieldInternalName = "MyFieldInternalName",
    $hide = $false 
)

Add-Type -LiteralPath ([IO.Path]::Combine($pathToCSOM, "Microsoft.SharePoint.Client.dll")) -PassThru | out-null #Load the CSOM assembly  
function Get-SPOnlineContext($url, $username,$password)  
{
    if($password -eq $null )
    {
        $psCredential = Get-Credential $username
        $username  = $psCredential.GetNetworkCredential().UserName
        $password = $psCredential.GetNetworkCredential().Password
    }
    $securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
    $context = New-Object -TypeName Microsoft.SharePoint.Client.ClientContext -ArgumentList ($url)
    $context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username,$securePassword) -ErrorAction:Stop
    return $context
}
function Get-SP2013Context($url, $username, $password)  
{
    $context = New-Object -TypeName Microsoft.SharePoint.Client.ClientContext -ArgumentList ($url)
    if(-not ([string]::IsNullOrEmpty($username) -and [string]::IsNullOrEmpty($password)))
    {
        $securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
        $context.Credentials = New-Object System.Net.NetworkCredential($username, $securePassword) -ErrorAction:Stop
    }
    return $context
}


try {  
    $context = $null
    if($spOnline)
    {
        $context = Get-SPOnlineContext $siteUrl $username $password 
    }
    else {
        $context = Get-SP2013Context $siteUrl $username $password 
    }
    $web = $context.Web
    $context.Load($web)
    $context.ExecuteQuery()
    [Microsoft.SharePoint.Client.List] $list = $web.Lists.GetByTitle($listName)
    $field = $list.Fields.GetByInternalNameOrTitle($fieldInternalName)
    $context.Load($field)
    $context.ExecuteQuery()

    $schema = $field.SchemaXml
    Write-Host "Old schema: $schema"
    if($schema -match "Hidden=") 
    {
        if($hide)
        {
            $schema = $schema.Replace('Hidden="FALSE"', 'Hidden="TRUE"')
        }
        else 
        {
            $schema = $schema.Replace('Hidden="TRUE"', 'Hidden="FALSE"')
        }
    }
    else {
        if($hide) 
        {
            $schema = $schema.Replace(' />', ' Hidden="TRUE" />')
        }
        else 
        {
           $schema = $schema.Replace(' />', ' Hidden="FALSE" />')
        }
    }
    Write-Host "New schema: $schema"
    $field.SchemaXml = $schema
    $field.Update()
    $list.Update()
    $context.ExecuteQuery()
}
finally {  
    if ($context -ne $null) {
        $context.Dispose()
        $context = $null
    }
}